Compare commits

..

2 Commits

Author SHA1 Message Date
MI15\Win
1d379543f5 v2.0.32-20230727 2023-07-28 00:19:25 +08:00
MI15\Win
0038e27493 v2.0.31-20230720 2023-07-20 14:03:00 +08:00
41 changed files with 1999 additions and 92 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{

View File

@@ -0,0 +1,9 @@
<?php if(!defined('DIR')){header('HTTP/1.1 404 Not Found');header("status: 404 Not Found");exit;}
$sql ="
ALTER TABLE `user_links` ADD `keywords` TEXT NOT NULL DEFAULT '' COMMENT '关键字' AFTER `weight` ;
";
if(exe_sql($sql)){
insert_db('updatadb_logs',['file_name'=>$file_name,'update_time'=>time(),'status'=>'TRUE','extra'=>'']);
}else{
msg(-1,'数据库更新失败');
}

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

@@ -0,0 +1,40 @@
<?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_categorys` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`uid` varchar(32) NOT NULL COMMENT '用户id',
`name` varchar(64) NOT NULL COMMENT '名称',
`weight` int(11) NOT NULL DEFAULT '0' COMMENT '权重',
`add_time` int(10) UNSIGNED NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) 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;
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,6 +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', '1689427853', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230723.php', '1690119053', 'TRUE', '');
-- 创建用户表
DROP TABLE IF EXISTS `global_user`;
@@ -109,6 +112,7 @@ CREATE TABLE IF NOT EXISTS `user_links` (
`url` text NOT NULL COMMENT '主链接',
`url_standby` text NOT NULL COMMENT '备用链接',
`weight` int(11) NOT NULL DEFAULT '0' COMMENT '权重',
`keywords` text NOT NULL DEFAULT '' COMMENT '关键字',
`description` text NOT NULL DEFAULT '' COMMENT '描述',
`icon` text NOT NULL DEFAULT '' COMMENT '图标',
`click` int(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '点击数',
@@ -193,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`;
@@ -272,4 +278,34 @@ 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_categorys` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`uid` varchar(32) NOT NULL COMMENT '用户id',
`name` varchar(64) NOT NULL COMMENT '名称',
`weight` int(11) NOT NULL DEFAULT '0' COMMENT '权重',
`add_time` int(10) UNSIGNED NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) 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,9 @@
<?php if(!defined('DIR')){header('HTTP/1.1 404 Not Found');header("status: 404 Not Found");exit;}
$sql ='
ALTER TABLE user_links ADD keywords TEXT(128) NOT NULL DEFAULT "";
';
if(exe_sql($sql)){
insert_db('updatadb_logs',['file_name'=>$file_name,'update_time'=>time(),'status'=>'TRUE','extra'=>'']);
}else{
msg(-1,'数据库更新失败');
}

View File

@@ -0,0 +1,40 @@
<?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_categorys" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"uid" integer(10) NOT NULL,
"name" text NOT NULL DEFAULT "",
"weight" integer NOT NULL,
"add_time" integer(10) NOT NULL,
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)
);
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,6 +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', '1689427853', 'TRUE', '');
INSERT INTO "updatadb_logs" ("file_name", "update_time", "status", "extra") VALUES ('20230723.php', '1690119053', 'TRUE', '');
-- 创建用户表
CREATE TABLE IF NOT EXISTS "global_user" (
@@ -93,6 +97,7 @@ CREATE TABLE IF NOT EXISTS "user_links" (
"url" TEXT(1024) NOT NULL,
"url_standby" text NOT NULL DEFAULT "",
"weight" integer(11) NOT NULL DEFAULT 0,
"keywords" TEXT(128) NOT NULL DEFAULT "",
"description" TEXT(128) NOT NULL DEFAULT "",
"icon" text NOT NULL DEFAULT "",
"click" integer(10) NOT NULL DEFAULT 0,
@@ -165,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" (
@@ -238,4 +245,30 @@ CREATE TABLE IF NOT EXISTS "global_icon" (
"extend" text NOT NULL DEFAULT "",
CONSTRAINT "id" UNIQUE ("id" ASC)
);
-- 用户文章分类
CREATE TABLE IF NOT EXISTS "user_article_categorys" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"uid" integer(10) NOT NULL,
"name" text NOT NULL DEFAULT "",
"weight" integer NOT NULL,
"add_time" integer(10) NOT NULL,
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

@@ -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

@@ -5,9 +5,10 @@ header("Access-Control-Allow-Headers: Access-Control-Allow-Private-Network,Conte
AccessControl();
//鉴权验证 Cookie验证通过,验证二级密码,Cookie验证失败时尝试验证token
if(!empty(trim($_REQUEST['token']))){ $_COOKIE = []; } //兼容浏览器插件,避免干扰
//获取请求方法
$method = htmlspecialchars(trim($_GET['method']),ENT_QUOTES);
$LoginConfig = unserialize($USER_DB['LoginConfig']);
if(!is_login()){
//没登录,根据API模式来限制
@@ -21,7 +22,7 @@ if(!is_login()){
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'])){
if(in_array($method,['link_list','get_a_link','q_category_link','category_list','get_a_category','check_login','app_info'])){
define('Access_Type','open'); //数据访问类型:仅开放
require 'api_compatible.php';
exit;
@@ -378,6 +379,7 @@ function write_link(){
$url = $_POST['url'];
$icon = empty($_POST['icon']) ? '' : $_POST['icon'];
$description = empty($_POST['description']) ? '' : $_POST['description'];
$keywords = empty($_POST['keywords']) ? '' : $_POST['keywords'];
$property = empty($_POST['property']) ? 0 : 1;
//检测链接是否合法
check_link($fid,$title,$url,$_POST['url_standby']);
@@ -390,7 +392,10 @@ function write_link(){
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'].'个字节');
}
//取最大链接ID
$lid = get_maxid('link_id');
//图标处理
@@ -416,6 +421,7 @@ function write_link(){
'title' => htmlspecialchars($title,ENT_QUOTES),
'url' => $url,
'url_standby' => $_POST['url_standby']??'',
'keywords' => htmlspecialchars($keywords,ENT_QUOTES),
'description' => htmlspecialchars($description,ENT_QUOTES),
'add_time' => time(),
'up_time' => time(),
@@ -425,7 +431,20 @@ function write_link(){
'property' => $property,
'icon' => $icon
];
//扩展字段
if($GLOBALS['global_config']['link_extend'] == 1 && check_purview('link_extend',1)){
$list = get_db("user_config","v",["k"=>"s_extend_list","uid"=>UID]);
if(!empty($list)){
$list = unserialize($list);
$extend = [];
foreach($list as $field){
$name = "_{$field['name']}";
if(isset($_POST[$name])){
$data['extend'][$name] = $_POST[$name];
}
}
}
}
//插入数据库
insert_db('user_links',$data);
msgA(['code'=>1,'msg'=>'添加成功','id'=>$lid]);
@@ -444,7 +463,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'];
//添加链接
@@ -498,7 +520,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();
@@ -537,6 +591,7 @@ function write_link(){
$title = $_POST['title'];
$url = $_POST['url'];
$icon = $_POST['icon'];
$keywords = empty($_POST['keywords']) ? '' : $_POST['keywords'];
$description = empty($_POST['description']) ? '' : $_POST['description'];
$property = empty($_POST['property']) ? 0 : 1;
//检测链接是否合法
@@ -546,6 +601,10 @@ function write_link(){
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(-1,'链接已存在!');}
//检查链接ID是否存在
@@ -557,6 +616,7 @@ function write_link(){
'title' => htmlspecialchars($title,ENT_QUOTES),
'url' => $url,
'url_standby' => $_POST['url_standby']??'',
'keywords' => htmlspecialchars($keywords,ENT_QUOTES),
'description' => htmlspecialchars($description,ENT_QUOTES),
'up_time' => time(),
'property' => $property,
@@ -576,7 +636,6 @@ function write_link(){
}
}
}
}
//非必须参数,未传递参数时
@@ -598,6 +657,9 @@ function write_link(){
if(!isset($_POST['pwd_id'])){
unset($data['pid']);
}
if(!isset($_POST['keywords'])){
unset($data['keywords']);
}
//更新数据
update_db('user_links',$data,['uid'=>UID,'lid'=>intval($_POST['lid']) ]);
msgA(['code'=>1,'msg'=>'修改成功','icon' => $icon]);
@@ -680,6 +742,116 @@ function write_link(){
if(empty($fid)){msg(-1,'分类ID错误');}
//加一个查找分类是否存在
update_db('user_links',['fid'=>$fid],['uid'=>UID ,"lid" => json_decode($_POST['lid']) ],[1,'设置成功']);
//检测是否满足要求
}elseif($_GET['type'] === 'msg_pull_check'){
if($global_config['offline']){
msg(-1,"离线模式不可用");
}
if(!is_subscribe('bool')){
msg(-1,"未检测到有效授权,无法使用该功能!");
}
if(intval($_POST['icon']) > 0){
if(!check_purview('icon_pull',1)){
msg(-1,'您所在的用户组,无法使用网站图标获取功能');
}
$path = DIR ."/data/user/".U."/favicon";
if(!Check_Path($path)){
msg(-1,'创建目录失败,请检查目录权限');
}
$config = unserialize( get_db("global_config", "v", ["k" => "icon_config"])) ?? [];
if($config['o_switch'] == '0'){
msg(-1,'相关服务处于关闭状态,请联系站长开启');
}
}
session_start();
$key = md5(uniqid().Get_Rand_Str(8));
$_SESSION['msg_pull']["$key"] = true;
msgA(['code'=>1,'msg'=>'success','key'=>$key]);
}elseif($_GET['type'] === 'msg_pull'){
session_start();
$key = $_POST['key'];
if(empty($key) || !$_SESSION['msg_pull']["$key"]){
msg(-1,'key验证失败,请重试!');
}elseif(empty($_POST['link_id'])){
msg(-1,'链接ID不能为空');
}
//读取信息
$link = get_db('user_links','*',['uid'=>UID ,'lid'=>$_POST['link_id'] ]);
//检查链接
if(empty($link)){
msg(-1,'链接ID不存在');
}elseif(!preg_match("/^(http:\/\/|https:\/\/).*/",$link['url'])){
msg(-1,'只支持识别http/https协议的链接!');
}elseif( !filter_var($link['url'], FILTER_VALIDATE_URL) ) {
msg(-1,'URL无效!');
}
//是否获取站点信息
if( ( intval($_POST['title']) + intval($_POST['keywords']) + intval($_POST['description']) ) > 0 ){
//读取长度限制配置
$length_limit = unserialize(get_db("global_config","v",["k"=>"length_limit"]));
//获取网站标题
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $link['url']);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($c, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36');
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($c , CURLOPT_TIMEOUT, 10);
$data = curl_exec($c);
curl_close($c);
require (DIR .'/system/get_page_info.php');
$info = get_page_info($data);
$new = [];
if(intval($_POST['title']) > 0 && !empty($info['site_title'])){
$new['title'] = $info['site_title'];
if($length_limit['l_name'] > 0 && strlen($new['title']) > $length_limit['l_name'] ){
$new['title'] = mb_substr($new['title'], 0, $length_limit['l_name'], 'utf-8');
}
}
if(intval($_POST['keywords']) > 0 && !empty($info['site_keywords'])){
$new['keywords'] = (empty($link['keywords']) || $_POST['keywords'] == '2') ? $info['site_keywords'] : $link['keywords'];
if($length_limit['l_key'] > 0 && strlen($new['keywords']) > $length_limit['l_key'] ){
$new['keywords'] = mb_substr($new['keywords'], 0, $length_limit['l_key'], 'utf-8');
}
}
if(intval($_POST['description']) > 0 && !empty($info['site_description'])){
$new['description'] = (empty($link['description']) || $_POST['description'] == '2') ? $info['site_description'] : $link['description'];
if($length_limit['l_desc'] > 0 && strlen($new['description']) > $length_limit['l_desc'] ){
$new['description'] = mb_substr($new['description'], 0, $length_limit['l_desc'], 'utf-8');
}
}
if(empty($new)){
$r['info'] = 'fail';
}else{
update_db('user_links',$new,['uid'=>UID ,"lid" => $link['lid'] ]);
$r['info'] = 'success';
}
}
//是否获取图标
if(intval($_POST['icon']) > 0){
//检查跳过已存在图标的链接
if($_POST['icon'] == '1' && !empty($link['icon'])){
$r['icon'] = 'skip';
}
$api = Get_Index_URL().'?c=icon&url='.base64_encode($link['url']);
$res = ccurl($api,30,true);
$data = get_db('global_icon','*',['url_md5'=>md5($link['url'])]);
if(empty($data)){
$r['icon'] = 'fail';
}
$new_path = "./data/user/".U.'/favicon/'.$data['file_name'];
if(copy("./data/icon/{$data['file_name']}",$new_path)){
update_db('user_links',['icon'=>$new_path],['uid'=>UID ,"lid" => $link['lid'] ]);
$r['icon'] = 'success';
}else{
$r['icon'] = 'fail';
}
}
msg(1,$r);
//图标拉取
}elseif($_GET['type'] === 'icon_pull'){
if($global_config['offline']){
@@ -739,7 +911,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' => '类型错误'] );
}
}
@@ -753,7 +925,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) {
@@ -1006,7 +1178,8 @@ function write_site_setting(){
function write_transit_setting(){
$datas = [
'visitor_stay_time'=>['int'=>true,'min'=>0,'max'=>60,'msg'=>'访客停留时间范围0-60'],
'admin_stay_time'=>['int'=>true,'min'=>0,'max'=>60,'msg'=>'管理员停留时间范围0-60']
'admin_stay_time'=>['int'=>true,'min'=>0,'max'=>60,'msg'=>'管理员停留时间范围0-60'],
'default_keywords'=>['int'=>true,'min'=>0,'max'=>1,'msg'=>'默认关键字参数错误']
];
foreach ($datas as $key => $data){
@@ -1135,7 +1308,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,"离线模式禁止下载主题!");} //离线模式
@@ -1256,6 +1429,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,'注册模板设置成功']);
@@ -1280,7 +1455,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
@@ -1480,6 +1655,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);
@@ -1581,9 +1758,11 @@ function read_data(){
$day_data = [];
array_push($day_data, ['name' => '访问量', 'type' => 'line', 'data' => []]);
array_push($day_data, ['name' => '点击量', 'type' => 'line', 'data' => []]);
array_push($day_data, ['name' => 'IP数', 'type' => 'line', 'data' => []]);
foreach ($dates as $date) {
array_push($day_data[0]['data'], get_db('user_count', 'v', ['uid' => UID, 'k' => $date, 't' => 'index_Ymd']) ?? 0);
array_push($day_data[1]['data'], get_db('user_count', 'v', ['uid' => UID, 'k' => $date, 't' => 'click_Ymd']) ?? 0);
array_push($day_data[2]['data'], get_db('user_count', 'v', ['uid' => UID, 'k' => $date, 't' => 'ip_count']) ?? 0);
}
$data = ['dates'=>$dates,'day_data'=>$day_data];
@@ -1596,6 +1775,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;
@@ -1615,6 +1805,7 @@ function other_get_link_info(){
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($c, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36');
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1); //允许重定向,解决http跳转到https无法识别
curl_setopt($c , CURLOPT_TIMEOUT, 5); //设置超时时间
$data = curl_exec($c);
@@ -1623,6 +1814,7 @@ function other_get_link_info(){
require (DIR .'/system/get_page_info.php');
$info = get_page_info($data);
$link['title'] = $info['site_title'];
$link['keywords'] = $info['site_keywords'];
$link['description'] = $info['site_description'];
msgA(['code'=>1,'data'=>$link]);
}

210
system/api_article.php Normal file
View File

@@ -0,0 +1,210 @@
<?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)$/',$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 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];
$where['ORDER']['weight'] = 'ASC';
$datas = select_db('user_article_list',['id','title','category','category_name','state','password','top','add_time','up_time','browse_count','summary'],$where);
$categorys = select_db('user_article_categorys',['id','name'],['uid'=>UID]);
foreach (select_db('user_article_categorys',['id','name'],['uid'=>UID]) as $data) {
$categorys[$data['id']] = $data['name'];
}
foreach ($datas as &$data) {
$data['category_name'] = $categorys[$data['category']];
}
msgA(['code'=>1,'count'=>$count,'data'=>$datas]);
}
//保存文章
function save_article(){
check_category($_POST['category']);$time = time();
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'=>'',
'extend'=>''
],[1,'保存成功']);
}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'],
],['uid'=>UID,'id'=>$_POST['id']],[1,'保存成功']);
}
}
//删除文章
function del_article(){
$id = json_decode($_POST['id']);
delete_db('user_article_list',['uid'=>UID,'id'=>$id],[1,'删除成功']);
}
//分类列表
function category_list(){
$where['uid'] = UID;
$where['ORDER']['weight'] = 'ASC';
$data = select_db('user_article_categorys',['id','name','weight','add_time'],$where);
msgA(['code'=>1,'count'=>count($data),'data'=>$data]);
}
//添加分类
function add_category(){
$name = trim($_POST['name']);
$time = time();
if(empty($name)){
msg(-1,'分类名称不能为空');
}
if(has_db('user_article_categorys',['uid'=>UID,'name'=>$name])){
msg(-1,'分类名称已存在');
}
insert_db('user_article_categorys',[
'uid'=>UID,
'name'=>$name,
'weight'=>0,
'add_time'=>$time
],[1,'添加成功']);
msg(-1,'添加失败');
}
//删除分类
function del_category(){
check_category($_POST['id']);
delete_db('user_article_categorys',['uid'=>UID,'id'=>$_POST['id']],[1,'删除成功']);
}
//保存分类
function save_category(){
check_category($_POST['id']);
update_db('user_article_categorys',['name'=>$_POST['name'],'weight'=>$_POST['weight']],['uid'=>UID,'id'=>$_POST['id']],[1,'更新成功']);
}
//检查分类
function check_category($id){
if(empty($id)){
msg(-1,'分类ID不能为空');
}
if(!has_db('user_article_categorys',['uid'=>UID,'id'=>$id])){
msg(-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 ( in_array($method,['link_list','get_a_link','q_category_link','category_list','get_a_category','check_login','add_link','app_info','del_link','global_search']) && function_exists($method) ) {
$method();
}else{
Amsg(-1,'方法未找到 >> '.$method);
@@ -42,6 +42,50 @@ function add_link(){
insert_db('user_links',$data);
msgA(['code'=>0,'id'=>$lid]);
}
//删除链接
function del_link(){
$lid = intval(trim($_REQUEST['id']));
if(empty($lid)){
msg(-1,'id不能为空');
}
$where['lid'] = $lid;
$where['uid'] = UID;
if(!has_db('user_links',$where)){
msg(-1,'链接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'];
$data = select_db('user_links',$field,$where);
// 查询出分类名称
$categorys = select_db('user_categorys',['cid(id)','name'],['uid'=>UID,'status'=>1]);
// 遍历分类以id作为键名
foreach ($categorys as $category) {
$newCategorys[$category['id']] = $category['name'];
}
// 遍历查询的数据,然后添加父级分类名称
foreach ($data as $key => $value) {
$data[$key]['category_name'] = $newCategorys[$value['fid']];
}
msgA(['code'=>0,'msg'=>'获取成功','count'=>count($data),'data'=>$data]);
}
//查询链接列表
function link_list(){
$page = empty(intval($_REQUEST['page'])) ? 1 : intval($_REQUEST['page']);
@@ -68,7 +112,6 @@ function get_a_link(){
$lid = intval(trim($_REQUEST['id']));
if(empty($lid)){
msg(-1,'id不能为空');
}
$where['lid'] = $lid;
$where['uid'] = UID;
@@ -135,6 +178,15 @@ function get_a_category(){
}
}
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'){

View File

@@ -521,7 +521,7 @@ function write_sys_settings(){
}
//长度限制
foreach (['c_name','c_desc','l_name','l_url','l_desc'] as $name){
foreach (['c_name','c_desc','l_name','l_url','l_key','l_desc'] as $name){
$length_limit[$name] = is_subscribe('bool') ? intval($_POST[$name]) : 0;
}
write_global_config("length_limit",$length_limit,'长度限制');
@@ -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 ?"保存成功,未检测到有效授权,带*号的配置无法为你保存":"保存成功")]);
}

View File

@@ -1,7 +1,8 @@
<?php if(!defined('DIR')){Not_Found();}AccessControl();
//负责过渡页/跳转/隐私保护/密码访问
$id = intval($_GET['id']);
//IP数统计
count_ip();
//如果id为空,则显示404
if(empty($id)){Not_Found();}
@@ -131,6 +132,19 @@ if($global_config['link_extend'] == 1 && check_purview('link_extend',1) && in_ar
//载入过渡页设置
$transition_page = unserialize(get_db("user_config", "v", ["uid"=>UID,"k"=>"s_transition_page"]));
//关键字处理
if(!empty($link['url_standby']) || $site['link_model'] == 'Transition'){
if(empty($link['keywords'])){
if($transition_page['default_keywords'] == '0'){
$link['keywords'] = $link['title'];
}else if($transition_page['default_keywords'] == '1'){
$link['keywords'] = $site['keywords'];
}else{
$link['keywords'] = $link['title'];
}
}
}
//如果存在备用链接,则强制载入过渡页
if(!empty($link['url_standby'])) {
$link['url_standby'] = unserialize($link['url_standby']);

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

@@ -0,0 +1,58 @@
<?php if(!defined('DIR')){Not_Found();}AccessControl();
$id = intval($_GET['id']);
//IP数统计
count_ip();
//如果id为空,则显示404
if(empty($id)){Not_Found();}
//查询文章
$where['uid'] = UID;
$where['state'] = 1; //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';
}
//统计点击数
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($dir_path.'/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

@@ -1,5 +1,4 @@
<?php
// 来源 https://blog.mimvp.com/article/23089.html
function get_page_info($output, $friend_link = '', $curl_info=array()) {
$page_info = array();
@@ -71,16 +70,39 @@ function get_page_info($output, $friend_link = '', $curl_info=array()) {
preg_match('/<META\s+content="([\w\W]*?)"\s+scheme="([\w\W]*?)"/si', $meta_str, $res);
if(!empty($res)) $meta_array[strtolower($res[2])] = $res[1];
// 20230716 新增匹配语法
preg_match('/<META\s+content=[\'"](.*?)[\'"]\s+itemprop=[\'"](.*?)[\'"]\s+name=[\'"](.*?)[\'"]>/si', $meta_str, $res);
if(!empty($res)) $meta_array[strtolower($res[3])] = $res[1];
preg_match('/<meta\s+itemprop=[\'"](.*?)[\'"]\s+name=[\'"](.*?)[\'"]\s+content=[\'"](.*?)[\'"]>/si', $meta_str, $res);
if(!empty($res)) $meta_array[strtolower($res[2])] = $res[3];
}
//如果正则匹配失败则使用php函数尝试再次匹配
if(empty($meta_array['keywords']) || empty($meta_array['description'])){
//将html保存为临时文件
$key = md5(uniqid().Get_Rand_Str(8));
$tempFile = DIR ."/data/temp/".md5(uniqid().Get_Rand_Str(8)).".html";
file_put_contents($tempFile, $output);
$tags = get_meta_tags($tempFile);
unlink($tempFile); //删除临时文件
if(empty($meta_array['keywords']) && !empty($tags['keywords'])){
$meta_array['keywords'] = $tags['keywords'];
}
if(empty($meta_array['description']) && !empty($tags['description'])){
$meta_array['description'] = $tags['description'];
}
}
$page_info['site_keywords'] = $meta_array['keywords'];
$page_info['site_description'] = $meta_array['description'];
//$page_info['meta_array'] = $meta_array; //暂时不需要全部meta
# 判断是否存在友链
if(!empty($friend_link) && strstr($output, $friend_link) != "") {
$page_info['friend_link_status'] = 1;
}
return $page_info;
}

View File

@@ -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;
@@ -198,6 +198,15 @@ function get_links($fid) {
//获取图标链接
$links[$key]['ico'] = $lock ? $GLOBALS['libs'].'/Other/lock.svg' : geticourl($site['link_icon'],$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($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']);
@@ -288,5 +297,6 @@ if(empty($_GET['share']) && !$site['ex_theme']){
//访问统计
write_user_count(date('Ym'),'index_Ym');
write_user_count(date('Ymd'),'index_Ymd');
count_ip();
//载入模板
require($index_path);

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'])){
@@ -739,4 +739,22 @@ function send_email($config){
msg(-1,'发送失败');
}
}
}
}
//统计访问ip数
function count_ip(){
$ip = Get_IP(); //取访客IP
$k = date('Ymd'); $t = 'ip_list';
$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,"e"=>$ip_list,'t'=>$t]);
}else{
update_db("user_count", ["e"=>$ip_list],['uid'=>UID,'t'=>$t,'k'=>$k]);
}
write_user_count($k,'ip_count');//访问ip数+1
}
}

View File

@@ -1 +1 @@
v2.0.30-20230713
v2.0.32-20230727

View File

@@ -29,8 +29,8 @@ layui.use(module, function () {
if(data.path != '' ){$("#iconurl").val(data.path);}
//如果勾选连续添加
if($("#continuity").is(":checked")){
//$('#reset').click();//完全清空
form.val('form',{'url':'','title':'','description':'','icon':''});
form.val('form',{'url':'','title':'','description':'','icon':'','keywords':''});
$('form input[name^="_"]').val(''); //扩展字段清空
$('#icon_img').attr('src', blank_img);//清除缩略图
layer.msg('添加成功', {icon: 1});
$("#url").focus();//URL获取输入焦点
@@ -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
});
@@ -233,6 +255,9 @@ function get_link_info() {
if(data.data.description != null) {
$("#description").val(data.data.description);
}
if(data.data.keywords != null) {
$("#keywords").val(data.data.keywords);
}
}else{
layer.msg(data.msg, {icon: 5});
}

View File

@@ -8,8 +8,8 @@ layui.use(['form','table','dropdown','miniTab'], function () {
var IDs = [];
var api = get_api('read_link_list'); //列表接口
var limit = localStorage.getItem(u + "_limit") || 50; //尝试读取本地记忆数据,没有就默认50
var link_sort = JSON.parse(localStorage.getItem(u + "_link_sort")) || {field: 'lid', type: null };
var pwds = [];
var field,order;
miniTab.listen();
//渲染表格
renderTable1();
@@ -81,21 +81,23 @@ layui.use(['form','table','dropdown','miniTab'], function () {
item.hide = local[item.field];
}
});
//渲染表格函数
var renderTable2 = function () {
where = link_sort.type === null ? {} : {field:link_sort.field,order:link_sort.type.toUpperCase()};
table.render({
elem: '#table'
,height: 'full-110' //自适应高度
,url: api //数据接口
,where: where
,page: true //开启分页
,limit:limit //默认每页显示行数
,limits: [20,50,100,300,500]
,even:true //隔行背景色
,loading:true //加载条
//,defaultToolbar:false
,toolbar: '#toolbar'
,id:'table'
,initSort: link_sort
,cols: [cols]
,method: 'post'
,response: {statusCode: 1 }
@@ -112,10 +114,9 @@ layui.use(['form','table','dropdown','miniTab'], function () {
$("[data-field='add_time']").addClass('layui-hide-xs');
$("[data-field='up_time']").addClass('layui-hide-xs');
$("[data-field='click']").addClass('layui-hide-xs');
//$(".layui-laypage .layui-laypage-count").css("padding-left","35px");
$(".layui-laypage .layui-laypage-prev").addClass('layui-hide-xs');
$(".layui-laypage .layui-laypage-curr").addClass('layui-hide-xs');
$(".layui-laypage .layui-laypage-next").addClass('layui-hide-xs');
// $(".layui-laypage .layui-laypage-prev").addClass('layui-hide-xs');
// $(".layui-laypage .layui-laypage-curr").addClass('layui-hide-xs');
// $(".layui-laypage .layui-laypage-next").addClass('layui-hide-xs');
$(".layui-laypage .layui-laypage-skip").addClass('layui-hide-xs');
$(".layui-table-tool-self").addClass('layui-hide-xs');
//加载加密分组数据
@@ -140,25 +141,23 @@ layui.use(['form','table','dropdown','miniTab'], function () {
});
// 监听表格排序事件
table.on('sort(table)', function(obj) {
field = obj.field; // 排序字段
order = obj.type == null ? '' : obj.type.toUpperCase(); // 排序方式asc,desc转为大写,null则默认排序
link_sort = {field:obj.field,type:obj.type};
localStorage.setItem(u + "_link_sort",JSON.stringify(link_sort));
link_search();
});
};
function link_search(){
var fid = document.getElementById("fid").value;
var keyword = document.getElementById("link_keyword").value;//获取输入内容
var property = document.getElementById("property").value;
var status = document.getElementById("status").value;
let data = form.val('form');
if(link_sort.type != null){
data.field = link_sort.field;
data.order = link_sort.type.toUpperCase();
}
table.reload('table', {
url: api
,method: 'post'
,request: {
pageName: 'page' //页码的参数名称
,limitName: 'limit' //每页数据量的参数名
}
,where: {query:keyword,fid:fid,property:property,status:status,field:field,order:order}
,request: {pageName: 'page',limitName: 'limit'}
,where: data
,page: {curr: 1}
});
}
@@ -321,8 +320,44 @@ layui.use(['form','table','dropdown','miniTab'], function () {
layer.msg(data.msg);
}
});
}else if(event === 'msg_pull'){
index = layer.open({type: 1,scrollbar: false,shadeClose: true,title: '批量识别链接信息',area : ['100%', '100%'],content: $('.msg_pull')});
}
});
$('#start_pull').click(function () {
let lits = table.checkStatus('table').data; console.log( lits );
let config = form.val('msg_pull');
let number = 0;
let total = lits.length;
let load_id = layer.load(1, {shade:[0.5,'#fff']});//加载层
let msg_id = layer.msg('正在识别中', {icon: 16,time: 1000*300}); //进度提示
//检查是否满足条件
$.post(get_api('write_link','msg_pull_check'),config,function(data,status){
if(data.code == 1){
config.key = data.key;
start_pull(number); //开始拉取
}else{
layer.alert(data.msg || '未知错误',{icon:5,title:'错误',anim: 2,closeBtn: 0,btn: ['刷新页面']},function () {location.reload();});
}
});
function start_pull(number){
if(number >= total){
layer.closeAll();
layer.alert('处理完毕,请刷新页面!' ,{icon:1,title:'提示',anim: 2,shadeClose: false,closeBtn: 0});
return true;
}
$("#layui-layer"+ msg_id+" .layui-layer-padding").html('<i class="layui-layer-face layui-icon layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i>[ ' + number + ' / ' + total + ' ] 正在处理中..');
config.link_id = lits[number].lid;
$.post(get_api('write_link','msg_pull'),config,function(data,status){
number ++;
start_pull(number);
});
}
return false;
});
table.render({
elem: '#link_extend_list'
@@ -341,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}
]]
});
@@ -495,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

@@ -41,11 +41,17 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">关键字</label>
<div class="layui-input-block">
<input type="text" id="keywords" name="keywords" placeholder="可留空" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">描述</label>
<div class="layui-input-block">
<textarea name="description" id="description" placeholder="请输入内容" class="layui-textarea"></textarea>
<textarea name="description" id="description" placeholder="可留空" class="layui-textarea"></textarea>
</div>
</div>

View File

@@ -0,0 +1,252 @@
<?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' ? '添加文章' : '编辑文章';
function echo_article_category(){
$where['uid'] = UID;
foreach (select_db('user_article_categorys','*',$where) as $category) {
echo "<option value=\"{$category['id']}\">{$category['name']}</option>";
}
}
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-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_article_category(); ?>
</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"><?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>
</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','group-video']}
const toolbar = createToolbar({
editor,
selector: '#toolbar-container',
config: toolbarConfig,
mode: 'default'
})
layui.use(['form'], function () {
var form = layui.form;
<?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;
});
$('#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,372 @@
<?php
if($global_config['article'] != 1 || !check_purview('article',1)){
require(DIR.'/templates/admin/page/404.php');
exit;
}
$title='文章列表';
function echo_article_category(){
$where['uid'] = UID;
foreach (select_db('user_article_categorys','*',$where) as $category) {
echo "<option value=\"{$category['id']}\">{$category['name']}</option>";
}
}
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_article_category(); ?>
</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 layui-hide-xs" lay-event="batch_del">删除选中</button>
<button class="layui-btn layui-btn-sm layui-btn-normal" lay-event="add_article">添加文章</button>
<button class="layui-btn layui-btn-sm layui-btn-normal" lay-event="category">分类管理</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="category" style="margin-top: 18px;display:none;padding-right: 10px;padding-left: 10px;">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-sm layui-btn-normal" lay-submit id="to_article_list">返回</button>
<button class="layui-btn layui-btn-sm layui-btn-normal" lay-submit id="add_category">添加</button>
<button class="layui-btn layui-btn-sm layui-btn-normal" lay-submit id="refresh_category">刷新</button>
<button class="layui-btn layui-btn-sm layui-btn-normal" lay-submit id="category_tip">权重提示</button>
</div>
<table id="category_list" lay-filter="category_list"></table>
</ul>
<ul class="edit_category" style="margin-top: 18px;display:none;padding-right: 10px;padding-left: 10px;">
<form class="layui-form" lay-filter="edit_category_form">
<input type="text" name="id" autocomplete="off" class="layui-input" style="display:none;">
<div class="layui-form-item">
<label class="layui-form-label" style="width: 40px;">名称</label>
<div class="layui-input-block" style="margin-left: 70px">
<input type="text" name="name" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label" style="width: 40px;">权重</label>
<div class="layui-input-block" style="margin-left: 70px">
<input type="number" name="weight" 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 id="save_category">保存</button>
</div>
</div>
</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'} //开启复选框
//,{field: 'id', title: 'ID', width:80, sort: true}
,{ title:'操作', toolbar: '#tablebar',width:110}
,{field: 'title', title: '标题', minWidth:200,templet: function(d){
return '<a style="color:#3c78d8" target="_blank" href="/index.php?c=article&id=' +d.id + '&u=' + u + '">'+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) {
//获取当前每页显示数量.并写入本都储存
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 search(){
let data = form.val('form');
table.reload('table', {
url: api
,method: 'post'
,request: {pageName: 'page',limitName: 'limit'}
,where: data
,page: {curr: 1}
});
}
//关键字回车搜索
$('#keyword').keydown(function (e){if(e.keyCode === 13){search();}});
//搜索按钮点击
$('#search').on('click', function(){search();});
//监听工具栏 - 文章列表
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: './index.php?c=admin&page=expand/article-edit&u=' + u,
end: function(){
search();
}
});
}else if(btn == 'category'){
category_index = layer.open({type: 1,scrollbar: false,shadeClose: true,title: false ,area : ['100%', '100%'],closeBtn:0,content: $('.category'),
success: function(layero, index, that){
category_list();
}
});
}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: './index.php?c=admin&page=expand/article-edit&id='+data.id+'&u=' + u,
end: function(){
search();
}
});
}
});
//监听行工具 - 分类列表
table.on('tool(category_list)', 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_category'),{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'){
form.val('edit_category_form', data);
edit_category_index = layer.open({type: 1,scrollbar: false,shadeClose: true,title: '编辑分类',area : ['auto', 'auto'],content: $('.edit_category')});
}
});
//添加分类
$('#add_category').click(function () {
add_category_index = layer.prompt({formType: 0,value: '',title: '请输入分类名称:',shadeClose: false,"success":function(){
$("input.layui-layer-input").on('keydown',function(e){
if(e.which == 13) {add_category();}
});
}},function(){
add_category()
});
});
//返回
$('#to_article_list').click(function () {
layer.close(category_index);
location.reload();
});
//刷新
$('#refresh_category').click(function () {
category_list();
});
//分类提示
$('#category_tip').click(function () {
layer.alert("权重越小越靠前",{title:'提示',anim: 2,closeBtn: 0});
});
//编辑分类-保存
$('#save_category').click(function () {
$.post(get_api('write_article','save_category'),form.val('edit_category_form'),function(data,status){
$("input.layui-layer-input").val("");
if(data.code == 1) {
category_list();
layer.msg('操作成功', {icon: 1});
layer.close(edit_category_index);
}else{
$("input.layui-layer-input").focus();
layer.msg(data.msg || '未知错误',{icon: 5});
}
});
return false;
});
function add_category(){
let name = $("input.layui-layer-input").val();
if(name == ''){ return false; }
$("*").blur();
let loading = layer.msg('正在添加文章分类,请稍后..', {icon: 16,time: 1000*300,shadeClose: false});
$.post(get_api('write_article','add_category'),{'name':name},function(data,status){
layer.close(loading); layer.close(add_category_index);
$("input.layui-layer-input").val("");
if(data.code == 1) {
category_list();
layer.msg('操作成功', {icon: 1});
}else{
$("input.layui-layer-input").focus();
layer.msg(data.msg || '未知错误',{icon: 5});
}
});
}
function category_list(){
table.render({
elem: '#category_list'
,height: 'full-70'
,url: get_api('read_article','category_list')
,page: false
,limit:999
,limits: [999]
,even:true
,loading:true
,id:'category_list'
,cols: [[
{title:'操作', toolbar: '#tablebar', width:110}
,{field: 'name', title: '分类名称', minWidth:200,width:300}
,{field: 'weight', title: '权重', minWidth:100,width:160}
]]
,method: 'post'
,response: {statusCode: 1 }
,done: function (res, curr, count) {
//获取当前每页显示数量.并写入本都储存
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);
}
}
});
}
});
</script>
</body>
</html>

View File

@@ -366,7 +366,7 @@ if($USER_DB['UserGroup'] == 'root'){
if(data.code == 1){
var optionRecords = {
tooltip: {trigger: 'axis'},
legend: {data:['访问量','点击量']},
legend: {data:['访问量','点击量','IP数']},
grid: {left: '3%',right: '4%',bottom: '3%',containLabel: true},
xAxis: {
type: 'category',

View File

@@ -79,14 +79,25 @@
</li>
</ul>
</div>
<div class="layui-form-item">
<label class="layui-form-label">关键字</label>
<div class="layui-input-block">
<input type="text" id="keywords" name="keywords" placeholder="可留空" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">描述</label>
<div class="layui-input-block">
<textarea name="description" id="description" placeholder="请输入内容" class="layui-textarea"></textarea>
<textarea name="description" id="description" placeholder="可留空" class="layui-textarea"></textarea>
</div>
</div>
<?php
//判断全局是否开启扩展
if($global_config['link_extend'] && check_purview('link_extend',1)){
require 'link_extend.php';
}?>
<div class="layui-form-item">
<div class="layui-input-block">
<input type="checkbox" id="continuity" lay-skin="primary" title="连续添加">

View File

@@ -1,5 +1,5 @@
<?php
$link = get_db('user_links',['lid','fid','pid(pwd_id)','property','title','url','url_standby','description','icon'],['uid'=>UID,'lid'=>$_GET['id']]);
$link = get_db('user_links',['lid','fid','pid(pwd_id)','property','title','url','url_standby','keywords','description','icon'],['uid'=>UID,'lid'=>$_GET['id']]);
if(empty($link)){
require(DIR.'/templates/admin/page/404.php');
exit;
@@ -92,11 +92,18 @@ $title='编辑链接';$awesome=true; require 'header.php';
</li>
</ul>
</div>
<div class="layui-form-item">
<label class="layui-form-label">关键字</label>
<div class="layui-input-block">
<input type="text" id="keywords" name="keywords" placeholder="可留空" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">描述</label>
<div class="layui-input-block">
<textarea name="description" id="description" placeholder="请输入内容" class="layui-textarea"></textarea>
<textarea name="description" id="description" placeholder="可留空" class="layui-textarea"></textarea>
</div>
</div>
<?php

View File

@@ -13,19 +13,22 @@ if(!empty($list)){
foreach ($list as $data) {
$field = "_".$data['name'];
$data['value'] = isset($extend_data[$field]) ? $extend_data[$field] : $data['default'];
$link["_{$data['name']}"] = ''.htmlentities($data['value']);
if($data['type'] == 'text'){
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
@@ -33,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

@@ -5,11 +5,11 @@
<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">
<select id="fid" lay-filter="fid" name="categorys" lay-search>
<select name="fid" lay-search>
<option value="0" selected="">全部</option>
<optgroup label="用户分类">
<?php echo_category(true); ?>
@@ -21,21 +21,20 @@
<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="link_keyword" placeholder='请输入标题或描述或URL' value=''autocomplete="off" >
<input class="layui-input" name="query" id="link_keyword" placeholder='请输入标题或描述或URL' 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 id="property" >
<select name="property" >
<option value="" selected>不限</option>
<option value="0" >公开</option>
<option value="1" >私有</option>
</select>
</div>
<div class="layui-input-inline" style=" width: 80px; ">
<select id="status" >
<select name="status" >
<option value="" selected>不限</option>
<option value="0" >禁用</option>
<option value="1" >启用</option>
@@ -43,12 +42,12 @@
</div>
</div>
<div class="layui-inline layui-form" style="padding-bottom: 5px;">
<button class="layui-btn layui-btn-normal " id="link_search" style="height: 36px;">搜索</button>
<button class="layui-btn layui-btn-normal "type="button" id="link_search" style="height: 36px;">搜索</button>
</div>
<span id = "testing_tip" style = "display:none;">测试中...</span>
<span id = "subscribe" style = "display:none;"><?php echo is_subscribe('bool')?'1':'0' ?></span>
<table id="table" class="layui-table" lay-filter="table" style="margin: 1px 0;"></table>
</form>
<table id="table" class="layui-table" lay-filter="table" style="margin: 1px 0;"></table>
</div>
</div>
<!-- 操作列 -->
@@ -75,9 +74,7 @@
<?php if($global_config['offline'] != 1 ){ ?>
<button class="layui-btn layui-btn-sm layui-btn-normal layui-btn-danger layui-hide-xs" lay-event="testing" id="testing">检测</button>
<?php }?>
<?php if($global_config['offline'] != 1 && check_purview('icon_pull',1)){ ?>
<button class="layui-btn layui-btn-sm layui-btn-normal layui-btn-danger layui-hide-xs" lay-event="icon_pull" id="icon_pull">图标拉取</button>
<?php }?>
<button class="layui-btn layui-btn-sm layui-btn-normal layui-btn-danger layui-hide-xs" lay-event="msg_pull" id="msg_pull">识别</button>
<button class="layui-btn layui-btn-sm layui-btn-normal layui-btn-danger" layuimini-content-href="link_sort" data-title="链接排序">排序模式</button>
</div>
</script>
@@ -116,5 +113,55 @@
</div>
</script>
</ul>
<ul class="msg_pull" style="margin-top: 18px;display:none;padding-right: 10px;padding-left: 10px;">
<form class="layui-form layuimini-form" lay-filter="msg_pull">
<pre class="layui-code" id="tip" >提示: 自动识别仅针对http/https有效,且不能保证百分百成功!未成功识别时不会对链接信息进行修改!大批量识别前建议先备份数据,效果不理想时可以回退!</pre>
<div class="layui-form-item">
<label class="layui-form-label">网站标题</label>
<div class="layui-input-inline">
<select name="title" >
<option value="0">保持不变</option>
<option value="1">获取 (覆盖)</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">关键字</label>
<div class="layui-input-inline">
<select name="keywords" >
<option value="0">保持不变</option>
<option value="1" selected>获取 (未填关键字时)</option>
<option value="2">获取 (覆盖)</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">网站描述</label>
<div class="layui-input-inline">
<select name="description" >
<option value="0">保持不变</option>
<option value="1" selected>获取 (未填描述时)</option>
<option value="2">获取 (覆盖)</option>
</select>
</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" selected>获取 (未上传图标时)</option>
<option value="2">获取 (覆盖)</option>
</select>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-warm" type="button" id="close" >关闭</button>
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="start_pull" id="start_pull">开始</button>
</div>
</div>
</form>
</ul>
</body>
</html>

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,9 +251,19 @@ $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表示不限制!</blockquote>
<blockquote class="layui-elem-quote layui-text" style="">程序采用UTF8编码,一个汉字约占用3个字节!英文字母和数组占用1个字节!值为0表示不限制!<br />添加或编辑时长度超限则不允许添加,批量识别时超限则截断</blockquote>
<div class="layui-form-item">
<label class="layui-form-label required">分类名称</label>
<div class="layui-input-inline">
@@ -282,6 +292,13 @@ $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">
<input type="number" name="l_key" autocomplete="off" value="0" class="layui-input">
</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">
@@ -328,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

@@ -10,7 +10,7 @@
<div class="layui-input-inline">
<input type="number" min="0" max="60" lay-verify="required|number" name="visitor_stay_time" value = "3" autocomplete="off" placeholder="访客停留时间单位s" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">访客停留时间单位秒</div>
<div class="layui-form-mid layui-word-aux">访客停留时间,单位秒(需模板支持)</div>
</div>
<div class="layui-form-item">
@@ -18,7 +18,18 @@
<div class="layui-input-inline">
<input type="number" min="0" max="60" lay-verify="required|number" name="admin_stay_time" value = "5" autocomplete="off" placeholder="管理员停留时间单位s" class="layui-input">
</div>
<div class="layui-form-mid layui-word-aux">管理员停留时间单位秒</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="default_keywords" >
<option value="0">链接标题</option>
<option value="1">站点关键字</option>
</select>
</div>
<div class="layui-form-mid layui-word-aux">指链接信息未填写关键字时选择其他值作为关键字</div>
</div>
<div class="layui-form-item">

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,42 @@
<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.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">
<h4 class="layui-timeline-title">v2.0.31-20230720</h4>
<ul>
<li>[新增] 支持统计访问IP数,可在后台概要页报表统计展示</li>
<li>[新增] 数据库链接表新增关键字列</li>
<li>[新增] 添加/编辑链接页面新增关键字输入,用于过渡页SEO优化 (注:230715之前的过度模板固定用链接标题作为关键字)</li>
<li>[新增] 过度模板设置新增默认关键字选项 (针对未填写关键字时选择其他值作为关键字,需更新过度页模板)</li>
<li>[新增] 链接列表新增识别按钮,用于批量获取URL的标题/描述/关键字/图标</li>
<li>[新增] 系统设置中新增链接关键字长度限制</li>
<li>[新增] 链接列表排序模式支持记忆到客户端</li>
<li>[新增] 已开启链接扩展字段时,添加链接时支持填写扩展字段 (原仅编辑支持)</li>
<li>[修复] 编辑链接时重置按钮未对扩展内容重置</li>
<li>[优化] 添加/编辑链接页面识别功能支持关键字识别</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">

View File

@@ -0,0 +1,145 @@
@charset "utf-8";
html{height: 100%;}
body{margin: 0;background: #0D1721;font-family:'pingfang SC','helvetica neue',arial,'hiragino sans gb','microsoft yahei ui','microsoft yahei',simsun,sans-serif;font-size:16px;line-height: 140%;color: #ddd;}
ul, ol, li,dt,dd{margin:0; padding:0;list-style: none;}
dl{margin-top:0; margin-bottom:0;}
p{margin:0 0 10px;}
img{border: 0; vertical-align:middle;max-width: 100%;}
img.img-responsive{width: 100%;}
input{outline: medium none;outline: none;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}
input::-webkit-input-placeholder, textarea::-webkit-input-placeholder { color: #8A8A8A;}
input:focus{border-color:#FF9900; -webkit-box-shadow:inset 0 1px 1px rgba(255,136,0,.075),0 0 8px rgba(255,136,0,.6);}
/* container */
*{-webkit-box-sizing:border-box; -moz-box-sizing:border-box; box-sizing:border-box}
:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
.container {width: 75%;position: relative;padding-right: 15px;padding-left: 15px;margin: 0 auto;}
.row{position: relative; margin-right: -15px; margin-left: -15px;}
.container:before,.container:after,.row:before,.row:after,.clearfix:before, .clearfix:after{ display: table; content: " "; clear: both;}
/* text */
h1{ font-size:22px; line-height: 28px;}
h2{ font-size:20px; line-height: 26px;}
h3{ font-size:18px; line-height: 24px;}
h4{ font-size:16px; line-height: 22px;}
h5{ font-size:14px; line-height: 20px;}
h6{ font-size:12px; line-height: 18px;}
h1,h2,h3,h4,h5,h6{ font-weight: 400; margin-top:10px; margin-bottom:10px}
a,button{ text-decoration:none; outline:none; -webkit-tap-highlight-color:rgba(0,0,0,0)}
a,h1, h2, h3, h4, h5, h6{ color: #8A8A8A;}
a,h1{color: #ffffff;}
a{color: #b1edff;}
a:focus,a:hover,a:active{text-decoration:none;color: #FF9900;}
.col-pd{ padding: 15px 20px;}
.text-muted{ color: #999;}
.split-line{display: inline-block; margin-left: 12px; margin-right: 12px; width: 1px; height: 14px; vertical-align: -2px; background: #636060;}
.news-title{
border-bottom: 1px solid #4f4f4f !important;
padding-bottom: 12px;
}
/* header */
.newbui-header__top{position: relative;height: 100px;padding: 0 20px;}
.newbui-header__logo{float:left; margin-right: 120px;}
.newbui-header__logo{width: auto;margin-top: 20px;}
.newbui-header__logo .logo{display:block;width: auto;height:60px;}
.newbui-header__search{float: right;position:relative;width:280px;margin-top: 32px;}
.newbui-header__search .form-control{display:block;width:100%;height: 35px;padding:6px 45px 6px 10px;font-size:12px;line-height:32px;border-radius: 5px;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;background: #2D2F36;color: #8A8A8A;-webkit-text-fill-color: #8A8A8A;border: 0;}
.newbui-header__search .submit{display:block; position:absolute; top: 0; right: 0; width:35px; height:35px; border: 0; cursor: pointer; background: url(img/icon_seacrh.png) center no-repeat;}
.newbui-header__bar{position:relative;margin: 0;background: #223855;color: #191A20;box-shadow: 0 5px 10px #000;}
.newbui-header__menu > li{ position: relative; float:left;}
.newbui-header__menu > li > a{display:inline-block; padding: 15px 30px; font-size:15px; color: #fff;}
.newbui-header__menu > li > a:hover {background: #191A20;color: #FF9900;}
.newbui-header__menu > li.active > a{background: #191A20; color: #fff;}
.newbui-header__menu li .dropdown{display: none;width: 100%;position: absolute;z-index: 999;top: 100%;right: 0;text-align: center;font-size: 12px;color: #999;background: #2D2F36;box-shadow: 0 2px 8px rgba(0,0,0,.1);}
.newbui-header__menu li .dropdown li{ padding: 8px 0; border-top: 1px solid #2D2F36;}
.newbui-header__menu li .dropdown li:first-child{ padding-top: 15px; border-top: 0;}
.newbui-header__menu li .dropdown li:last-child{ padding-bottom: 15px;}
.newbui-header__menu li a{ font-size: 14px;}
.newbui-header__menu li:hover .dropdown{ display: block;}
.newbui-header__more{float: left;padding-top: 20px;width: 250px;}
.newbui-header__more li{margin-bottom: 5px;color: #ddd;}
.newbui-header__more li .text{ display: inline-block; width: 60px; color: #fff;}
/* pannel */
.newbui-pannel{position: relative;margin-top: 30px;background: #0D1721;border-radius: 5px;border: 1px solid #2D2F36;}
.newbui-pannel-left{ float: left; width: 70%;}
.newbui-pannel-side{ float: left; width: 30%;}
.newbui-pannel__head{padding: 15px 20px;line-height: 25px;border-bottom: 1px solid #2D2F36;}
.newbui-pannel__head .title{ margin: 0;}
.newbui-pannel__foot{ padding: 15px 20px;}
/* more */
.margin-0{ margin: 0 !important;}
.padding-0{ padding: 0 !important;}
.pull-left{ float: left !important;}
.pull-right{ float: right !important;}
.hide,.visible-lg, .visible-md, .visible-sm, .visible-xs, .visible-mi{ display: none !important;}
.newbui-foot{ padding: 20px; text-align: center; color: #999;}
.pc{display: block!important;}
.m{display: none!important;}
.navbar-light {
color: #fff !important;
font-size: 16px;
/*font-weight: bold;*/
text-shadow: 0px 1px 0px #000
}
@media (min-width: 1200px){
.visible-lg { display: block !important;}
.hidden-lg {display: none !important;}
}
@media (max-width: 1199px) and (min-width: 992px){
.visible-md { display: block !important;}
.hidden-md {display: none!important;}
}
@media (max-width: 991px) and (min-width: 768px){
.visible-sm{ display: block !important;}
.hidden-sm {display: none !important;}
}
@media (max-width: 1023px){
.container{ width: 100%; padding-right: 30px; padding-left: 30px;}
}
@media (max-width:767px){
.visible-xs { display: block !important;}
.hidden-xs {display: none!important;}
.container{ padding: 0;}
.row{ margin: 0;}
.col-pd{ padding: 10px;}
/* header */
.newbui-header__top{ height: 60px; padding:0 10px;}
.newbui-header__logo{margin: 12px 0 0;padding: 0;}
.newbui-header__logo .logo{width: 148px; height:35px;}
.newbui-header__search{ float: none; width: auto; margin: 0; position: absolute; top: 15px; right: 10px; left: 168px;}
.newbui-header__search .form-control{ height: 30px; line-height: 30px; border-radius: 5px; padding:6px 40px 6px 10px; border: 0;}
.newbui-header__search .submit{ width: 30px; height: 30px;}
.newbui-header__bar{ box-shadow: none;}
.newbui-header__menu { position:relative; margin: 0; overflow: auto; white-space:nowrap; overflow-y:hidden;overflow-x:scroll; -webkit-overflow-scrolling:touch}
.newbui-header__menu > li{ float: none; display: inline-block;}
.newbui-header__menu > li > a{ padding: 10px 15px; font-size: 14px;}
.newbui-header__menu li:hover .dropdown{ display: none;}
/* pannel */
.newbui-pannel{ margin-top: 10px; border: 0; border-radius: 0; box-shadow: none;}
.newbui-pannel__head{ padding: 10px; line-height: 25px; border-bottom: 1px solid #2D2F36;}
.newbui-pannel__head .title{ font-size: 16px;}
.newbui-pannel__foot{ padding: 10px;}
.pc{
display: none!important;
}
.m{
display: block!important;
}
}

View File

@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title><?php echo $data['title'];?></title>
<meta name="keywords" content="<?php echo $data['summary']; ?>">
<meta name="description" content="<?php echo $data['summary']; ?>">
<link rel="stylesheet" href="<?php echo $theme_dir?>/index.css?v=<?php echo $theme_ver; ?>" type="text/css" media="all" />
<link rel="shortcut icon" href="<?php echo $favicon;?>">
</head>
<body>
<div class="newbui-header__bar clearfix">
<div class="container">
<div class="row">
<ul class="newbui-header__menu clearfix">
<li class="pc"><a class="navbar-light" href="./index.php?u=<?php echo $GLOBALS['u'];?>">首页</a></li>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="newbui-pannel clearfix">
<div class="newbui-pannel-box clearfix">
<div class="newbui-pannel_bd col-pd clearfix">
<h1 class="news-title"><?php echo $data['title'];?></h1>
<div class="news-content">
<?php echo $data['content'];?>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="newbui-foot clearfix">
<p class="text-muted">
<?php echo $copyright.PHP_EOL;?>
<?php echo $ICP.PHP_EOL;?>
</p>
<?php echo $site['custom_footer'].PHP_EOL;?>
<?php echo $global_config['global_footer'].PHP_EOL;?>
</div>
</body>
</html>

View File

@@ -0,0 +1,9 @@
{
"name":"默认",
"description":"待优化",
"homepage":"https://gitee.com/tznb/TwoNav",
"version":"2.0.0",
"update":"2023/07/27",
"author":"TwoNav",
"screenshot":"https://s3.bmp.ovh/imgs/2022/04/17/8cac968a8cc8135c.png"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<title><?php echo $link['title']; ?> - <?php echo $site['title']; ?></title>
<meta name="keywords" content="<?php echo $link['title']; ?>" />
<meta name="keywords" content="<?php echo $link['keywords']; ?>" />
<meta name="description" content="<?php echo $link['description']; ?>" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="<?php echo $libs?>/bootstrap4/css/bootstrap.min.css" type="" media=""/>

View File

@@ -2,8 +2,8 @@
"name":"OneNav1",
"description":"OneNav旧版过渡页",
"homepage":"https://www.xiaoz.me",
"version":"2.0.1",
"update":"2023/04/05",
"version":"2.0.2",
"update":"2023/07/16",
"author":"xiaoz",
"screenshot":"https://s3.bmp.ovh/imgs/2022/04/17/8cac968a8cc8135c.png",
"config": {