Compare commits

..

2 Commits

Author SHA1 Message Date
MI15\Win
cec87b24f2 v2.0.33-20230802 2023-08-02 15:57:19 +08:00
MI15\Win
1d379543f5 v2.0.32-20230727 2023-07-28 00:19:25 +08:00
37 changed files with 1974 additions and 106 deletions

View File

@@ -74,7 +74,7 @@ if(empty($c) || $c == 'index'){
require "./system/login.php";//登陆
}elseif(in_array($c,['admin','click','api','ico','icon','verify'])){
require "./system/{$c}.php";
}elseif(in_array($c,['apply','guestbook'])){
}elseif(in_array($c,['apply','guestbook','article'])){
if($global_config['Maintenance'] != 0){Amsg(-1,'网站正在进行维护,请稍后再试!');}
require "./system/expand/{$c}.php";
}else{

32
system/MySQL/20230723.php Normal file
View File

@@ -0,0 +1,32 @@
<?php if(!defined('DIR')){header('HTTP/1.1 404 Not Found');header("status: 404 Not Found");exit;}
$sql =<<<EOF
CREATE TABLE IF NOT EXISTS `user_article_list` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`uid` varchar(32) NOT NULL COMMENT '用户id',
`title` text NOT NULL COMMENT '标题',
`category` int(10) UNSIGNED NOT NULL COMMENT '分类id',
`state` int(10) UNSIGNED NOT NULL COMMENT '状态',
`password` text NOT NULL COMMENT '访问密码',
`top` int(10) UNSIGNED NOT NULL COMMENT '置顶',
`add_time` int(10) UNSIGNED NOT NULL COMMENT '创建时间',
`up_time` int(10) UNSIGNED NOT NULL COMMENT '修改时间',
`browse_count` int(10) UNSIGNED NOT NULL COMMENT '浏览次数',
`summary` text NOT NULL COMMENT '摘要',
`content` text NOT NULL COMMENT '内容',
`cover` text NOT NULL COMMENT '封面',
`extend` text NOT NULL COMMENT '扩展',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
ALTER TABLE `user_count` ADD `e` TEXT NOT NULL DEFAULT '' COMMENT '扩展';
INSERT INTO `purview_list` (`code`, `name`, `description`) VALUES
('article', '文章管理', '允许使用文章管理功能'),
('article_image', '文章图片', '允许在文章编辑器上传图片');
EOF;
if(exe_sql($sql)){
insert_db('updatadb_logs',['file_name'=>$file_name,'update_time'=>time(),'status'=>'TRUE','extra'=>'']);
}else{
msg(-1,'数据库更新失败');
}

View File

@@ -26,7 +26,8 @@ CREATE TABLE IF NOT EXISTS `user_count` (
`uid` int(10) UNSIGNED NOT NULL COMMENT '用户ID',
`k` varchar(32) NOT NULL COMMENT '',
`v` bigint(10) UNSIGNED DEFAULT '0' COMMENT '',
`t` varchar(32) NOT NULL COMMENT '类型'
`t` varchar(32) NOT NULL COMMENT '类型',
`e` text NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@@ -46,7 +47,8 @@ INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALU
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230420.php', '1681977368', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230518.php', '1684393068', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230522.php', '1684762253', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230715.php', '1684762253', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230715.php', '1689427853', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230723.php', '1690119053', 'TRUE', '');
-- 创建用户表
DROP TABLE IF EXISTS `global_user`;
@@ -195,7 +197,9 @@ INSERT INTO `purview_list` (`code`, `name`, `description`) VALUES
('link_extend', '链接扩展', '允许使用链接扩展字段'),
('theme_in', '主题设置', '后台显示主题设置菜单'),
('theme_set', '主题配置', '允许自定义主题配置'),
('icon_pull', '图标拉取', '允许用户拉取链接图标');
('icon_pull', '图标拉取', '允许用户拉取链接图标'),
('article', '文章管理', '允许使用文章管理功能'),
('article_image', '文章图片', '允许在文章编辑器上传图片');
-- 注册码列表
DROP TABLE IF EXISTS `regcode_list`;
@@ -274,4 +278,25 @@ CREATE TABLE IF NOT EXISTS `global_icon` (
`file_mime` text NOT NULL COMMENT 'MIME类型',
`extend` text NOT NULL COMMENT '预留扩展',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
-- 用户文章列表
CREATE TABLE IF NOT EXISTS `user_article_list` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`uid` varchar(32) NOT NULL COMMENT '用户id',
`title` text NOT NULL COMMENT '标题',
`category` int(10) UNSIGNED NOT NULL COMMENT '分类id',
`state` int(10) UNSIGNED NOT NULL COMMENT '状态',
`password` text NOT NULL COMMENT '访问密码',
`top` int(10) UNSIGNED NOT NULL COMMENT '置顶',
`add_time` int(10) UNSIGNED NOT NULL COMMENT '创建时间',
`up_time` int(10) UNSIGNED NOT NULL COMMENT '修改时间',
`browse_count` int(10) UNSIGNED NOT NULL COMMENT '浏览次数',
`summary` text NOT NULL COMMENT '摘要',
`content` text NOT NULL COMMENT '内容',
`cover` text NOT NULL COMMENT '封面',
`extend` text NOT NULL COMMENT '扩展',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

View File

@@ -0,0 +1,31 @@
<?php if(!defined('DIR')){header('HTTP/1.1 404 Not Found');header("status: 404 Not Found");exit;}
$sql =<<<EOF
CREATE TABLE "user_article_list" (
"id" integer PRIMARY KEY AUTOINCREMENT,
"uid" integer(10) NOT NULL,
"title" TEXT NOT NULL DEFAULT "",
"category" integer NOT NULL,
"state" integer(1) DEFAULT 0,
"password" TEXT NOT NULL DEFAULT "",
"top" integer(10),
"add_time" integer(10),
"up_time" integer(10),
"browse_count" integer DEFAULT 0,
"summary" TEXT,
"content" TEXT,
"cover" TEXT,
"extend" TEXT,
CONSTRAINT "id" UNIQUE ("id" ASC)
);
ALTER TABLE user_count ADD e TEXT NOT NULL DEFAULT "";
INSERT INTO `purview_list` (`code`, `name`, `description`) VALUES
('article', '文章管理', '允许使用文章管理功能'),
('article_image', '文章图片', '允许在文章编辑器上传图片');
EOF;
if(exe_sql($sql)){
insert_db('updatadb_logs',['file_name'=>$file_name,'update_time'=>time(),'status'=>'TRUE','extra'=>'']);
}else{
msg(-1,'数据库更新失败');
}

View File

@@ -23,7 +23,8 @@ CREATE TABLE IF NOT EXISTS "user_count" (
"uid" integer(10) NOT NULL,
"k" text(32) NOT NULL DEFAULT "",
"v" integer(10) NOT NULL DEFAULT 0,
"t" text(32) NOT NULL DEFAULT ""
"t" text(32) NOT NULL DEFAULT "",
"e" text NOT NULL DEFAULT ""
);
-- 数据库升级记录
@@ -38,7 +39,9 @@ CREATE TABLE IF NOT EXISTS "updatadb_logs" (
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230417.php', '1681719049', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230420.php', '1681977368', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230522.php', '1684762253', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230715.php', '1684762253', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230715.php', '1689427853', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230723.php', '1690119053', 'TRUE', '');
-- 创建用户表
CREATE TABLE IF NOT EXISTS "global_user" (
@@ -167,7 +170,9 @@ INSERT INTO `purview_list` (`code`, `name`, `description`) VALUES
('link_extend', '链接扩展', '允许使用链接扩展字段'),
('theme_in', '主题设置', '后台显示主题设置菜单'),
('theme_set', '主题配置', '允许自定义主题配置'),
('icon_pull', '图标拉取', '允许用户拉取链接图标');
('icon_pull', '图标拉取', '允许用户拉取链接图标'),
('article', '文章管理', '允许使用文章管理功能'),
('article_image', '文章图片', '允许在文章编辑器上传图片');
-- 注册码列表
CREATE TABLE IF NOT EXISTS "regcode_list" (
@@ -241,3 +246,21 @@ CREATE TABLE IF NOT EXISTS "global_icon" (
CONSTRAINT "id" UNIQUE ("id" ASC)
);
-- 用户文章列表
CREATE TABLE "user_article_list" (
"id" integer PRIMARY KEY AUTOINCREMENT,
"uid" integer(10) NOT NULL,
"title" TEXT NOT NULL DEFAULT "",
"category" integer NOT NULL,
"state" integer(1) DEFAULT 0,
"password" TEXT NOT NULL DEFAULT "",
"top" integer(10),
"add_time" integer(10),
"up_time" integer(10),
"browse_count" integer DEFAULT 0,
"summary" TEXT,
"content" TEXT,
"cover" TEXT,
"extend" TEXT,
CONSTRAINT "id" UNIQUE ("id" ASC)
);

View File

@@ -64,7 +64,7 @@ if($page == 'config_home'){
$theme_config = empty($theme_config['config']) ? []:$theme_config['config'];
//读取用户主题配置
if(!in_array($_GET['fn'],['home','login','register','transit','guide'])){
if(!in_array($_GET['fn'],['home','login','register','transit','guide','article'])){
msg(-1,"参数错误");
}
$theme_config_db = get_db('user_config','v',['t'=>'theme_'.$_GET['fn'],'k'=>$theme,'uid'=>UID]);
@@ -83,7 +83,7 @@ if($page == 'config_home'){
}
//主题设置页面
if( $page == 'theme_home' || $page == 'theme_login' || $page == 'theme_transit' || $page == 'theme_register' || $page == 'theme_guide') {
if( $page == 'theme_home' || $page == 'theme_login' || $page == 'theme_transit' || $page == 'theme_register' || $page == 'theme_guide' || $page == 'theme_article') {
if(!check_purview('theme_in',1)){
require(DIR.'/templates/admin/page/404.php');
exit;
@@ -208,7 +208,9 @@ if ($page == 'menu') {
if($global_config['guestbook'] == 1 && check_purview('guestbook',1)){
array_push($extend,['title'=>'留言管理','href'=>'expand/guestbook-admin','icon'=>'fa fa-commenting-o']);
}
if($global_config['article'] == 1 && check_purview('article',1)){
array_push($extend,['title'=>'文章管理','href'=>'expand/article-list','icon'=>'fa fa-file-text-o']);
}
if(!empty($extend)){
$extend = ['title'=>'扩展功能','icon'=>'fa fa-folder-open-o','href'=>'','child'=> $extend];
array_push($menu,$extend);
@@ -242,6 +244,13 @@ if(empty($page)){
exit;
}
// 插件编辑链接跳转
if($page === 'edit_link' && !empty($_GET['id'])){
header("HTTP/1.1 302 Moved Permanently");
header("Location: ./index.php?c=admin&page=link_edit&u=".U."&id=".$_GET['id']);
exit;
}
//页面文件不存在时载入404
if(!empty($page)){
if(!is_file(DIR.'/templates/admin/page/'.$page.'.php')){

View File

@@ -4,51 +4,48 @@ header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Access-Control-Allow-Private-Network,Content-Type, AccessToken, X-CSRF-Token, Authorization, Token,X-Token,X-Cid");
AccessControl();
//鉴权验证 Cookie验证通过,验证二级密码,Cookie验证失败时尝试验证token
if(!empty(trim($_REQUEST['token']))){ $_COOKIE = []; } //兼容浏览器插件,避免干扰
//获取请求方法
$method = htmlspecialchars(trim($_GET['method']),ENT_QUOTES);
$LoginConfig = unserialize($USER_DB['LoginConfig']);
$api_model = $LoginConfig['api_model']; //API模式
if(!is_login()){
//没登录,根据API模式来限制
$api_model = $LoginConfig['api_model']; //API模式
$token = trim($_REQUEST['token']); //尝试获取令牌
if( empty($USER_DB['Token']) && $api_model != 'compatible+open' ){
Amsg(-1,'未设置token');
//没登录,尝试验证token
if( empty($USER_DB['Token']) ){
msg(-1,'鉴权失败:未登录且未设置token');
}
//获取请求token
$token = trim($_REQUEST['token']);
if(empty($token)){
if($api_model != 'compatible+open'){
Amsg(-1,'非开放模式,token不能为空!');
}
if(in_array($method,['link_list','get_a_link','q_category_link','category_list','get_a_category','check_login'])){
define('Access_Type','open'); //数据访问类型:仅开放
require 'api_compatible.php';
exit;
}else{
Amsg(-1,'token为空时不允许访问此接口');
}
msg(-1,'鉴权失败:未登录且请求未携带token');
}else{
if($token === $USER_DB['Token']){
define('Access_Type','all');
//验证通过
}else{
Amsg(-1,'token验证失败');
msg(-1,'鉴权失败:未登录且token错误');
}
}
if($api_model === 'compatible' || $api_model ==='compatible+open'){
require 'api_compatible.php';
}
//Cookie登录验证OK,验证二级密码
}elseif(Check_Password2($LoginConfig)){
// Cookie 二级密码验证成功(未设置时也认为成功)
}else{
msg(-1,'请先验证二级密码!');
}
//是否加载扩展API
//扩展API
if($global_config['api_extend'] == 1 && is_file('./system/api_extend.php')){
require './system/api_extend.php';
}
//兼容API
$compatible_list = ['add_link','edit_link','del_link','link_list','get_a_link','q_category_link','category_list','get_a_category','add_category','edit_category','app_info','check_login','global_search'];
if(in_array($api_model,['compatible','compatible+open']) && in_array($method,$compatible_list)){
require 'api_compatible.php';
exit;
}
//站长相关方法名
$root = ['write_subscribe','write_sys_settings','write_default_settings','read_user_list','write_user_info','read_purview_list','read_users_list','write_users','read_regcode_list','write_regcode','other_upsys','read_log','other_root'];
if(in_array($method,$root)){
@@ -62,9 +59,7 @@ if(in_array($method,$root)){
if ( preg_match("/^read_|^write_|^other_/",$method) && function_exists($method) ) {
$method();
}else{
if($api_model == 'security'){
Amsg(-1,'方法未找到 >> '.$method);
}
Amsg(-1,'方法未找到 >> '.$method);
}
//读分类列表
@@ -462,7 +457,10 @@ function write_link(){
@unlink($_FILES["file"]["tmp_name"]);
msg(-1,'文件格式不被支持!');
}
//限制文件大小
if(filesize($_FILES["file"]["tmp_name"]) > 1 * 1024 * 1024){
msg(-1,'文件大小超限');
}
session_start();
$sid = $_POST['page_sid'];
//添加链接
@@ -516,7 +514,39 @@ function write_link(){
}else{
msg(-1,'参数错误');
}
//扩展上传图片
}elseif($_GET['type'] == 'extend_up_img'){
//权限检测
if(!check_purview('Upload_icon',1)){
msg(-1,'您的用户组无权限上传图片');
}elseif(empty($_FILES["file"]) || $_FILES["file"]["error"] > 0){
msg(-1,'文件上传失败');
}
//取后缀并判断是否支持
$suffix = strtolower(end(explode('.',$_FILES["file"]["name"])));
if(!preg_match('/^(jpg|jpeg|png|ico|bmp|svg)$/',$suffix)){
@unlink($_FILES["file"]["tmp_name"]);
msg(-1,'文件格式不被支持!');
}
//限制文件大小
if(filesize($_FILES["file"]["tmp_name"]) > 1 * 1024 * 1024){
msg(-1,'文件大小超限');
}
//文件临时路径
$path = DIR . "/data/user/{$u}/upload";
//检测目录,不存在则创建!
if(!Check_Path($path)){
msg(-1,'创建upload目录失败,请检查权限');
}
$tmp_name = 'LE_'.uniqid().'.'.$suffix;
//移动文件
if(!move_uploaded_file($_FILES["file"]["tmp_name"],"{$path}/{$tmp_name}")) {
msg(-1,'上传失败,请检查目录权限');
}else{
msgA(['code'=>1,'msg'=>'上传成功','url'=>"./data/user/".U.'/upload/'.$tmp_name]);
}
//删除图标
}elseif($_GET['type'] === 'del_images'){
session_start();
@@ -625,7 +655,7 @@ function write_link(){
unset($data['keywords']);
}
//更新数据
update_db('user_links',$data,['uid'=>UID,'lid'=>intval($_POST['lid']) ]);
update_db('user_links',$data,['uid'=>UID,'lid'=>$lid ]);
msgA(['code'=>1,'msg'=>'修改成功','icon' => $icon]);
//删除
}elseif($_GET['type'] === 'del'){
@@ -875,7 +905,7 @@ function write_link(){
if(empty($data['name']) || check_xss($data['name']) || !preg_match('/^[A-Za-z0-9]{3,18}$/',$data['name'])){
msgA( ['code' => -1,'msg' => '字段名错误,请输入长度3-18的字母/数字'] );
}
if(!in_array($data['type'],['text','textarea'])){
if(!in_array($data['type'],['text','textarea','up_img'])){
msgA( ['code' => -1,'msg' => '类型错误'] );
}
}
@@ -889,7 +919,7 @@ function write_link(){
$datas = [];
foreach ($lists as $key => $data ){
array_push($datas,['title'=>$data['title'],'name'=>$data['name'],'weight'=>$data['weight'],'type'=>$data['type'],'default'=> "{$data['default']}"]);
array_push($datas,['title'=>$data['title'],'name'=>$data['name'],'weight'=>$data['weight'],'type'=>$data['type'],'default'=> "{$data['default']}",'tip'=>$data['tip']]);
}
//根据序号排序
usort($datas, function($a, $b) {
@@ -917,7 +947,7 @@ function write_security_setting(){
'HttpOnly'=>['int'=>true,'min'=>0,'max'=>1,'msg'=>'HttpOnly参数错误'],
'KeySecurity'=>['int'=>true,'min'=>0,'max'=>2,'msg'=>'Key安全参数错误'],
'KeyClear'=>['int'=>true,'min'=>1,'max'=>60,'msg'=>'Key清理参数错误'],
'api_model'=>['v'=>['security','compatible','compatible+open'],'msg'=>'API模式参数错误'],
'api_model'=>['v'=>['security','compatible'],'msg'=>'API模式参数错误'],
'login_page'=>['v'=>['admin','index','auto'],'msg'=>'登录成功参数错误'],
'Password2'=>['empty'=>true]
];
@@ -1272,7 +1302,7 @@ function other_testing_link(){
//主题下载/更新/删除
function write_theme(){
global $global_config;
$fn = $_POST['fn'];if($_GET['type'] != 'config' && !in_array($fn,['home','login','transit','register','guide'])){msg(-1,'fn参数错误');}
$fn = $_POST['fn'];if($_GET['type'] != 'config' && !in_array($fn,['home','login','transit','register','guide','article'])){msg(-1,'fn参数错误');}
if($_GET['type'] == 'download'){
is_root();
if($global_config['offline']){msg(-1,"离线模式禁止下载主题!");} //离线模式
@@ -1393,6 +1423,8 @@ function write_theme(){
$s_templates['login'] = $name;
}elseif($fn == 'transit'){
$s_templates['transit'] = $name;
}elseif($fn == 'article'){
$s_templates['article'] = $name;
}elseif($fn == 'register'){
$global_templates['register'] = $name;
update_db('global_config',['v'=>$global_templates],['k'=>'s_templates'],[1,'注册模板设置成功']);
@@ -1417,7 +1449,7 @@ function write_theme(){
msg(-1,"获取模板类型错误");
}
$fn = empty($GET['fn']) ? $_GET['template_type'] : $GET['fn'];
if(!in_array($fn,['home','login','register','transit','guide'])){
if(!in_array($fn,['home','login','register','transit','guide','article'])){
msg(-1,"参数错误");
}
//0420 END
@@ -1617,6 +1649,8 @@ function read_data(){
curl_setopt($ch, CURLOPT_URL, $_POST['url']);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$start = microtime(true);
$response = curl_exec($ch);
$end = microtime(true);
@@ -1735,6 +1769,17 @@ function other_local_backup(){
require DIR . '/system/UseFew/local_backup.php';
exit;
}
//读文章
function read_article(){
require DIR . '/system/api_article.php';
exit;
}
//写文章
function write_article(){
require DIR . '/system/api_article.php';
exit;
}
//获取链接信息
function other_get_link_info(){
global $global_config;

222
system/api_article.php Normal file
View File

@@ -0,0 +1,222 @@
<?php if(!defined('DIR')){header('HTTP/1.1 404 Not Found');header("status: 404 Not Found");exit;}
$type = htmlspecialchars(trim($_GET['type']),ENT_QUOTES);
if (function_exists($type) ) {
if($GLOBALS['global_config']['article'] != 1 || !check_purview('article',1)){
msg(-1,'无权限');
}
$type();
}else{
Amsg(-1,'请求类型错误 >> '.$type);
}
//上传图片
function uploadImage(){
global $u;
//权限检测
if(!check_purview('article_image',1)){
msgA(['errno'=>-1,'message'=>'您的用户组无权限上传图片']);
}elseif(empty($_FILES["file"]) || $_FILES["file"]["error"] > 0){
msgA(['errno'=>-1,'message'=>'文件上传失败']);
}
//取后缀并判断是否支持
$suffix = strtolower(end(explode('.',$_FILES["file"]["name"])));
if(!preg_match('/^(jpg|png|gif|bmp|jpeg|svg|webp)$/',$suffix)){
@unlink($_FILES["file"]["tmp_name"]);
msgA(['errno'=>-1,'message'=>'文件格式不被支持']);
}
//限制文件大小
if(filesize($_FILES["file"]["tmp_name"]) > 5 * 1024 * 1024){
msgA(['errno'=>-1,'message'=>'文件大小超限']);
}
//文件临时路径
$ym = date("Ym");
$path = DIR . "/data/user/{$u}/upload/{$ym}/";
//检测目录,不存在则创建!
if(!Check_Path($path)){
msgA(['errno'=>-1,'message'=>'创建upload目录失败,请检查权限']);
}
$tmp_name = 'AI_'.uniqid().'.'.$suffix;
//移动文件
if(!move_uploaded_file($_FILES["file"]["tmp_name"],"{$path}/{$tmp_name}")) {
msgA(['errno'=>-1,'message'=>'上传失败,请检查目录权限']);
}else{
msgA(['errno'=>0,'data'=>['url'=>"./data/user/{$u}/upload/{$ym}/$tmp_name",'alt'=>$_FILES["file"]["name"],'href'=>''],'message'=>'上传成功']);
}
}
//删除图片
function deleteImage(){
global $u;
if(empty($_POST['path'])){
msg(-1,'请求参数错误');
}
$path = $_POST['path'];
$pattern = "/^\.\/data\/user\/{$u}\/upload\/\d{6}\/AI_[A-Za-z0-9_]+\.(jpg|png|gif|bmp|jpeg|svg|webp)$/i";
if(preg_match($pattern,$path) && is_file($path)){
@unlink($path);
}else{
msg(-1,'请求参数错误');
}
//需考虑编辑文章删除封面时未点击保存的情况
if(is_file($path)){
msg(-1,'删除失败');
}else{
msg(1,'删除成功');
}
}
//上传视频
function uploadVideo(){
msgA(['errno'=>-1,'message'=>'未开放']);
global $u;
//权限检测
if(!check_purview('article_image',1)){
msgA(['errno'=>-1,'message'=>'您的用户组无权限上传视频']);
}elseif(empty($_FILES["file"]) || $_FILES["file"]["error"] > 0){
msgA(['errno'=>-1,'message'=>'文件上传失败']);
}
//取后缀并判断是否支持
$suffix = strtolower(end(explode('.',$_FILES["file"]["name"])));
if(!preg_match('/^(avi|mp4|wma|rmvb|rm|flash|3gp|flv)$/',$suffix)){
@unlink($_FILES["file"]["tmp_name"]);
msgA(['errno'=>-1,'message'=>'文件格式不被支持']);
}
//限制文件大小
if(filesize($_FILES["file"]["tmp_name"]) > 20 * 1024 * 1024){
msgA(['errno'=>-1,'message'=>'文件大小超限']);
}
//文件临时路径
$ym = date("Ym");
$path = DIR . "/data/user/{$u}/upload/{$ym}/";
//检测目录,不存在则创建!
if(!Check_Path($path)){
msgA(['errno'=>-1,'message'=>'创建upload目录失败,请检查权限']);
}
$tmp_name = 'AV_'.uniqid().'.'.$suffix;
//移动文件
if(!move_uploaded_file($_FILES["file"]["tmp_name"],"{$path}/{$tmp_name}")) {
msgA(['errno'=>-1,'message'=>'上传失败,请检查目录权限']);
}else{
msgA(['errno'=>0,'data'=>['url'=>"./data/user/{$u}/upload/{$ym}/$tmp_name",'alt'=>$_FILES["file"]["name"],'href'=>''],'message'=>'上传成功']);
}
}
//获取文章列表
function article_list(){
$where['uid'] = UID;
//分类筛选
if(intval(@$_POST['category']) > 0){
$where['AND']['category'] = intval(@$_POST['category']);
}
//状态筛选
if(intval(@$_POST['state']) > 0){
$where['AND']['state'] = intval(@$_POST['state']);
}
//关键字筛选
$query = $_POST['keyword'];
if(!empty($query)){
$where['AND']['OR'] = ["title[~]" => $query,"summary[~]" => $query,"content[~]" => $query];
}
//统计条数
$count = count_db('user_article_list',$where);
//分页
$page = empty(intval($_REQUEST['page'])) ? 1 : intval($_REQUEST['page']);
$limit = empty(intval($_REQUEST['limit'])) ? 50 : intval($_REQUEST['limit']);
$offset = ($page - 1) * $limit; //起始行号
$where['LIMIT'] = [$offset,$limit];
$datas = select_db('user_article_list',['id','title','category','state','password','top','add_time','up_time','browse_count','summary','cover'],$where);
//查询分类
$categorys = select_db('user_categorys',['cid(id)','name'],['uid'=>UID]);
$categorys = array_column($categorys,'name','id');
//为文章添加分类名称
foreach ($datas as &$data) {
$data['category_name'] = $categorys[$data['category']] ?? 'Null';
}
msgA(['code'=>1,'count'=>$count,'data'=>$datas]);
}
//保存文章
function save_article(){
if(empty($_POST['category']) || !has_db('user_categorys',['uid'=>UID,'cid'=>$_POST['category']])){
msg(-1,'分类不存在');
}
$time = time();
//id为空,添加文章
if(empty($_POST['id'])){
insert_db('user_article_list',[
'uid'=>UID,
'title'=>$_POST['title'],
'category'=>$_POST['category'],
'state'=>$_POST['state'],
'password'=>'',
'top'=>0,
'add_time'=>$time,
'up_time'=>$time,
'browse_count'=>0,
'summary'=>$_POST['summary'],
'content'=>$_POST['content'],
'cover'=>$_POST['cover_url'],
'extend'=>''
],[1,'保存成功']);
//存在id,更新文章数据
}else{
if(!has_db('user_article_list',['uid'=>UID,'id'=>$_POST['id']])){
msg(-1,'文章id错误');
}
update_db('user_article_list',[
'title'=>$_POST['title'],
'category'=>$_POST['category'],
'state'=>$_POST['state'],
'up_time'=>$time,
'summary'=>$_POST['summary'],
'content'=>$_POST['content'],
'cover'=>$_POST['cover_url']
],['uid'=>UID,'id'=>$_POST['id']],[1,'保存成功']);
}
}
//删除文章
function del_article(){
$id = json_decode($_POST['id']);
if(empty($id)) msg(-1,'参数错误');
delete_db('user_article_list',['uid'=>UID,'id'=>$id],[1,'操作成功']);
}
//修改分类
function up_category(){
$id = json_decode($_POST['id']);
if(empty($id)) msg(-1,'参数错误');
if(empty($_POST['category_id']) || !has_db('user_categorys',['uid'=>UID,'cid'=>$_POST['category_id']])){
msg(-1,'分类不存在');
}
update_db('user_article_list',['category'=>$_POST['category_id']],['uid'=>UID,'id'=>$id],[1,'操作成功']);
}
//修改状态
function up_state(){
$id = json_decode($_POST['id']);
if(empty($id)) msg(-1,'参数错误');
if(!in_array($_POST['state_id'],['1','2','3','4'])){
msg(-1,'状态参数错误');
}
update_db('user_article_list',['state'=>$_POST['state_id']],['uid'=>UID,'id'=>$id],[1,'操作成功']);
}
//保存设置 (与站点配置共享)
function save_article_set(){
//检查配置参数
if(!in_array($_POST['visual'],['0','1','2']) || !in_array($_POST['icon'],['0','1','2'])){
msg(-1,'参数错误');
}
//读取站点配置
$s_site = unserialize(get_db('user_config','v',['uid'=>UID,'k'=>'s_site']));
$s_site['article_visual'] = $_POST['visual'];
$s_site['article_icon'] = $_POST['icon'];
update_db("user_config",["v"=>$s_site],["k"=>'s_site',"uid"=>UID],[1,'保存成功']);
}

View File

@@ -1,6 +1,6 @@
<?php if(!defined('DIR')){header('HTTP/1.1 404 Not Found');header("status: 404 Not Found");exit;}
if ( in_array($method,['link_list','get_a_link','q_category_link','category_list','get_a_category','check_login','add_link']) && function_exists($method) ) {
if (function_exists($method)) {
$method();
}else{
Amsg(-1,'方法未找到 >> '.$method);
@@ -42,17 +42,83 @@ function add_link(){
insert_db('user_links',$data);
msgA(['code'=>0,'id'=>$lid]);
}
//编辑链接
function edit_link(){
$lid = intval(@$_POST['id']);
$fid = intval(@$_POST['fid']);
$title = $_POST['title'];
$url = $_POST['url'];
$description = empty($_POST['description']) ? '' : $_POST['description'];
$property = empty($_POST['property']) ? 0 : 1;
//检测链接是否合法
check_link($fid,$title,$url,'');
//描述长度检测
$length_limit = unserialize(get_db("global_config","v",["k"=>"length_limit"]));
if($length_limit['l_desc'] > 0 && strlen($description) > $length_limit['l_desc'] ){
msg(-1,'描述长度不能大于'.$length_limit['l_desc'].'个字节');
}
//关键字长度检测
if($length_limit['l_key'] > 0 && strlen($keywords) > $length_limit['l_key'] ){
msg(-1,'关键字长度不能大于'.$length_limit['l_key'].'个字节');
}
//检查链接是否已存在
if(has_db('user_links',['uid'=>UID ,'lid[!]'=>$lid, "url" => $url])){msg(-1011,'链接已存在!');}
//检查链接ID是否存在
if(!has_db('user_links',['uid'=>UID ,'lid'=>$lid])){msg(-1012,'链接ID不存在!');}
$data = [
'fid' => $fid,
'title' => htmlspecialchars($title,ENT_QUOTES),
'url' => $url,
'description' => htmlspecialchars($description,ENT_QUOTES),
'up_time' => time(),
'property' => $property
];
//更新数据
update_db('user_links',$data,['uid'=>UID,'lid'=>$lid ]);
msgA(['code'=>0,'msg'=>'successful']);
}
//删除链接
function del_link(){
$lid = intval(trim($_REQUEST['id']));
if(empty($lid)){
msg(-1010,'链接ID不能为空');
}
$where['lid'] = $lid;
$where['uid'] = UID;
if(!has_db('user_links',$where)){
msg(-1010,'链接id不存在');
}
delete_db('user_links',$where,[0,'删除成功']);
}
//搜索链接
function global_search(){
$keyword = htmlspecialchars($_REQUEST['keyword']);
if( strlen($keyword) < 2 ) {
msg(-2000,'关键字的长度太短');
}elseif( strlen($keyword) > 32 ) {
msg(-2000,'关键字长度过长');
}
$where['uid'] = UID;
$where['status'] = 1;
$where['AND']['OR'] = ["title[~]" => $keyword,"url[~]" => $keyword, "url_standby[~]" => $keyword,"description[~]" => $keyword];
$where['ORDER'] = ['weight'=>'DESC'];
$field = ['lid(id)','fid','status','property','title','url','url_standby','weight','description','click','add_time','up_time'];
$datas = select_db('user_links',$field,$where);
links_add_category_field($datas); //添加分类信息
msgA(['code'=>0,'msg'=>'获取成功','count'=>count($datas),'data'=>$datas]);
}
//查询链接列表
function link_list(){
$page = empty(intval($_REQUEST['page'])) ? 1 : intval($_REQUEST['page']);
$limit = empty(intval($_REQUEST['limit'])) ? 50 : intval($_REQUEST['limit']);
$offset = ($page - 1) * $limit; //起始行号
$where['uid'] = UID;
$where['AND']['status'] = 1;
if(Access_Type != 'all'){
$where['property'] = 0;
}
$where['status'] = 1;
$count = count_db('user_links',$where); //统计条数
//权重排序(数字小的排前面)
$where['ORDER']['weight'] = 'ASC';
@@ -61,6 +127,7 @@ function link_list(){
$where['LIMIT'] = [$offset,$limit];
//查询
$datas = select_db('user_links',['lid(id)','fid','property','title','url','url_standby','weight','description','icon','click','add_time','up_time'],$where);
links_add_category_field($datas); //添加分类信息
msgA(['code'=>0,'msg'=>'获取成功','count'=>$count,'data'=>$datas]);
}
//查询单个链接
@@ -68,7 +135,6 @@ function get_a_link(){
$lid = intval(trim($_REQUEST['id']));
if(empty($lid)){
msg(-1,'id不能为空');
}
$where['lid'] = $lid;
$where['uid'] = UID;
@@ -76,11 +142,7 @@ function get_a_link(){
if(empty($link_info)){
msgA(['code'=>-1,'msg'=>'没有找到链接信息','data'=>[]]);
}else{
if(Access_Type == 'all' || $link_info['property'] == 0){
msgA(['code'=>0,'data'=>$link_info]);
}else{
msgA(['code'=>-1,'msg'=>'私有链接,无权查看','data'=>[]]);
}
msgA(['code'=>0,'data'=>$link_info]);
}
}
//查询指定分类的链接
@@ -92,9 +154,6 @@ function q_category_link(){
$where['uid'] = UID;
$where['AND']['status'] = 1;
$where['AND']['fid'] = $category_id;
if(Access_Type != 'all'){
$where['property'] = 0;
}
$count = count_db('user_links',$where); //统计条数
//权重排序(数字小的排前面)
@@ -104,17 +163,120 @@ function q_category_link(){
$where['LIMIT'] = [$offset,$limit];
//查询
$datas = select_db('user_links',['lid(id)','fid','property','title','url','url_standby','weight','description','icon','click','add_time','up_time'],$where);
links_add_category_field($datas); //添加分类信息
msgA(['code'=>0,'msg'=>'获取成功','count'=>$count,'data'=>$datas]);
}
//查询分类列表
function category_list(){
$where = ['uid'=>UID,'status'=>1,'ORDER' => ['weight'=>'ASC']];
if(Access_Type != 'all'){
$where['property'] = 0;
}
$datas = select_db('user_categorys',['cid(id)','fid','property','name','add_time','up_time','weight','description','font_icon'],$where);
msgA(['code'=>0,'msg'=>'获取成功','count'=>count($datas),'data'=>$datas ]);
}
//添加分类
function add_category(){
if(empty($_POST['name'])){
msg(-1,'分类名称不能为空');
}elseif(!preg_match('/^(fa fa-|layui-icon layui-icon-)([A-Za-z0-9]|-)+$/',$_POST['font_icon'])){
$_POST['font_icon'] = 'fa fa-star-o';
}
//分类名查重
if(get_db('user_categorys','cid',['uid'=>UID ,"name" => $_POST['name']])){
msg(-1,'分类名称已存在');
}
//父分类不能是二级分类
if(intval($_POST['fid']) !=0 && get_db('user_categorys','fid',['uid'=>UID ,"cid" => intval($_POST['fid']) ]) !=0 ){
msg(-1,'父分类不能是二级分类');
}
//长度检测
$length_limit = unserialize(get_db("global_config","v",["k"=>"length_limit"]));
if($length_limit['c_name'] > 0 && strlen($_POST['name']) > $length_limit['c_name'] ){
msg(-1,'名称长度不能大于'.$length_limit['c_name'].'个字节');
}
if($length_limit['c_desc'] > 0 && strlen($_POST['description']) > $length_limit['c_desc'] ){
msg(-1,'名称长度不能大于'.$length_limit['c_desc'].'个字节');
}
//取最大CID
$cid = get_maxid('category_id');
//插入数据库
insert_db('user_categorys',[
'uid'=>UID,
'cid'=>$cid,
'fid'=>intval($_POST['fid']??'0'),
'pid'=>0,
'status'=>1,
'property'=>intval($_POST['property']??'0'),
'name'=>htmlspecialchars($_POST['name'],ENT_QUOTES),
'add_time'=>time(),
'up_time'=>time(),
'weight'=>$cid,
'description'=>htmlspecialchars($_POST['description'],ENT_QUOTES),
'font_icon'=>$_POST['font_icon'],
'icon'=>''
],[0,'添加成功']
);
}
//编辑分类
function edit_category(){
if(empty($_POST['name'])){
msg(-1,'分类名称不能为空');
}elseif(!preg_match('/^(fa fa-|layui-icon layui-icon-)([A-Za-z0-9]|-)+$/',$_POST['font_icon'])){
$_POST['font_icon'] = 'fa fa-star-o';
}
//父分类不能是自己
if($_POST['id'] == $_POST['fid']){
msg(-1,'父分类不能是自己');
}
//查CID是否存在
if(!get_db('user_categorys','cid',['uid'=>UID ,"cid" => intval($_POST['id'])])){
msg(-1,'分类不存在');
}
//分类名查重(排除自身)
if(get_db('user_categorys','cid',['uid'=>UID,'cid[!]'=>intval($_POST['id']),"name" => $_POST['name']])){
msg(-1,'分类名称已存在');
}
//父分类不能是二级分类
if(intval($_POST['fid']) !=0 && get_db('user_categorys','fid',['uid'=>UID ,"cid" => intval($_POST['fid']) ]) !=0 ){
msg(-1,'父分类不能是二级分类');
}
//分类下存在子分类,禁止修改父分类
if( $_POST['fid']!=0 && count_db('user_categorys',['uid'=>UID,'fid'=>$_POST['id']])>0){
msg(-1,'该分类下已存在子分类!');
}
//查父分类是否存在
if( $_POST['fid'] !=0 && !get_db('user_categorys','cid',['uid'=>UID ,"cid" => intval($_POST['fid'])])){
msg(-1,'父分类不存在');
}
//长度检测
$length_limit = unserialize(get_db("global_config","v",["k"=>"length_limit"]));
if($length_limit['c_name'] > 0 && strlen($_POST['name']) > $length_limit['c_name'] ){
msg(-1,'名称长度不能大于'.$length_limit['c_name'].'个字节');
}
if($length_limit['c_desc'] > 0 && strlen($_POST['description']) > $length_limit['c_desc'] ){
msg(-1,'名称长度不能大于'.$length_limit['c_desc'].'个字节');
}
//更新数据
$data = [
'fid'=>$_POST['fid'],
'property'=>intval($_POST['property']??'0'),
'name'=>$_POST['name'],
'up_time'=>time(),
'description'=>$_POST['description']??'',
'font_icon'=>$_POST['font_icon'],
];
if(!isset($_POST['fid'])){ //为空时不修改父id,避免二级变一级
unset($data['fid']);
}
if(!isset($_POST['font_icon'])){
unset($data['font_icon']);
}
update_db('user_categorys',$data,['uid'=>UID ,"cid"=>intval($_POST['id'])],[0,'successful']);
}
//查询单个分类信息
function get_a_category(){
$cid = intval(trim($_REQUEST['id']));
@@ -127,19 +289,33 @@ function get_a_category(){
if(empty($category_info)){
msgA(['code'=>-1,'msg'=>'没有找到分类信息','data'=>[]]);
}else{
if(Access_Type == 'all' || $category_info['property'] == 0){
msgA(['code'=>0,'data'=>$category_info]);
}else{
msgA(['code'=>-1,'msg'=>'私有分类,无权查看','data'=>[]]);
}
msgA(['code'=>0,'data'=>$category_info]);
}
}
//是否已登录
//获取TwoNav信息
function app_info(){
$data['php_version'] = floatval(PHP_VERSION);
$data['onenav_version'] = SysVer;
$data['cat_num'] = count_db('user_categorys',['uid'=>UID])??0;
$data['link_num'] = count_db('user_links',['uid'=>UID])??0;
$data['username'] = U;
msgA(['code'=>200,'msg'=>'success','data'=>$data]);
}
//是否已登录,由于上游已经拦截未登录状态,所以这里固定返回已登录
function check_login(){
if(Access_Type == 'open'){
msgA(['code'=>-1002,'data'=>'false','err_msg'=>'Authorization failure!']);
}else{
msgA(['code'=>200,'data'=>'true','msg'=>'success']);
msgA(['code'=>200,'data'=>'true','msg'=>'success']);
}
//给链接数组添加分类字段
function links_add_category_field(&$arr){
$where['uid'] = UID;
$where['status'] = 1;
$categorys = select_db('user_categorys',['cid(id)','name'],$where);
$newCategorys = array_column($categorys,'name','id');
foreach ($arr as &$data) {
$data['category_name'] = $newCategorys[$data['fid']];
}
}
return $arr;
}

View File

@@ -555,6 +555,7 @@ function write_sys_settings(){
'apply'=>['int'=>true,'min'=>0,'max'=>1,'msg'=>'收录管理参数错误'],
'guestbook'=>['int'=>true,'min'=>0,'max'=>1,'msg'=>'留言管理参数错误'],
'link_extend'=>['int'=>true,'min'=>0,'max'=>1,'msg'=>'链接扩展参数错误'],
'article'=>['int'=>true,'min'=>0,'max'=>1,'msg'=>'文章管理参数错误']
];
$o_config = [];
foreach ($datas as $key => $data){
@@ -575,9 +576,30 @@ function write_sys_settings(){
if($_POST['apply'] == 1){$o_config['apply'] = 0;$filter = true;}
if($_POST['guestbook'] == 1){$o_config['guestbook'] = 0;$filter = true;}
if($_POST['link_extend'] == 1){$o_config['link_extend'] = 0;$filter = true;}
if($_POST['article'] == 1){$o_config['article'] = 0;$filter = true;}
}
//检测于下载文章管理依赖资源
clearstatcache();
if($o_config['article'] == 1 && ( !is_file('./static/wangEditor/wangEditor.js') || !is_file('./static/wangEditor/wangEditor.css'))){
$filePath = "./data/temp/wangEdito.tar.gz";
if(downFile('https://update.lm21.top/TwoNav/updata/wangEdito.tar.gz','wangEdito.tar.gz','./data/temp/')){
$file_md5 = md5_file($filePath);
if($file_md5 != "95f830656ba8972cca39a1ddd6ebaeda"){
unlink($filePath);
msg(-1,'效验wangEdito失败<br/>!');
}
}else{
msg(-1,'下载wangEdito失败,请重试!<br/>如需手动安装可联系技术支持!');
}
try {
$phar = new PharData($filePath);
$phar->extractTo('./static/', null, true);
unlink($filePath);
clearstatcache();
} catch (Exception $e) {
msg(-1,'安装wangEdito失败');
}
}
update_db("global_config", ["v" => $o_config], ["k" => "o_config"],[1,($filter ?"保存成功,未检测到有效授权,带*号的配置无法为你保存":"保存成功")]);
}

65
system/expand/article.php Normal file
View File

@@ -0,0 +1,65 @@
<?php if(!defined('DIR')){Not_Found();}AccessControl();
if($global_config['article'] == 0 | !check_purview('article',1)){
Not_Found();
}
$id = intval($_GET['id']);
//IP数统计
count_ip();
//如果id为空,则显示404
if(empty($id)){Not_Found();}
//查询文章
$where['uid'] = UID;
if(!is_login()){
$where['state'] = 1; //状态筛选
}
$where['id'] = $id;
$data = get_db('user_article_list','*',$where);
//查找失败时显示404
if(empty($data)){Not_Found();}
//var_dump($data);
//exit;
//站点设置和站点图标
$site = unserialize(get_db('user_config','v',['uid'=>UID,'k'=>'s_site']));
$site['Title'] = $site['title'].(empty($site['subtitle'])?'':' - '.$site['subtitle']);
//免费用户请保留版权,谢谢!
$copyright = empty($global_config['copyright'])?'<a target="_blank" href="https://gitee.com/tznb/TwoNav">Copyright © TwoNav</a>':$global_config['copyright'];
$ICP = empty($global_config['ICP'])?'':'<a target="_blank" href="https://beian.miit.gov.cn">'.$global_config['ICP'].'</a>';
$favicon = ( !empty($site['site_icon_file'])) ? $site['site_icon'] : './favicon.ico';
//取模板信息
require DIR ."/system/templates.php";
$dir_path = DIR.'/templates/article/'.$s_templates['article'];
$theme_dir = str_replace(DIR.'/templates/article',"./templates/article",$dir_path);
$path = $dir_path.'/index.php';
//检查是否存在,不存在则使用默认
if(!is_file($path)){
$path= DIR.'/templates/article/default/index.php';
$theme_dir = './templates/article/default';
}
//统计点击数
update_db("user_article_list", ["browse_count[+]"=>1],['uid'=>UID,'id'=>$id]);
//读取用户主题配置
$theme_config_db = unserialize(get_db('user_config','v',['t'=>'theme_article','k'=>$s_templates['article'],'uid'=>UID]));
//读取默认主题配置
$theme_info = json_decode(@file_get_contents($theme_dir.'/info.json'),true);
$theme_config = empty($theme_info['config']) ? []:$theme_info['config'];
$theme_ver = !Debug?$theme_info['version']:$theme_info['version'].'.'.time();
//合并配置数据
$theme_config = empty($theme_config_db) ? $theme_config : array_merge ($theme_config??[],$theme_config_db??[]);
require $path;
exit;
//返回404
function Not_Found() {
header('HTTP/1.1 404 Not Found');header("status: 404 Not Found");exit;
}

View File

@@ -11,7 +11,9 @@ foreach($_POST as $key =>$value){
if($method =='write_site_setting' && ($key =='custom_header' || $key =='custom_footer')){
continue;
}
if($method == 'write_article'){
continue;
}
if(preg_match('/<(iframe|script|body|img|layer|div|meta|style|base|object|input)/i',$value)){
$code = 2001;
}elseif(preg_match('/(onmouseover|onerror|onload)\=/i',$value)){

View File

@@ -77,7 +77,7 @@ $theme_ver = !Debug?$theme_info['version']:$theme_info['version'].'.'.time();
$site['ex_theme'] = in_array($theme,['snail-nav','heimdall']); //例外主题,不支持热门网址/最新网址/输出上限
//分类查找条件
$categorys = []; //声明一个空数组
$content = ['cid(id)','name','property','font_icon','icon','description'];//需要的内容
$content = ['cid(id)','fid','name','property','font_icon','icon','description'];//需要的内容
$where['uid'] = UID;
$where['fid'] = 0;
$where['status'] = 1;
@@ -102,7 +102,7 @@ function get_category_sub($id) {
if(!empty($share)){
$where['cid'] = $data;
}
$content = ['cid(id)','name','property','font_icon','icon','description'];
$content = ['cid(id)','name','fid','property','font_icon','icon','description'];
$where['uid'] = UID;
$where['fid'] = intval($id);
$where['status'] = 1;
@@ -163,7 +163,7 @@ function get_links($fid) {
$where['LIMIT'] = $site['max_link'];
$max_link = true;
}
$links = select_db('user_links',['lid(id)','fid','property','title','url(real_url)','url_standby','description','icon','click','pid'],$where);
$links = select_db('user_links',['lid(id)','fid','property','title','url(real_url)','url_standby','description','icon','click','pid','extend'],$where);
foreach ($links as $key => $link) {
$click = false; $lock = false;
@@ -197,7 +197,41 @@ function get_links($fid) {
//获取图标链接
$links[$key]['ico'] = $lock ? $GLOBALS['libs'].'/Other/lock.svg' : geticourl($site['link_icon'],$link);
$links[$key]['type'] = 'link';
}
//处理扩展信息
if($GLOBALS['global_config']['link_extend'] == 1 && check_purview('link_extend',1) && in_array($GLOBALS['theme_info']['support']['link_extend'],["true","1"])){
foreach ($links as &$link) {
if(!empty($link['extend'])){
$link = array_merge ($link,unserialize($link['extend']));
}
}
}
//生成文章链接, 条件:非隐藏,且主题未声明不显示文章
if( intval($site['article_visual'] ?? '1') > 0 && $GLOBALS['theme_info']['support']['article'] != 'notdisplay'){
$articles = get_article_list($fid);
foreach ($articles['data'] as $article) {
$url = "./index.php?c=article&id={$article['id']}&u={$u}";
if($site['article_icon'] == '1'){ //站点图标
$icon = $GLOBALS['favicon'];
}elseif($site['article_icon'] == '2' && !empty($article['cover'])){ //封面
$icon = $article['cover'];
}else{ //首字
$icon = './system/ico.php?text='.mb_strtoupper(mb_substr($article['title'], 0, 1));
}
$article_link = ['type'=>'article','id'=>0,'title'=>$article['title'],'url'=>$url,'real_url'=>$url,'description'=>$article['summary'],'ico'=>$icon,'icon'=>$icon];
//判断靠前还是靠后
if($site['article_visual'] == '1'){
array_unshift($links,$article_link);
}else{
array_push($links,$article_link);
}
}
}
if($max_link && $count > $site['max_link']){
$oc_url = "./index.php?u={$u}&oc={$fid}" . (empty($_GET['theme']) ? '':"&theme={$_GET['theme']}");
array_push($links,['id'=>0,'title'=>'查看全部','url'=>$oc_url,'real_url'=>$oc_url,'description'=>'该分类共有'.$count.'条数据','ico'=>'./favicon.ico']);

View File

@@ -1,6 +1,5 @@
<?php if(!defined('DIR')){header('HTTP/1.1 404 Not Found');header("status: 404 Not Found");exit;}
//登录入口
require "./system/templates.php";
//如果是Get请求则载入登录模板
if($_SERVER['REQUEST_METHOD'] === 'GET'){
require DIR ."/system/templates.php";

View File

@@ -445,10 +445,10 @@ function is_subscribe($type = 'bool'){
$count = count($host);
if($count != 2){
$data['host'] = $host[$count-2].'.'.$host[$count-1];
//如果存在端口则去除
if(preg_match("/(.+):\d+/",$data['host'],$host)) {
$data['host'] = $host[1];
}
}
//如果存在端口则去除
if(preg_match("/(.+):\d+/",$data['host'],$host)) {
$data['host'] = $host[1];
}
}
if(!stristr($data['domain'],$data['host'])){
@@ -745,15 +745,15 @@ function send_email($config){
function count_ip(){
$ip = Get_IP(); //取访客IP
$k = date('Ymd'); $t = 'ip_list';
$ip_list = get_db('user_count','v',['uid'=>UID,'k'=>$k,'t'=>$t]); //取列表
$ip_list = get_db('user_count','e',['uid'=>UID,'k'=>$k,'t'=>$t]); //取列表
$ip_list = empty($ip_list) ? [] : unserialize($ip_list); //反序列化
//判断IP是否存在列表中
if(!in_array($ip, $ip_list)){
$ip_list[] = $ip; //加入列表
if(!has_db('user_count',['uid'=>UID,'t'=>$t,'k'=>$k])){
insert_db("user_count", ['uid'=>UID,"k"=>$k,"v"=>$ip_list,'t'=>$t]);
insert_db("user_count", ['uid'=>UID,"k"=>$k,"e"=>$ip_list,'t'=>$t]);
}else{
update_db("user_count", ["v"=>$ip_list],['uid'=>UID,'t'=>$t,'k'=>$k]);
update_db("user_count", ["e"=>$ip_list],['uid'=>UID,'t'=>$t,'k'=>$k]);
}
write_user_count($k,'ip_count');//访问ip数+1
}

View File

@@ -14,7 +14,7 @@ if(empty($s_templates)){
}
//载入辅助函数
if(empty($c) || in_array($c,['index','click'])){
if(empty($c) || in_array($c,['index','click','article'])){
//将URL转换为base64编码
function base64($url){
$urls = parse_url($url);
@@ -98,3 +98,83 @@ if(empty($c) || in_array($c,['index','click'])){
}
//获取文章列表
function get_article_list($category = 0,$limit = 0){
$where['uid'] = UID;
if(!is_login()){
$where['AND']['state'] = 1; //状态筛选
}else{
$where['AND']['OR']['state'] = [1,2]; //状态筛选
}
//分类筛选
if($category > 0){
$where['AND']['category'] = $category;
}
//统计条数
$count = count_db('user_article_list',$where);
//获取条数
if($limit > 0){
$where['LIMIT'] = [0,$limit];
}
//获取文章列表
$datas = select_db('user_article_list','*',$where);
//查询分类
$categorys = select_db('user_categorys',['cid(id)','name'],['uid'=>UID]);
$categorys = array_column($categorys,'name','id');
//为文章添加分类名称
foreach ($datas as &$data) {
$data['category_name'] = $categorys[$data['category']] ?? 'Null';
}
return ['data'=>$datas,'count'=>$count];
}
//根据文章id获取内容
function get_article_content($id){
$where['uid'] = UID;
if(!is_login()){
$where['AND']['state'] = 1; //状态筛选
}else{
$where['AND']['OR']['state'] = [1,2]; //状态筛选
}
$where['id'] = $id;
$data = get_db('user_article_list','*',$where);
$data['category_name'] = get_db('user_categorys','name',['uid'=>UID,'cid'=>$data['category']]);
return $data;
}
//获取分类列表
function get_category_list($layer = false){
//查询条件
$where = [];
$where['uid'] = UID;
$where['fid'] = 0;
$where['status'] = 1;
$where['ORDER'] = ['weight'=>'ASC'];
if(!is_login()){
$where['property'] = 0;
}
//查找一级分类
$content = ['cid(id)','name','property','font_icon','icon','description'];
$category_parent = select_db('user_categorys',$content,$where);
//查找二级分类
$categorys = [];
if($layer === true){
foreach ($category_parent as $key => $category) {
$where['fid'] = $category['id'];
$category_subitem = select_db('user_categorys',$content,$where);
$category['subitem_count'] = count($category_subitem);
$category['subitem'] = $category_subitem;
array_push($categorys,$category);
}
}else{
foreach ($category_parent as $key => $category) {
$where['fid'] = $category['id'];
$category_subitem = select_db('user_categorys',$content,$where);
$category['subitem_count'] = count($category_subitem);
array_push($categorys,$category);
$categorys = array_merge ($categorys,$category_subitem);
}
}
return $categorys;
}

View File

@@ -1 +1 @@
v2.0.31-20230720
v2.0.33-20230802

View File

@@ -204,6 +204,28 @@ layui.use(module, function () {
}
}
//链接扩展上传图片
upload.render({
elem: '.extend_up_img'
,url: get_api('write_link','extend_up_img')
,exts: 'jpg|jpeg|png|ico|bmp|svg'
,acceptMime: 'image/*'
,accept: 'file'
,size: 1024
,done: function(res){
if(res.code == 1){
let inpu = this.item.closest('.layui-form-item').find('input[name^="_"]');
inpu.val(res.url);
}else{
layer.msg(res.msg || '上传失败', {icon: 5});
}
},error: function(){
layer.msg("上传异常,请刷新重试", {icon: 5});
}
});
//layui>end
});

View File

@@ -376,6 +376,7 @@ layui.use(['form','table','dropdown','miniTab'], function () {
,{field:'name',title:'字段名',edit:'text',width:256}
,{field:'type',title:'类型',edit:'text',width:256}
,{field:'default',title:'默认值',edit:'text',width:256}
,{field:'tip',title:'提示内容',edit:'text',width:256}
,{ title:'操作',toolbar:'#link_extend_toolbar',align:'center',width:118}
]]
});
@@ -530,7 +531,7 @@ layui.use(['form','table','dropdown','miniTab'], function () {
"title": "请输入标题",
"name":"请输入字段名(大小写字母或数字)",
"weight":(max_weight + 1),
"type":"请输入 text 或 textarea",
"type":"请输入 text 或 textarea 或 up_img",
"default":""
});
table.reload('link_extend_list', {data: data});

View File

@@ -83,10 +83,9 @@
<select name="api_model">
<option value="security" selected>安全模式</option>
<option value="compatible">兼容模式</option>
<option value="compatible+open">兼容模式+开放</option>
</select>
</div>
<div class="layui-form-mid layui-word-aux">部分主题和插件需设为兼容+开放模式 <a href="javascript:;" layuimini-content-href="Token" data-title="Token"><font color="red"> 获取API ( Token )</font></a></div>
<div class="layui-form-mid layui-word-aux">部分主题和插件需设为兼容 <a href="javascript:;" layuimini-content-href="Token" data-title="Token"><font color="red"> 获取API ( Token )</font></a></div>
</div>
<div class="layui-form-item">

View File

@@ -0,0 +1,311 @@
<?php
if($global_config['article'] != 1 || !check_purview('article',1)){
require(DIR.'/templates/admin/page/404.php');
exit;
}
$article_id = Get('id');
$mode = empty($article_id) ? 'add' : 'edit' ;
if($mode == 'edit'){
if(has_db('user_article_list',['uid'=>UID,'id'=>$article_id])){
$data = get_db('user_article_list','*',['uid'=>UID,'id'=>$article_id]);
//var_dump($data);
}else{
$mode = 'add';
}
}
$title = $mode == 'add' ? '添加文章' : '编辑文章';
require dirname(__DIR__).'/header.php' ?>
<link href="<?php echo $libs?>/wangEditor/wangEditor.css" rel="stylesheet">
<style type="text/css">
#editor—wrapper { border: 1px solid #cccccc88; }
#toolbar-container { border-bottom: 1px solid #ccc; }
#editor-container { height: 400px; }
.w40{width:40px;}
.layui-upload-drag .layui-icon{font-size: 40px;color: #c2c2c2;}
.layui-upload-drag{padding: 10px;}
.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:11px;font-weight:700;color:#fff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}
.bg-red{background-color:#e74c3c!important}
.uploads-delete-tip{position: absolute;right: 10px;font-size: 12px;}
.layui-input-block{margin-left: 70px;}
@media screen and (max-width: 768px) {
.layui-input-block {margin-left: 12px;}
.content{display: none!important;}
.layui-form-select .layui-edge {top: 75%;}
}
</style>
<body>
<div class="layuimini-container">
<div class="layuimini-main">
<form class="layui-form" lay-filter="form">
<input class="layui-input layui-hide" name="id" autocomplete="off" value="<?php echo $data['id'];?>">
<div class="layui-form-item ">
<label class="layui-form-label w40">标题:</label>
<div class="layui-input-block">
<input class="layui-input" name="title" placeholder='请输入文章标题' autocomplete="off" value="<?php echo $data['title'];?>">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label w40">分类:</label>
<div class="layui-input-block">
<select name="category" lay-search>
<?php echo_category(true); ?>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label w40">状态:</label>
<div class="layui-input-block">
<select name="state">
<option value="1">公开</option>
<option value="2">私有</option>
<option value="3">草稿</option>
<option value="4">废弃</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label w40">摘要:</label>
<div class="layui-input-block">
<textarea name="summary" rows ="2" placeholder="文章摘要,留空时自动获取" class="layui-textarea" style="min-height: 45px;"><?php echo $data['summary'];?></textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label w40 content">正文:</label>
<div class="layui-input-block" id="editor—wrapper">
<div id="toolbar-container"></div>
<div id="editor-container"></div>
<textarea name="content" id="content" class="layui-textarea layui-hide"><?php echo $data['content'] ?? '<p><br></p>';?></textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label w40">封面:</label>
<div class="layui-upload-drag">
<input type="text" name="cover_url" id="cover_url" style="display: none;" value="<?php echo $data['cover'];?>">
<small class="uploads-delete-tip bg-red badge" style="cursor:pointer;display: none;" id="del_cover_view">×</small>
<i class="up_cover layui-icon layui-icon-add-1" id="up_cover" style="padding-right: 20px; padding-left: 20px;color: #e2e2e2;"></i>
<p class="up_cover">上传封面</p>
<div id="cover_view" style="display: none;"><img src="<?php echo $data['cover'];?>" style="max-width: 196px"></div>
</div>
</div>
</form>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal layui-btn-danger" id="cancel" >取消</button>
<button class="layui-btn layui-btn-normal" id="save" >保存</button>
</div>
</div>
</div>
</div>
<script src = "<?php echo $libs;?>/jquery/jquery-3.6.0.min.js"></script>
<script src = '<?php echo $libs?>/jquery/jquery.md5.js'></script>
<script src = "./templates/admin/js/public.js?v=<?php echo $Ver;?>"></script>
<?php load_static('js');?>
<script src="<?php echo $libs?>/wangEditor/wangEditor.js"></script>
<script>
const { createEditor, createToolbar } = window.wangEditor
const editorConfig = {
placeholder: '请输入文章内容...',
MENU_CONF: {
uploadImage: {}
},
onChange(editor) {
const html = editor.getHtml();
$('#content').val(html);
}
}
editorConfig.MENU_CONF['uploadImage'] = {
base64LimitSize: 128 * 1024, //小于该值就插入base64
server: get_api('write_article','uploadImage'),
fieldName: 'file',
maxFileSize: 5 * 1024 * 1024, // 单文件限制5M
maxNumberOfFiles: 10, //最多上传10个文件
// 上传之前触发
onBeforeUpload(file) {
return file
},
// 上传进度的回调函数
onProgress(progress) {
console.log('progress', progress) //进度: 0-100
},
// 单个文件上传成功之后
onSuccess(file, res) {
parent.layer.msg('上传成功', {icon: 1});
},
// 单个文件上传失败
onFailed(file, res) {
layer.alert(`${res.message}`,{icon:5,title:`上传失败: ${file.name}`,anim: 2,closeBtn: 0});
console.log(res );
},
// 上传错误,或者触发 timeout 超时
onError(file, err, res) {
layer.alert(`${err}`,{icon:5,title:`上传错误: ${file.name}`,anim: 2,closeBtn: 0});
},
}
editorConfig.MENU_CONF['uploadVideo'] = {
base64LimitSize: 128 * 1024, //小于该值就插入base64
server: get_api('write_article','uploadVideo'),
fieldName: 'file',
maxFileSize: 20 * 1024 * 1024, // 单文件限制
maxNumberOfFiles: 10, //最多上传10个文件
// 上传之前触发
onBeforeUpload(file) {
return file
},
// 上传进度的回调函数
onProgress(progress) {
console.log('progress', progress) //进度: 0-100
},
// 单个文件上传成功之后
onSuccess(file, res) {
parent.layer.msg('上传成功', {icon: 1});
},
// 单个文件上传失败
onFailed(file, res) {
layer.alert(`${res.message}`,{icon:5,title:`上传失败: ${file.name}`,anim: 2,closeBtn: 0});
console.log(res );
},
// 上传错误,或者触发 timeout 超时
onError(file, err, res) {
layer.alert(`${err}`,{icon:5,title:`上传错误: ${file.name}`,anim: 2,closeBtn: 0});
},
}
const editor = createEditor({
selector: '#editor-container',
html: $('#content').val(),
config: editorConfig,
mode: 'default'
})
const toolbarConfig = {excludeKeys: ['fullScreen','uploadVideo']}
const toolbar = createToolbar({
editor,
selector: '#toolbar-container',
config: toolbarConfig,
mode: 'default'
})
layui.use(['form','upload'], function () {
var form = layui.form,
upload = layui.upload;
<?php if($mode == 'edit'){ ?>
form.val('form',{category:<?php echo $data['category'];?>,state:<?php echo $data['state'];?>});
<?php }?>
var original_md5 = $.md5(JSON.stringify(form.val('form')));
$('#cancel').click(function () {
let data = form.val('form');
if($.md5(JSON.stringify(form.val('form'))) == original_md5){
parent.layer.close(parent.layer.getFrameIndex(window.name));
return false;
}
layer.confirm('确定取消?',{icon: 3, title:'温馨提示'}, function(index){
parent.layer.close(parent.layer.getFrameIndex(window.name));
});
return false;
});
//如果存在封面则加载
if($("#cover_url").val() != ''){
layui.$('#cover_view img').attr('src', $("#cover_url").val());
layui.$('#cover_view').show();
layui.$('#del_cover_view').show();
layui.$('.up_cover').hide();
}
//上传
var uploadInst = upload.render({
elem: '.up_cover'
,url: get_api('write_article','uploadImage')
,accept: 'images'
,acceptMime: 'image/*'
,exts:'jpg|png|gif|bmp|jpeg|svg|webp'
,size: 5*1024
,done: function(res){
if(res.errno == 0){
$("#cover_url").val(res.data.url);
layui.$('#cover_view img').attr('src', res.data.url);
layui.$('#cover_view').show();
layui.$('#del_cover_view').show();
layui.$('.up_cover').hide();
layer.msg('上传成功', {icon: 1});
}else{
layer.msg(res.message || '上传失败', {icon: 5});
}
},error: function(){
layer.msg("上传异常,请刷新重试", {icon: 5});
}
});
//删除封面
$(document).on('click', '#del_cover_view', function() {
$.post(get_api('write_article','deleteImage'),{'path':$("#cover_url").val()},function(data,status){
if(data.code == 1) {
$("#cover_url").val('');
layui.$('#cover_view').hide();
layui.$('#del_cover_view').hide();
layui.$('.up_cover').show();
uploadInst.config.elem.next()[1].value = '';
layer.msg("删除成功",{icon:1});
}else{
layer.msg(data.msg || '未知错误',{icon: 5});
}
});
});
$('#save').click(function () {
let data = form.val('form');
if(data.title == ''){
layer.msg('标题不能为空,请输入标题',{icon: 5});
return false;
}
if(data.summary == ''){
data.summary = truncateString(editor.getText(),120).replace(/\n/g, ' ');
}
let loading = layer.msg('正在处理,请稍后..', {icon: 16,time: 1000*300,shadeClose: false});
$.post(get_api('write_article','save_article'),data,function(data,status){
layer.close(loading);
if(data.code == 1) {
parent.layer.close(parent.layer.getFrameIndex(window.name));
parent.layer.msg('操作成功', {icon: 1});
}else{
layer.msg(data.msg || '未知错误',{icon: 5});
}
});
return false;
});
});
function truncateString(str,n) {
var r=/[^\x00-\xff]/g;
if(str.replace(r,"mm").length<=n){return str;}
var m=Math.floor(n/2);
for(var i=m;i<str.length;i++){
if(str.substr(0,i).replace(r,"mm").length>=n){
return str.substr(0,i)+"...";
}
}
return str;
}
</script>
</body>
</html>

View File

@@ -0,0 +1,392 @@
<?php
if($global_config['article'] != 1 || !check_purview('article',1)){
require(DIR.'/templates/admin/page/404.php');
exit;
}
//读取设置
$s_site = unserialize(get_db('user_config','v',['uid'=>UID,'k'=>'s_site']));
$set['visual'] = $s_site['article_visual'] ?? '1';
$set['icon'] = $s_site['article_icon'] ?? '1';
$title='文章列表';
require dirname(__DIR__).'/header.php' ?>
<body>
<div class="layuimini-container">
<div class="layuimini-main">
<form class="layui-form" lay-filter="form">
<div class="layui-inline layui-form" style="padding-bottom: 5px;">
<label class="layui-form-label " style="width:60px;padding-left: 5px;padding-right: 5px;">文章筛选:</label>
<div class="layui-input-inline" style="width: 150px;">
<select name="category" lay-search>
<option value="0" selected="">全部</option>
<optgroup label="用户分类">
<?php echo_category(true); ?>
</optgroup>
</select>
</div>
</div>
<div class="layui-inline layui-form" style="padding-bottom: 5px;">
<label class="layui-form-label layui-hide-sm" style="width:60px;padding-left: 5px;padding-right: 5px;">关键字:</label>
<div class="layui-input-inline">
<input class="layui-input" name="keyword" id="keyword" placeholder='请输入标题或文章内容' autocomplete="off" >
</div>
</div>
<div class="layui-inline layui-form layui-hide-xs" style="padding-bottom: 5px;" >
<label class="layui-form-label layui-hide-sm" style="width:60px;padding-left: 5px;padding-right: 5px; ">属性筛选:</label>
<div class="layui-input-inline" style="width: 80px;">
<select name="state">
<option value="0" selected="">全部</option>
<option value="1">公开</option>
<option value="2">私有</option>
<option value="3">草稿</option>
<option value="4">废弃</option>
</select>
</div>
</div>
<div class="layui-inline layui-form" style="padding-bottom: 5px;">
<button class="layui-btn layui-btn-normal "type="button" id="search" style="height: 36px;">搜索</button>
</div>
</form>
<table id="table" class="layui-table" lay-filter="table" style="margin: 1px 0;"></table>
</div>
</div>
<!-- 操作列 -->
<script type="text/html" id="tablebar">
<div class="layui-btn-group">
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</a>
</div>
</script>
<!-- 表头工具栏 -->
<script type="text/html" id="toolbar">
<div class="layui-btn-group">
<button class="layui-btn layui-btn-sm layui-btn-danger" id="batch_operation"><span>批量操作</span><i class="layui-icon layui-icon-down layui-font-12"></i></button>
<button class="layui-btn layui-btn-sm layui-btn-normal" lay-event="add_article">添加文章</button>
<button class="layui-btn layui-btn-sm " lay-event="set">设置</button>
</div>
</script>
<script src = "<?php echo $libs;?>/jquery/jquery-3.6.0.min.js"></script>
<script src = "./templates/admin/js/public.js?v=<?php echo $Ver;?>"></script>
<?php load_static('js');?>
<!--批量修改分类-->
<ul class="batch_category" style="margin-top: 18px;display:none;padding-right: 10px;padding-left: 10px;">
<form class="layui-form" lay-filter="batch_category">
<div class="layui-form-item">
<label class="layui-form-label">父级分类</label>
<div class="layui-input-block">
<select id="batch_category_fid">
<?php echo_category(true); ?>
</select>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal layui-btn-danger cancel" type="button">取消</button>
<button class="layui-btn" type="button" id="batch_category" >确定修改</button>
</div>
</div>
</form>
</ul>
<!--设置-->
<ul class="set" style="margin-top: 18px;display:none;padding-right: 10px;padding-left: 10px;">
<form class="layui-form" lay-filter="set_form">
<div class="layui-form-item">
<label class="layui-form-label">显示文章</label>
<div class="layui-input-inline">
<select name="visual">
<option value="1">显示靠前</option>
<option value="2">显示靠后</option>
<option value="0">隐藏</option>
</select>
</div>
<div class="layui-form-mid layui-word-aux">是否在主页显示文章链接</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">链接图标</label>
<div class="layui-input-inline">
<select name="icon">
<option value="0">首字图标</option>
<option value="1">站点图标</option>
<option value="2">文章封面</option>
</select>
</div>
<div class="layui-form-mid layui-word-aux">设为文章封面且无封面时显示站点图标</div>
</div>
<div class="layui-form-item" style="padding-top: 10px;">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal layui-btn-danger cancel">取消</button>
<button class="layui-btn" lay-submit id="save_set">保存</button>
</div>
</div>
<pre class="layui-code" >
小提示:
1.文章所属分类加密时不会对文章加密 (暂不支持文章加密,不想被看到可将文章设为私有)
2.文章所属分类私有且未登录时不显示文章链接 (通过文章链接访问不受限制,不想被看到可将文章设为私有)
3.上传图片支持格式:jpg|png|gif|bmp|jpeg|svg 大小限制:5M
4.编辑器中上传图片小于128KB时使用base64编码存入数据库,大于128KB时将以文件的方式上传到服务器
5.显示文章选项中的靠前/靠后是指文章链接在所属分类下的位置,隐藏则不在主页显示
</pre>
</form>
</ul>
<script>
layui.use(['form','table','dropdown','miniTab'], function () {
var $ = layui.jquery;
var table = layui.table;
var form = layui.form;
var dropdown = layui.dropdown;
var miniTab = layui.miniTab;
var api = get_api('read_article','article_list');
var limit = localStorage.getItem(u + "_limit") || 50;
var state_data = ["Null","公开", "私有", "草稿", "废弃"];
var cols=[ //表头
{type:'checkbox'} //开启复选框
,{ title:'操作', toolbar: '#tablebar',width:110}
,{field: 'title', title: '标题', minWidth:200,templet: function(d){
return '<a style="color:#3c78d8" target="_blank" href="./?c=article&id=' +d.id + '&u=' + u + '" title="' + d.summary + '">'+d.title+'</a>'
}}
,{field:'category',title:'分类',width:100,templet: function(d){
return d.category_name;
}}
,{field:'state',title:'状态',width:100,templet: function(d){
return state_data[d.state];
}}
,{field: 'browse_count', title: '浏览次数',width:120,sort:true}
,{field: 'add_time', title: '添加时间', width:170, sort: true,templet:function(d){
var add_time = timestampToTime(d.add_time);
return add_time;
}}
,{field: 'up_time', title: '修改时间', width:170,sort:true,templet:function(d){
return d.up_time == null ?'':timestampToTime(d.up_time);
}}
];
table.render({
elem: '#table'
,height: 'full-80'
,url: api
,page: true
,limit:limit
,limits: [20,50,100,300,500]
,even:true
,loading:true
,toolbar: '#toolbar'
,id:'table'
,cols: [cols]
,method: 'post'
,response: {statusCode: 1 }
,done: function (res, curr, count) {
batch_operation();//初始化批量操作菜单
//获取当前每页显示数量.并写入本都储存
var temp_limit = $(".layui-laypage-limits option:selected").val();
if(temp_limit > 0 && localStorage.getItem(u + "_limit") != temp_limit){
localStorage.setItem(u + "_limit",temp_limit);
}
}
});
//批量操作
function batch_operation(){
dropdown.render({
elem: '#batch_operation',
data: [{
title: ' 修改分类 ',
id: 'up_category'
},{
title: '修改状态',
child: [{
title: '设为公开',
id: "up_state",
value: 1
},{
title: '设为私有',
id: "up_state",
value: 2
},{
title: '设为草稿',
id: "up_state",
value: 3
},{
title: '设为废弃',
id: "up_state",
value: 4
}]
},{
title: '批量删除',
id: 'del_article'
}],
click: function(obj){
let checkStatus = table.checkStatus('table').data;
if( checkStatus.length == 0 ) {
layer.msg('未选中任何数据!');
return;
}
//获取被选ID并格式化
tableIds = checkStatus.map(function (value) {return value.id;});
tableIds = JSON.stringify(tableIds);
//删除文章
if(obj.id == 'del_article'){
layer.confirm('确认删除?',{icon: 3, title:'温馨提示'}, function(index){
$.post(get_api('write_article','del_article'),{id:tableIds},function(data,status){
if(data.code == 1) {
search();
layer.msg(data.msg, {icon: 1});
}else{
layer.msg(data.msg, {icon: 5});
}
});
});
}else if(obj.id == 'up_category'){
index = layer.open({type: 1,scrollbar: false,shadeClose: true,title: false ,area : ['100%', '100%'],closeBtn:0,content: $('.batch_category')});
}else if(obj.id == 'up_state'){
$.post(get_api('write_article','up_state'),{'id':tableIds,'state_id':obj.value},function(data,status){
if(data.code == 1) {
search();
layer.msg('操作成功', {icon: 1});
}else{
layer.msg(data.msg || '未知错误',{icon: 5});
}
});
}
}
});
}
//输入框回车事件和搜索按钮点击事件
$('#keyword, #search').on('keydown click', function(e) {
if ( (e.target.id === 'keyword' && e.keyCode === 13) || (e.target.id === 'search' && e.type === 'click') ) {
search();
}
});
//搜索
function search(){
let data = form.val('form');
table.reload('table', {
url: api
,method: 'post'
,request: {pageName: 'page',limitName: 'limit'}
,where: data
,page: {curr: 1}
});
}
//监听工具栏
table.on('toolbar(table)', function (obj) {
var btn = obj.event;
if (btn == 'add_article') { //添加文章
layer.open({
title: false,
type: 2,
scrollbar: false,
shade: 0.2,
maxmin:false,
shadeClose: true,
closeBtn:0,
area: ['100%', '100%'],
content: './?c=admin&page=expand/article-edit&u=' + u,
end: function(){
search();
}
});
}else if(btn == 'set'){ //设置
index = layer.open({type: 1,scrollbar: false,shadeClose: true,title: false ,area : ['100%', '100%'],closeBtn:0,content: $('.set')});
}else{ //综合批量操作
//取选中数据
var checkStatus = table.checkStatus(obj.config.id);
if( checkStatus.data.length == 0 && ['LAYTABLE_COLS','LAYTABLE_EXPORT','LAYTABLE_PRINT'].indexOf(btn) == -1 ) {
layer.msg('未选中任何数据!');
return;
}
//批量删除
if(btn == 'batch_del'){
tableIds = checkStatus.data.map(function (value) {return value.id;});
tableIds = JSON.stringify(tableIds);
layer.confirm('确认删除?',{icon: 3, title:'温馨提示'}, function(index){
$.post(get_api('write_article','del_article'),{id:tableIds},function(data,status){
if(data.code == 1) {
search();
layer.msg(data.msg, {icon: 1});
}else{
layer.msg(data.msg, {icon: 5});
}
});
});
}
}
});
//监听行工具
table.on('tool(table)', function (obj) {
let btn = obj.event;
let data = obj.data;
if (btn === 'del') {
layer.confirm('确认删除?',{icon: 3, title:'温馨提示'}, function(index){
$.post(get_api('write_article','del_article'),{id:'['+data.id+']'},function(data,status){
if(data.code == 1) {
obj.del();
layer.msg(data.msg, {icon: 1});
}else{
layer.msg(data.msg, {icon: 5});
}
});
});
}else if(btn === 'edit'){
layer.open({
title: false,
type: 2,
scrollbar: false,
shade: 0.2,
maxmin:false,
shadeClose: true,
closeBtn:0,
area: ['100%', '100%'],
content: './?c=admin&page=expand/article-edit&id='+data.id+'&u=' + u,
end: function(){
search();
}
});
}
});
//设置相关
form.val('set_form', <?php echo json_encode($set);?>);
$('#save_set').on('click', function(){
$.post(get_api('write_article','save_article_set'),form.val('set_form'),function(data,status){
if(data.code == 1) {
layer.close(index);
layer.msg('操作成功', {icon: 1});
}else{
layer.msg(data.msg || '未知错误',{icon: 5});
}
});
return false;
});
//取消按钮
$('.cancel').click(function () {
layer.close(index);
return false;
});
//批量修改分类
$('#batch_category').click(function () {
fid = $('#batch_category_fid').val();
$.post(get_api('write_article','up_category'),{'id':tableIds,'category_id':fid},function(data,status){
if(data.code == 1) {
search();
layer.close(index);
layer.msg('操作成功', {icon: 1});
}else{
layer.msg(data.msg || '未知错误',{icon: 5});
}
});
return false;
});
});
</script>
</body>
</html>

View File

@@ -18,15 +18,17 @@ if(!empty($list)){
echo_text($data);
}elseif($data['type'] == 'textarea'){
echo_textarea($data);
}elseif($data['type'] == 'up_img'){
echo_up_img($data);
}
}
}
function echo_text($data){ ?>
<div class="layui-form-item">
<label class="layui-form-label"><?php echo $data['title']?></label>
<label class="layui-form-label" title="<?php echo $data['name']?>"><?php echo $data['title']?></label>
<div class="layui-input-block">
<input type="text" name="_<?php echo $data['name']?>" autocomplete="off" value="<?php echo htmlentities($data['value'])?>" class="layui-input">
<input type="text" name="_<?php echo $data['name']?>" autocomplete="off" value="<?php echo htmlentities($data['value'])?>" placeholder="<?php echo htmlentities($data['tip'])?>" class="layui-input" >
</div>
</div>
<?php
@@ -34,13 +36,26 @@ function echo_text($data){ ?>
function echo_textarea($data){ ?>
<div class="layui-form-item">
<label class="layui-form-label"><?php echo $data['title']?></label>
<label class="layui-form-label" title="<?php echo $data['name']?>"><?php echo $data['title']?></label>
<div class="layui-input-block">
<textarea name="_<?php echo $data['name']?>" class="layui-textarea"><?php echo htmlentities($data['value'])?></textarea>
<textarea name="_<?php echo $data['name']?>" placeholder="<?php echo htmlentities($data['tip'])?>" class="layui-textarea"><?php echo htmlentities($data['value'])?></textarea>
</div>
</div>
<?php
}
}
function echo_up_img($data){ ?>
<div class="layui-form-item">
<label class="layui-form-label" title="<?php echo $data['name']?>"><?php echo $data['title']?></label>
<div class="layui-input-block layuimini-upload" >
<input type="text" name="_<?php echo $data['name']?>" autocomplete="off" class="layui-input obtn" value="<?php echo htmlentities($data['value'])?>" placeholder="<?php echo htmlentities($data['tip'])?>">
<div style="position: absolute; top:0px;" >
<span><a class="layui-btn layui-btn-primary extend_up_img"><i class="fa fa-upload"></i> 上传</a></span>
</div>
</div>
</div>
<?php
}
?>

View File

@@ -17,18 +17,21 @@ $title='系统设置';require(dirname(__DIR__).'/header.php');
<div class="layui-input-inline">
<input type="pass" name="user" lay-verify="required" lay-reqtext="账号不能为空" placeholder='请输入账号' autocomplete="off" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">邮箱账号,例如: admin@qq.com</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密码</label>
<div class="layui-input-inline">
<input type="password" name="pwd" lay-verify="required" lay-reqtext="密码不能为空" placeholder='请输入密码或授权码' autocomplete="off" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">邮箱密码,也可能是独立密码或者授权码</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">服务器</label>
<div class="layui-input-inline">
<input type="text" name="host" lay-verify="required" lay-reqtext="服务器不能为空" placeholder='请输入发件服务器地址' autocomplete="off" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">例如: smtp.qq.com</div>
</div>
<div class="layui-form-item">
@@ -36,6 +39,7 @@ $title='系统设置';require(dirname(__DIR__).'/header.php');
<div class="layui-input-inline">
<input type="number" name="port" lay-verify="required" lay-reqtext="端口不能为空" placeholder='请输入服务器端口' value="465" autocomplete="off" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">通常是: 465或587</div>
</div>
<div class="layui-form-item">
@@ -46,6 +50,7 @@ $title='系统设置';require(dirname(__DIR__).'/header.php');
<option value="TLS" >TLS</option>
</select>
</div>
<div class="layui-form-mid layui-word-aux">通常是: ssl</div>
</div>
<div class="layui-form-item">
@@ -53,6 +58,7 @@ $title='系统设置';require(dirname(__DIR__).'/header.php');
<div class="layui-input-inline">
<input type="text" name="sender" lay-verify="required" lay-reqtext="发送人邮箱不能为空" placeholder='' autocomplete="off" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">例如: TwoNav书签&lt;test@qq.com&gt;</div>
</div>
<div class="layui-form-item">
@@ -60,6 +66,7 @@ $title='系统设置';require(dirname(__DIR__).'/header.php');
<div class="layui-input-inline">
<input type="text" name="addressee" placeholder='仅用于发件测试' autocomplete="off" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">例如:user@qq.com</div>
</div>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;"><legend>注册参数</legend></fieldset>
@@ -71,12 +78,14 @@ $title='系统设置';require(dirname(__DIR__).'/header.php');
<option value="1" >开启</option>
</select>
</div>
<div class="layui-form-mid layui-word-aux">开启时用户注册需通过邮箱接收验证码</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">发送间隔</label>
<div class="layui-input-inline">
<input type="number" name="send_interval" lay-verify="required" lay-reqtext="发送间隔不能为空" placeholder='IP发送间隔,单位秒!' value="60" autocomplete="off" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">为了避免被恶意发送,建议不低于30秒</div>
</div>
<div class="layui-form-item layui-form-text">

View File

@@ -251,6 +251,16 @@ $title='系统设置';require(dirname(__DIR__).'/header.php');
</div>
<div class="layui-form-mid layui-word-aux">自定义链接的扩展信息(需自行添加字段,目前仅用于自定义过渡页)</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">文章管理</label>
<div class="layui-input-inline">
<select name="article">
<option value="0" selected="">关闭</option>
<option value="1" >开启</option>
</select>
</div>
<div class="layui-form-mid layui-word-aux">简易文章管理功能 ( 请勿和专业的比,首次开启时自动下载相关资源 )</div>
</div>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;"><legend>相关限制</legend></fieldset>
<blockquote class="layui-elem-quote layui-text" style="">程序采用UTF8编码,一个汉字约占用3个字节!英文字母和数组占用1个字节!值为0表示不限制!<br />添加或编辑时长度超限则不允许添加,批量识别时超限则截断</blockquote>
@@ -335,7 +345,9 @@ layui.use(['jquery','form','miniTab'], function () {
});
//监听提交
form.on('submit(save)', function (data) {
layer.msg('正在保存中,请稍后...', {icon: 16,time: 1000*300,shadeClose: false});
$.post('./index.php?c=api&method=write_sys_settings&u='+u,data.field,function(data,status){
layer.closeAll();
if(data.code == 1) {
if(data.msg!="保存成功"){
layer.alert(data.msg)

View File

@@ -0,0 +1,83 @@
<?php $title='文章模板';$awesome=true; require 'header.php';
$site = unserialize(get_db('user_config','v',['uid'=>UID,'k'=>'s_site']));
?>
<style type="text/css">
.screenshot{
width: 99%;
height: 99%;
max-width: 100%;
max-height: 100%;
aspect-ratio:16/9;
}
#default #del {display: none;}
</style>
<body>
<div class="layuimini-container">
<div class="layuimini-main">
<blockquote class="layui-elem-quote layuimini-form" style="margin-top: 0px;border-left: 5px solid <?php echo $cache?"#1e9fff":($global_config['offline']?"":"#639d11") ?>;padding: 6px;">
<span class="layui-breadcrumb" lay-separator="|">
<a href="./index.php?c=admin&page=theme_article&cache=no&u=<?php echo U;?>">刷新数据</a>
</span>
</blockquote>
<div class="layui-bg-gray" style="padding: 1px;" >
<div class="layui-row layui-col-space15">
<?php
$Space = ' ';//占位符,强迫症想让输出的源码好看点而已...
foreach ($themes as $key => $theme) {
$online = !empty($theme['info']['md5']); //在线主题!
if($s_templates['article'] == $key){
$icon ='<i class="fa fa-magic" style="color: #03a9f4;" title = "正在使用"></i> ';
}else{
$icon ='';
}
$color = ($s_templates['article'] == $key ?"color: #03a9f4;":"");
?>
<!--主题卡片-->
<div class="layui-col-xs layui-col-sm4 layui-col-md3 ">
<div class="layui-card">
<div class="layui-card-header">
<div style="float:left; cursor:pointer;<?php echo $color; ?>" title="<?php echo $key; ?>"><?php echo $icon.$theme['info']['name']; ?></div>
<div style="float:right;cursor:pointer;" title="<?php echo $theme['info']['update']; ?>"><?php echo $theme['info']['version']; ?></div>
</div>
<div class="layui-card-body">
<div class="img-list"><img class="screenshot" layer-src="<?php echo $theme['info']['screenshot']; ?>" data-original="<?php echo $theme['info']['screenshot']; ?>"></div>
</div>
<div class="layui-card-header" style="height: 1px;"></div>
<div class="layui-card-header" style="height: auto;" id="article">
<div class="layui-btn-group" id="<?php echo $key;?>">
<?php
if($online){ //如果是在线主题则显示下载
echo $Space.'<button type="button" class="layui-btn layui-btn-sm layui-btn-danger" id="dw">下载</button>'."\n";
}elseif($theme['info']['up'] == 1){ //如果有更新则同时显示下载和使用
echo $Space.'<button type="button" class="layui-btn layui-btn-sm layui-btn-danger" id="up">更新</button>'."\n";
echo $Space.'<button type="button" class="layui-btn layui-btn-sm layui-btn-danger" id="set">使用</button>'."\n";
}else{ //其他情况仅显示使用
echo $Space.'<button type="button" class="layui-btn layui-btn-sm layui-btn-danger" id="set">使用</button>'."\n";
}
echo $Space.'<button type="button" class="layui-btn layui-btn-sm layui-btn-normal" id="detail">详情</button>'."\n";
if($theme['info']['config'] == '1'){ //支持配置的主题显示配置
echo $Space.'<button type="button" class="layui-btn layui-btn-sm layui-btn-normal" id="config">配置</button>'."\n";
}
if($USER_DB['UserGroup'] === 'root' && !$online){ //管理员&本地主题>显示删除
echo $Space.'<button type="button" class="layui-btn layui-btn-sm layui-btn-danger" id="del">删除</button>'."\n";
}
?>
</div>
</div>
</div>
</div>
<!--主题卡片End-->
<?php }?>
</div>
</div>
</div>
</div>
<script src = "<?php echo $libs;?>/jquery/jquery-3.6.0.min.js"></script>
<script src = "<?php echo $libs;?>/jquery/jquery.lazyload.min.js"></script>
<script src = "./templates/admin/js/public.js?v=<?php echo $Ver;?>"></script>
<?php load_static('js');?>
<script>var datas = <?php echo json_encode($themes)?>;</script>
<script src = "./templates/admin/js/theme.js?v=<?php echo $Ver;?>"></script>
</body>
</html>

View File

@@ -17,6 +17,7 @@
<a href="./index.php?c=admin&page=theme_home&cache=no&u=<?php echo U;?>" >刷新数据</a>
<a href="javascript:;" layuimini-content-href="theme_login" data-title="登录模板">登录模板</a>
<a href="javascript:;" layuimini-content-href="theme_transit" data-title="过渡模板">过渡模板</a>
<a href="javascript:;" layuimini-content-href="theme_article" data-title="文章模板">文章模板</a>
<?php if($USER_DB['UserGroup'] === 'root'){echo '<a href="javascript:;" layuimini-content-href="theme_register" data-title="注册模板">注册模板</a>';} ?>
<?php if($USER_DB['UserGroup'] === 'root'){echo '<a href="javascript:;" layuimini-content-href="theme_guide" data-title="引导页模板">引导页模板</a>';} ?>
</span>

View File

@@ -2,6 +2,41 @@
<body>
<div class="layuimini-container">
<div class="layuimini-main" style=" margin-left: 20px;">
<li class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis"></i>
<div class="layui-timeline-content layui-text">
<h4 class="layui-timeline-title">v2.0.33-20230802</h4>
<ul>
<li>[新增] 文章编辑新增封面上传功能,插入网络视频功能</li>
<li>[新增] 文章列表以链接的方式展现到主页( 已登录时显示公开和私有,未登录时显示公开文章 )</li>
<li>[新增] 文章列表新增批量操作,支持批量删除,批量修改文章分类和状态</li>
<li>[修复] 文章相关功能的已知问题</li>
<li>[变更] 移除文章功能的独立分类机制,改为使用链接分类 ( 已存在的文章需手动更新分类 )</li>
<li>[变更] API接口鉴权逻辑调整,新增几个兼容API,移除API模式中的兼容+开放模式</li>
<li>[变更] 默认主页模板右键对查看全部或文章链接操作给出提示,给文章链接添加黑色角标</li>
<li>[新增] 主页模板:简约主题 ( 需将安全设置>API模式>改为兼容模式才能使用全部功能 ) 作者:涂山</li>
<li>[新增] 主页模板:花森主页( 自带文章浏览功能 ),作者:花森JioJio</li>
<li>[新增] 文章模板:挽风导航,作者:凌云</li>
<li>[优化] 默认文章模板样式</li>
</ul>
</div>
</li>
<li class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis"></i>
<div class="layui-timeline-content layui-text">
<h4 class="layui-timeline-title">v2.0.32-20230727</h4>
<ul>
<li>[新增] 扩展功能新增简易文章管理 [ 半成品,尚未完善 ]</li>
<li>[新增] 链接自定义字段类型新增up_img,该类型支持上传1M大小的图片,权限与上传图标共享</li>
<li>[新增] 链接自定义字段新增提示内容</li>
<li>[变更] 主页模板前置处理,若模板支持链接扩展时提供扩展信息</li>
<li>[跟进] 支持onenav新版浏览器插件的兼容</li>
<li>[修复] ip统计存在异常的问题</li>
<li>[修复] 上传链接图标后端接口未限制大小</li>
<li>[修复] 在使用CDN的情况下可能出现授权验证问题</li>
</ul>
</div>
</li>
<li class="layui-timeline-item">
<i class="layui-icon layui-timeline-axis"></i>
<div class="layui-timeline-content layui-text">

View File

@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title><?php echo $theme;?> - 主题配置</title>
<link rel='stylesheet' href='<?php echo $layui['css']; ?>'>
<style>
.layui-form-item {margin-bottom: 10px;}
</style>
</style>
</head>
<body>
<div class="layui-row" style = "margin-top:18px;">
<div class="layui-container">
<div class="layui-col-lg8 layui-col-md-offset2">
<form class="layui-form" lay-filter="form">
<div class="layui-form-item">
<label class="layui-form-label">最大宽度</label>
<div class="layui-input-block">
<input type="text" name="container_width" placeholder="默认为空(全宽),输入格式80%或1280px" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item" style="padding-top: 10px;">
<div class="layui-input-block"><button class="layui-btn" lay-submit lay-filter="save">保存</button></div>
</div>
</form>
</div>
</div>
</div>
<script src="<?php echo $layui['js']; ?>"></script>
<script src="./templates/admin/js/public.js?v=<?php echo $Ver;?>"></script>
<script>
var u = _GET('u');
layui.use(['form'], function(){
var form = layui.form;var $ = layui.$;
form.val('form', <?php echo json_encode($theme_config);?>);
form.on('submit(save)', function(data){
$.post(get_api('write_theme','config') + '&t=' + _GET('theme'),data.field,function(data,status){
if(data.code == 1) {
layer.msg(data.msg, {icon: 1,time: 500,end: function() {if(_GET('source') != 'admin'){parent.location.reload();}}});
}else{
layer.msg(data.msg, {icon: 5});
}
});
return false;
});
});
</script>
</body>
</html>

View File

@@ -0,0 +1,68 @@
@charset "utf-8";
html{height: 100%;}
h1,h2,h3,h4,h5{
color: black;
}
li {
line-height: 2.2;
}
/*图片边距*/
img {
margin: 10px;
}
/*代码段样式*/
pre {
background-color: #f2f2f2;
border: 1px solid #ccc;
border-radius: 5px;
padding: 10px;
margin: 10px 0;
font-family: "Courier New", monospace;
font-size: 14px;
line-height: 1.5;
overflow-x: auto;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
}
/*表格样式*/
.mdui-table {
border-collapse: collapse;
width: 100%;
}
.mdui-table th,
.mdui-table td {
border: 1px solid #ccc;
padding: 8px;
text-align: center;
}
.mdui-table th::after,
.mdui-table td::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
right: -1px;
width: 1px;
background-color: #ccc;
}
/*a标签样式*/
.container a {
text-decoration: none;
color: inherit;
font-family: Arial, sans-serif;
color: #007bff;
padding: 5px 10px;
border-radius: 5px;
background-color: #f2f2f2;
}
.container a:hover {
color: #ff4500;
}
/*文章标题样式*/
.mdui-typo-title, .mdui-typo-title-opacity {
font-size: 1em;
}
/*prism 代码上色*/
code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="renderer" content="webkit"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=5.0">
<meta http-equiv="Cache-Control" content="no-siteapp"/>
<title><?php echo $data['title'];?> - <?php echo $site['title']; ?></title>
<meta name="keywords" content="<?php echo $data['summary']; ?>">
<meta name="description" content="<?php echo $data['summary']; ?>">
<link rel="shortcut icon" href="<?php echo $favicon;?>">
<link rel="stylesheet" href="<?php echo $libs?>/MDUI/v1.0.1/css/mdui.min.css">
<link rel="stylesheet" href="<?php echo $theme_dir?>/index.css">
</head>
<body class="mdui-drawer-body-left mdui-appbar-with-toolbar mdui-theme-primary-indigo mdui-theme-accent-pink mdui-theme-layout-auto">
<header class="appbar mdui-appbar mdui-appbar-fixed">
<div class="mdui-toolbar mdui-color-theme">
<span class="mdui-btn mdui-btn-icon mdui-ripple mdui-ripple-white" mdui-drawer="{target: '#main-drawer', swipe: true}">
<i class="mdui-icon material-icons">menu</i>
</span>
<a href="" class="mdui-typo-headline mdui-hidden-xs"><?php echo $site['logo'];?></a>
<a href="" class="mdui-typo-title"><?php echo $data['title'];?></a>
<div class="mdui-toolbar-spacer"></div>
</div>
</header>
<div class="mdui-drawer" id="main-drawer">
<div class="mdui-collapse-item-header mdui-list-item mdui-ripple" data_id="to_top">
<i class="mdui-list-item-icon mdui-icon material-icons mdui-text-color-blue">&#xe25a;</i>
<div class="mdui-list-item-content">文章开始</div>
</div>
<div class="mdui-collapse-item-header mdui-list-item mdui-ripple" data_id="to_bottom" id="to_bottom">
<i class="mdui-list-item-icon mdui-icon material-icons mdui-text-color-blue">&#xe258;</i>
<div class="mdui-list-item-content">文章结尾</div>
</div>
</div>
<div class="container p-download mdui-container" style="max-width: <?php echo $theme_config['container_width'];?> ;">
<?php echo $data['content'];?>
</div>
<script src="<?php echo $libs?>/MDUI/v1.0.1/js/mdui.min.js"></script>
<script src="<?php echo $libs?>/jquery/jquery-3.6.0.min.js"></script>
<script src="<?php echo $theme_dir?>/index.js"></script>
</body>
</html>

View File

@@ -0,0 +1,12 @@
{
"name":"默认",
"description":"系统默认的文章模板,支持代码段上色,支持自适应!",
"homepage":"https://gitee.com/tznb/TwoNav",
"version":"2.0.0",
"update":"2023/07/01",
"author":"TwoNav",
"screenshot":"https://img.lm21.top/article_default.jpg",
"config": {
"container_width":""
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@@ -192,10 +192,8 @@ body{
<!--定义一个卡片-->
<div class="mdui-card link-line mdui-hoverable CBC">
<!-- 如果是私有链接,则显示角标 -->
<?php if($link['property'] == 1 ) { ?>
<div class="angle">
<span> </span>
</div>
<?php if($link['property'] == 1 || $link['type'] == 'article') { ?>
<div class="angle" <?php echo $link['type'] == 'article' ? 'style="background: #000000;"':'';?>><span> </span></div>
<?php } ?>
<!-- 角标END -->
<a class="TFC" href="<?php echo $link['url']; ?>" target="_blank" <?php echo $protectA; ?> title = "<?php echo $link['description']; ?>">

View File

@@ -2,8 +2,8 @@
"name":"默认主题(加强)",
"description":"默认主题(加强)",
"homepage":"https://gitee.com/tznb/OneNav",
"version":"2.0.2",
"update":"2023/05/20",
"version":"2.0.3",
"update":"2023/07/31",
"author":"落幕",
"screenshot":"https://s3.bmp.ovh/imgs/2022/04/17/8cac968a8cc8135c.png",
"config": {

View File

@@ -33,17 +33,19 @@ var menu = {
var link_id = $(this).attr('id');
link_id = link_id.replace('id_','');
var tempwindow=window.open('_blank');
tempwindow.location='./index.php?c=click&id='+link_id+"&u="+u;
tempwindow.location = $(this).attr('link-url');
}},
"edit": {name: "编辑", icon: "edit",callback:function(key,opt){
var link_id = $(this).attr('id');
link_id = link_id.replace('id_','');
if(link_id == '0'){mdui.alert('非常规链接,无法操作');return true;}
var tempwindow=window.open('_blank');
tempwindow.location='./index.php?c=admin&page=link_edit&id='+link_id+"&u="+u;
}},
"delete": {name: "删除", icon: "delete",callback:function(){
var link_id = $(this).attr('id');
link_id = link_id.replace('id_','');
if(link_id == '0'){mdui.alert('非常规链接,无法操作');return true;}
mdui.confirm('确认删除?'
,function(){
$.post(get_api('write_link','del'),{lid:link_id},function(data,status){