Compare commits

...

14 Commits

Author SHA1 Message Date
taoser
78a9655d10 2.3.10 2023-08-02 19:41:11 +08:00
taoser
0c2f0154a8 修复内容加密泄露 2023-07-03 12:56:37 +08:00
taoser
74ab2ac512 comment level 2023-07-03 12:54:48 +08:00
taoser
868797f0bb nav&top 2023-07-03 12:52:34 +08:00
taoser
ac854d627d comment 2023-07-03 12:50:57 +08:00
taoser
6a735f6fc8 upload 2023-07-03 12:49:15 +08:00
taoser
d3bfb9b3c3 2.3.4 2023-05-05 12:09:57 +08:00
taoser
0c8ebe8290 2.3.3 2023-05-05 12:08:35 +08:00
taoser
0dc8798850 2.3.2 2023-05-05 12:07:11 +08:00
taoser
300c9e6a72 2.3.1 2023-05-05 12:06:07 +08:00
taoser
3dbc77904e 2.3.0 2023-05-05 12:04:46 +08:00
taoser
a825153e2e 2.2.10 2023-05-05 12:03:45 +08:00
taoser
599adb73d2 2.2.9 2023-05-05 12:02:44 +08:00
taoser
06b783c1e7 2.2.8 2023-05-05 12:01:49 +08:00
240 changed files with 10819 additions and 6593 deletions

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="keywords" content="fly,layui,前端社区">
<meta name="description" content="Fly社区是模块化前端UI框架Layui的官网社区致力于为web开发提供强劲动力">
<link rel="stylesheet" href="/static/layui/css/layui.css">
<link rel="stylesheet" href="/layui-1/css/layui.css">
<link rel="stylesheet" href="/static/res/css/global.css" charset="utf-8">
</head>
<body>
@ -22,8 +22,8 @@
</div>
<include file="./footer" />
<script src="/static/layui/jquery.min.js" charset="utf-8"></script>
<script src="/static/layui/layui.js" charset="utf-8"></script>
<script src="/layui-1/jquery.min.js" charset="utf-8"></script>
<script src="/layui-1/layui.js" charset="utf-8"></script>
<script>
layui.cache.user = {

View File

@ -100,102 +100,6 @@ abstract class BaseController
return $v->failException(true)->check($data);
}
/**
* 操作错误跳转
* @param mixed $msg 提示信息
* @param string $url 跳转的URL地址
* @param mixed $data 返回的数据
* @param integer $wait 跳转等待时间
* @param array $header 发送的Header信息
* @return void
*/
protected function error($msg = '', string $url = null, $data = '', int $wait = 3, array $header = []): Response
{
if (is_null($url)) {
$url = request()->isAjax() ? '' : 'javascript:history.back(-1);';
} elseif ($url) {
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : app('route')->buildUrl($url);
}
$result = [
'code' => 0,
'msg' => $msg,
'data' => $data,
'url' => $url,
'wait' => $wait,
];
$type = (request()->isJson() || request()->isAjax()) ? 'json' : 'html';
if ('html' == strtolower($type)) {
$type = 'jump';
}
$response = Response::create($result, $type)->header($header)->options(['jump_template' => app('config')->get('app.dispatch_error_tmpl')]);
throw new HttpResponseException($response);
}
/**
* 返回封装后的API数据到客户端
* @param mixed $data 要返回的数据
* @param integer $code 返回的code
* @param mixed $msg 提示信息
* @param string $type 返回数据格式
* @param array $header 发送的Header信息
* @return Response
*/
protected function result($data, int $code = 0, $msg = '', string $type = '', array $header = []): Response
{
$result = [
'code' => $code,
'msg' => $msg,
'time' => time(),
'data' => $data,
];
$type = $type ?: 'json';
$response = Response::create($result, $type)->header($header);
throw new HttpResponseException($response);
}
/**
* 操作成功跳转
* @param mixed $msg 提示信息
* @param string $url 跳转的URL地址
* @param mixed $data 返回的数据
* @param integer $wait 跳转等待时间
* @param array $header 发送的Header信息
* @return void
*/
protected function success($msg = '', string $url = null, $data = '', int $wait = 3, array $header = []): Response
{
if (is_null($url) && isset($_SERVER["HTTP_REFERER"])) {
$url = $_SERVER["HTTP_REFERER"];
} elseif ($url) {
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : app('route')->buildUrl($url);
}
$result = [
'code' => 1,
'msg' => $msg,
'data' => $data,
'url' => $url,
'wait' => $wait,
];
$type = (request()->isJson() || request()->isAjax()) ? 'json' : 'html';
// 把跳转模板的渲染下沉,这样在 response_send 行为里通过getData()获得的数据是一致性的格式
if ('html' == strtolower($type)) {
$type = 'jump';
}
$response = Response::create($result, $type)->header($header)->options(['jump_template' => app('config')->get('app.dispatch_success_tmpl')]);
throw new HttpResponseException($response);
}
//显示网站设置
protected function getSystem()
{
@ -264,148 +168,6 @@ abstract class BaseController
return $domain . $articleUrl;
}
/**
* 关键词
* 通过百度分词接口获取关键词或者标签
* flag 1.为word时获取分词2.为tag时获取标签
*
* @return array
*/
public function setKeywords($data)
{
$keywords = [];
// 百度分词自动生成关键词
if(!empty(config('taoler.baidu.client_id')) == true) {
//headers数组内的格式
$headers = array();
$headers[] = "Content-Type:application/json";
switch($data['flag']) {
//分词
case 'word':
$url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?charset=UTF-8&access_token='.config('taoler.baidu.access_token');
$body = ["text" => $data['keywords']];
break;
//标签
case 'tag':
$url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/keyword?charset=UTF-8&access_token='.config('taoler.baidu.access_token');
$body = ['title' => $data['keywords'], 'content'=>$data['content']];
break;
default:
$url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?charset=UTF-8&access_token='.config('taoler.baidu.access_token');
$body = ["text" => $data['keywords']];
}
$postBody = json_encode($body);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);//设置请求头
curl_setopt($curl, CURLOPT_POSTFIELDS, $postBody);//设置请求体
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');//使用一个自定义的请求信息来代替"GET"或"HEAD"作为HTTP请求。(这个加不加没啥影响)
$datas = curl_exec($curl);
if($datas == false) {
echo '接口无法链接';
} else {
$res = stripos($datas,'error_code');
// 接收返回的数据
$dataItem = json_decode($datas);
if($res == false) {
// 数据正常
$items = $dataItem->items;
foreach($items as $item) {
switch($data['flag']) {
case 'word':
if($item->pos == 'n' && !in_array($item->item,$keywords)){
$keywords[] = $item->item;
}
break;
case 'tag':
if(!in_array($item->tag,$keywords)){
$keywords[] = $item->tag;
}
break;
default:
if($item->pos == 'n' && !in_array($item->item,$keywords)){
$keywords[] = $item->item;
}
}
}
} else {
// 接口正常但获取数据失败可能参数错误重新获取token
$url = 'https://aip.baidubce.com/oauth/2.0/token';
$post_data['grant_type'] = config('taoler.baidu.grant_type');;
$post_data['client_id'] = config('taoler.baidu.client_id');
$post_data['client_secret'] = config('taoler.baidu.client_secret');
$o = "";
foreach ( $post_data as $k => $v )
{
$o.= "$k=" . urlencode( $v ). "&" ;
}
$post_data = substr($o,0,-1);
$res = $this->request_post($url, $post_data);
// 写入token
SetArr::name('taoler')->edit([
'baidu'=> [
'access_token' => json_decode($res)->access_token,
]
]);
echo 'api接口数据错误 - ';
echo $dataItem->error_msg;
}
}
}
return $keywords;
}
// api_post接口
function request_post($url = '', $param = '')
{
if (empty($url) || empty($param)) {
return false;
}
$postUrl = $url;
$curlPost = $param;
$curl = curl_init();//初始化curl
curl_setopt($curl, CURLOPT_URL,$postUrl);//抓取指定网页
curl_setopt($curl, CURLOPT_HEADER, 0);//设置header
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上
curl_setopt($curl, CURLOPT_POST, 1);//post提交方式
curl_setopt($curl, CURLOPT_POSTFIELDS, $curlPost);
$data = curl_exec($curl);//运行curl
curl_close($curl);
return $data;
}
/**
* 标题调用百度关键词词条
*
* @return Json
*/
public function getBdiduSearchWordList($words)
{
if(empty($words)) return json(['code'=>-1,'msg'=>'null']);
$url = 'https://www.baidu.com/sugrec?prod=pc&from=pc_web&wd='.$words;
//$result = Api::urlGet($url);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$datas = curl_exec($curl);
curl_close($curl);
$data = json_decode($datas,true);
if(isset($data['g'])) {
return json(['code'=>0,'msg'=>'success','data'=>$data['g']]);
} else {
return json(['code'=>-1,'msg'=>'null']);
}
}
/**
* 上传接口
@ -414,22 +176,23 @@ abstract class BaseController
*/
public function uploadFiles($type)
{
$max_file_seze = $this->getSystem()['upsize'];
$uploads = new Uploads();
switch ($type){
case 'image':
$upRes = $uploads->put('file','article_pic',2048,'image');
$upRes = $uploads->put('file','article_pic',$max_file_seze,'image');
break;
case 'zip':
$upRes = $uploads->put('file','article_zip',1024,'application|image');
$upRes = $uploads->put('file','article_zip',$max_file_seze,'application|image');
break;
case 'video':
$upRes = $uploads->put('file','article_video',102400,'video|audio');
$upRes = $uploads->put('file','article_video',$max_file_seze,'video|audio');
break;
case 'audio':
$upRes = $uploads->put('file','article_audio',102400,'audio');
$upRes = $uploads->put('file','article_audio',$max_file_seze,'audio');
break;
default:
$upRes = $uploads->put('file','article_file',2048,'image');
$upRes = $uploads->put('file','article_file',$max_file_seze,'image');
break;
}
return $upRes;
@ -451,7 +214,6 @@ abstract class BaseController
}
//下载远程图片
private function downloadImage($url)
{
@ -543,7 +305,12 @@ abstract class BaseController
*/
public function getParamFilter(array $array) :array
{
return array_filter($array, "filter");
return array_filter($array, function($arr){
if($arr === '' || $arr === null){
return false;
}
return true;
});
}
/**
@ -561,4 +328,17 @@ abstract class BaseController
return $array;
}
/**
* 过滤字符串中表情
* @param $str string 字符串内容
* @return string
*/
public function filterEmoji(string $str): string
{
$str = preg_replace_callback('/./u', function (array $match) {
return strlen($match[0]) >= 4 ? '' : $match[0];
}, $str);
return $str;
}
}

View File

@ -34,12 +34,6 @@ class Addons extends AdminController
*/
public function index()
{
// if(Request::isAjax()) {
// $data = Request::param();
// if(!isset($data['type'])) $data['type'] = 'onlineAddons';
// if(!isset($data['selector'])) $data['selector'] = 'all';
// return $this->getList($data);
// }
return View::fetch();
}
@ -101,123 +95,6 @@ class Addons extends AdminController
return json(['code' => -1, 'msg' => '未获取到服务器信息']);
}
/**
* 插件动态列表
* @param $data
* @return Json
*/
public function getList()
{
$data = Request::param();
if(!isset($data['type'])) $data['type'] = 'onlineAddons';
if(!isset($data['selector'])) $data['selector'] = 'all';
$res = [];
//本地插件列表
$addonsList = Files::getDirName('../addons/');
$response = HttpHelper::withHost()->get('/v1/addons');
$addons = $response->toJson();
switch($data['type']){
//已安装
case 'installed':
if($addonsList){
$res = ['code'=>0,'msg'=>'','count'=>5];
$res['col'] = [
['type' => 'numbers'],
['field' => 'name','title'=> '插件', 'width'=> 120],
['field'=> 'title','title'=> '标题', 'width'=> 100],
['field'=> 'version','title'=> '版本', 'templet' => '<div>{{d.version}}</div>', 'width'=> 60],
['field' => 'author','title'=> '作者', 'width'=> 80],
['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'install','title'=> '安装', 'width'=> 100],
['field' => 'ctime','title'=> '到期时间', 'width'=> 100],
['field' => 'status','title'=> '状态', 'width'=> 95, 'templet' => '#buttonStatus'],
['title' => '操作', 'width'=> 150, 'align'=>'center', 'toolbar'=> '#addons-installed-tool']
];
// $data数据
foreach($addonsList as $v){
$info_file = '../addons/'.$v.'/info.ini';
$info = parse_ini_file($info_file);
$info['show'] = $info['status'] ? '启用' : '禁用';
$info['install'] = $info['status'] ? '是' : '否';
$res['data'][] = $info;
}
} else {
$res = ['code'=>-1,'msg'=>'没有安装任何插件'];
}
break;
//在线全部
case 'onlineAddons':
if($response->ok()) {
$res['code'] = 0;
$res['msg'] = '';
$res['count'] = count($addons->data);
$res['col'] = [
['type' => 'numbers'],
['field' => 'title','title'=> '插件', 'width'=> 200],
['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'author','title'=> '作者', 'width'=> 100],
['field' => 'price','title'=> '价格(元)','width'=> 85],
['field' => 'downloads','title'=> '下载', 'width'=> 70],
['field' => 'version','title'=> '版本', 'templet' => '<div>{{d.version}} {{# if(d.have_newversion == 1){ }}<span class="layui-badge-dot"></span>{{# } }}</div>','width'=> 75],
['field' => 'status','title'=> '在线', 'width'=> 70],
['title' => '操作', 'width'=> 150, 'align'=>'center', 'toolbar'=> '#addons-tool']
];
// $data数据 与本地文件对比
foreach($addons->data as $v){
switch ($data['selector']) {
case 'free':
if($v->price == 0) {
if(in_array($v->name,$addonsList)) {
$info = get_addons_info($v->name);
//已安装
$v->isInstall = 1;
//判断是否有新版本
if($v->version > $info['version']) $v->have_newversion = 1;
$v->price = $v->price ? $v->price : '免费';
}
$res['data'][] = $v;
}
break;
case 'pay':
if($v->price > 0) {
if(in_array($v->name,$addonsList)) {
$info = get_addons_info($v->name);
//已安装
$v->isInstall = 1;
//判断是否有新版本
if($v->version > $info['version']) $v->have_newversion = 1;
$v->price = $v->price ? $v->price : '免费';
}
$res['data'][] = $v;
}
break;
case 'all':
if(in_array($v->name,$addonsList)) {
$info = get_addons_info($v->name);
//已安装
$v->isInstall = 1;
//判断是否有新版本
if($v->version > $info['version']) $v->have_newversion = 1;
$v->price = $v->price ? $v->price : '免费';
}
$res['data'][] = $v;
break;
}
};
} else {
$res = ['code' => -1, 'msg' => '未获取到服务器信息'];
}
break;
}
return json($res);
}
/**
* 安装&升级,
* @param array $data
@ -423,10 +300,10 @@ class Addons extends AdminController
}
// 写入版本号
set_addons_info($data['name'],['version' =>$data['version']]);
return $installRes;
} catch (\Exception $e) {
return json(['code' => -1, 'msg' => $e->getMessage()]);
}
return $res;
}
/**
@ -460,13 +337,15 @@ class Addons extends AdminController
* @return string|Json
* @throws \Exception
*/
public function config($name)
public function config()
{
$name = input('name');
$config = get_addons_config($name);
// halt($config);
if(empty($config)) return json(['code'=>-1,'msg'=>'无配置项!无需操作']);
if(Request::isAjax()){
$params = Request::param('params/a',[],'trim');
// halt($params);
if ($params) {
foreach ($config as $k => &$v) {
if (isset($params[$k])) {
@ -492,7 +371,7 @@ class Addons extends AdminController
}
return json(['code'=>0,'msg'=>'配置成功!']);
}
//halt($config);
//模板引擎初始化
$view = ['formData'=>$config,'title'=>'title'];
View::assign($view);
@ -667,4 +546,20 @@ class Addons extends AdminController
}
/**
* 检测已安装插件是否有新的插件版本
* @param string $addons_name
* @param string $local_version
* @return bool
*/
public function checkHasNewVer(string $addons_name, string $local_version) :bool
{
// 在线插件
$response = HttpHelper::withHost()->get('/v1/checkNewVersion', ['name' => $addons_name, 'version' => $local_version]);
$addons = $response->toJson();
if($addons->code === 0) return true;
return false;
}
}

View File

@ -11,6 +11,7 @@
namespace app\admin\controller\content;
use app\common\controller\AdminController;
use think\App;
use think\facade\View;
use think\facade\Request;
use think\facade\Db;
@ -20,6 +21,17 @@ use app\common\model\Comment as CommentModel;
class Comment extends AdminController
{
protected $model;
public function __construct(App $app)
{
parent::__construct($app);
$this->model = new \app\common\model\Comment();
}
/**
* 浏览
* @return string
@ -28,68 +40,93 @@ class Comment extends AdminController
{
return View::fetch();
}
public function list1()
{
$data = Request::only(['name','content','status']);
$map = $this->getParamFilter($data);
$where = [];
if(!empty($map['content'])){
$where[] = ['content', 'like', $map['content'].'%'];
}
if(isset($data['status'])){
$where[] = ['status', '=', (int) $data['status']];
}
if(isset($data['name'])){
$userId = Db::name('user')->where('name',$data['name'])->value('id');
$where[] = ['user_id', '=', $userId];
}
unset($map);
$list = $this->model->getCommentList($where, input('page'), input('limit'));
$res = [];
if($list['total']) {
$res = ['code' =>0, 'msg' => 'ok', 'count' => $list['total']];
foreach($list['data'] as $k => $v){
$res['data'][] = [
'id' => $v['id'],
'replyer' => $v['user']['name'],
'title' => $v['article']['title'],
'avatar' => $v['user']['user_img'],
'content' => strip_tags($v['content']),
'replytime' => $v['create_time'],
'check' => $v['status'],
//'url' => $this->getArticleUrl($v['article_id'], 'index', $v->article->cate->ename),
];
}
return json($res);
}
return json(['code' => 0, 'msg' => 'no data']);
}
//帖子评论
public function list()
{
if(Request::isAjax()) {
$data = Request::only(['name','content','status']);
$map = array_filter($data);
$where = array();
if(!empty($map['content'])){
$where[] = ['a.content','like', $map['content'].'%'];
unset($map['content']);
}
if(isset($data['status']) && $data['status'] !== '' ){
$where[] = ['a.status','=',(int)$data['status']];
unset($map['status']);
}
/*
$replys = Comment::field('id,article_id,user_id,content,create_time')->with([
'user' => function($query){
$query->field('id,name,user_img');
},
'article' => function($query){
$query->field('id,title');
}
])->paginate(15);
*/
$replys = Db::name('comment')
->alias('a')
->join('user u','a.user_id = u.id')
->join('article c','a.article_id = c.id')
->join('cate ca','c.cate_id = ca.id')
->field('a.id as aid,name,ename,appname,title,user_img,a.content as content,a.create_time as create_time,a.status as astatus,c.id as cid')
->where('a.delete_time',0)
->where($map)
->where($where)
->order('a.create_time', 'desc')
->paginate(15);
$count = $replys->total();
$res = [];
if ($count) {
$res = ['code'=>0,'msg'=>'','count'=>$count];
foreach($replys as $k => $v){
$url = $this->getRouteUrl($v['cid'],$v['ename'], $v['appname']);
//$res['data'][] = ['id'=>$v['id'],'replyer'=>$v->user->name,'cardid'=>$v->article->title,'avatar'=>$v->user->user_img,'content'=>$v['content'],'replytime'=>$v['create_time']];
$res['data'][] = [
'id' => $v['aid'],
'replyer' => $v['name'],
'title' => htmlspecialchars($v['title']),
'avatar' => $v['user_img'],
'content' => strip_tags($v['content']),
'replytime' => date("Y-m-d",$v['create_time']),
'check' => $v['astatus'],
'url' => $url
];
}
} else {
$res = ['code'=>-1,'msg'=>'没有查询结果!'];
}
return json($res);
}
$data = Request::only(['name','content','status']);
$map = array_filter($data);
$where = array();
if(!empty($map['content'])){
$where[] = ['a.content','like', $map['content'].'%'];
unset($map['content']);
}
if(isset($data['status']) && $data['status'] !== '' ){
$where[] = ['a.status','=',(int)$data['status']];
unset($map['status']);
}
$replys = Db::name('comment')
->alias('a')
->join('user u','a.user_id = u.id')
->join('article c','a.article_id = c.id')
->join('cate ca','c.cate_id = ca.id')
->field('a.id as aid,name,ename,appname,title,user_img,a.content as content,a.create_time as create_time,a.status as astatus,c.id as cid')
->where('a.delete_time',0)
->where($map)
->where($where)
->order('a.create_time', 'desc')
->paginate([
'list_rows' => input('limit'),
'page' => input('page')
]);
$count = $replys->total();
if ($count) {
$res = ['code'=>0,'msg'=>'','count'=>$count];
foreach($replys as $k => $v){
$res['data'][] = [
'id' => $v['aid'],
'replyer' => $v['name'],
'title' => htmlspecialchars($v['title']),
'avatar' => $v['user_img'],
'content' => strip_tags($v['content']),
'replytime' => date("Y-m-d",$v['create_time']),
'check' => $v['astatus'],
'url' => $this->getArticleUrl($v['cid'],'index',$v['ename'])
];
}
} else {
$res = ['code'=>-1,'msg'=>'没有查询结果!'];
}
return json($res);
}
@ -103,14 +140,14 @@ class Comment extends AdminController
public function delete($id)
{
if(Request::isAjax()){
$arr = explode(",",$id);
foreach($arr as $v){
$comm = CommentModel::find($v);
$result = $comm->delete();
}
if($result){
try {
$arr = explode(",",$id);
foreach($arr as $v){
$comm = CommentModel::find($v);
$comm->delete();
}
return json(['code'=>0,'msg'=>'删除成功']);
}else{
} catch (\Exception $e) {
return json(['code'=>-1,'msg'=>'删除失败']);
}
}

View File

@ -12,6 +12,7 @@ namespace app\admin\controller\content;
use app\common\controller\AdminController;
use app\common\model\Article;
use app\facade\Cate;
use think\App;
use think\facade\View;
use think\facade\Request;
@ -43,7 +44,50 @@ class Forum extends AdminController
public function list()
{
$list = $this->model->getList(input('limit'),input('page'));
$data = Request::only(['id','name','title','sec','cate_id']);
$where = [];
if (!empty($data['sec'])) {
switch ($data['sec']) {
case '1':
$where[] = ['status', '=', 1];
break;
case '2':
$where[] = ['is_top', '=', 1];
break;
case '3':
$where[] = ['is_hot', '=', 1];
break;
case '4':
$where[] = ['is_reply', '=', 1];
break;
case '5':
$where[] = ['status', '=', -1];
break;
case '6':
$where[] = ['status', '=', 0];
break;
}
}
unset($data['sec']);
if(!empty($data['id'])){
$where[] = ['id', '=', $data['id']];
}
if(!empty($data['cate_id'])){
$where[] = ['cate_id', '=', $data['cate_id']];
}
if(!empty($data['name'])){
$userId = Db::name('user')->where('name',$data['name'])->value('id');
$where[] = ['user_id', '=', $userId];
}
if(!empty($data['title'])){
$where[] = ['title', 'like', '%'.$data['title'].'%'];
}
$list = $this->model->getList($where, input('limit'), input('page'));
$res = [];
if($list['total']){
foreach($list['data'] as $v) {
@ -52,6 +96,7 @@ class Forum extends AdminController
'poster' => $v['user']['name'],
'avatar' => $v['user']['user_img'],
'title' => htmlspecialchars($v['title']),
'cate' => $v['cate']['catename'],
'url' => $this->getArticleUrl($v['id'], 'index', $v['cate']['ename']),
'content' => strip_tags($v['content']),
'posttime' => $v['update_time'],
@ -60,7 +105,6 @@ class Forum extends AdminController
'reply' => $v['is_reply'],
'check' => $v['status']
];
}
return json(['code' =>0, 'msg' => 'ok', 'count' => $list['total'], 'data' => $res['data']]);
}
@ -93,9 +137,9 @@ class Forum extends AdminController
$data['content'] = $this->downUrlPicsReaplace($data['content']);
// 把,转换为,并去空格->转为数组->去掉空数组->再转化为带,号的字符串
$data['keywords'] = implode(',',array_filter(explode(',',trim(str_replace('',',',$data['keywords'])))));
$data['description'] = strip_tags($this->filterEmoji($data['description']));
// 获取分类ename,appname
$cateName = $this->model->field('ename,appname')->find($data['cate_id']);
$cateEname = Db::name('cate')->where('id',$data['cate_id'])->value('ename');
$result = $this->model->add($data);
if ($result['code'] == 1) {
@ -114,7 +158,7 @@ class Forum extends AdminController
// 清除文章tag缓存
Cache::tag('tagArtDetail')->clear();
$link = $this->getArticleUrl((int)$aid, 'index', $cateName['ename']);
$link = $this->getArticleUrl((int)$aid, 'index', $cateEname);
hook('SeoBaiduPush', ['link'=>$link]); // 推送给百度收录接口
@ -125,11 +169,6 @@ class Forum extends AdminController
}
return $res;
}
//1.查询分类表获取所有分类
$cateList = Db::name('cate')->where(['status'=>1,'delete_time'=>0])->order('sort','asc')->cache('catename',3600)->select();
//2.将catelist变量赋给模板 公共模板nav.html
View::assign('cateList',$cateList);
return View::fetch('add');
}
@ -163,7 +202,7 @@ class Forum extends AdminController
$data['content'] = $this->downUrlPicsReaplace($data['content']);
// 把,转换为,并去空格->转为数组->去掉空数组->再转化为带,号的字符串
$data['keywords'] = implode(',',array_filter(explode(',',trim(str_replace('',',',$data['keywords'])))));
$data['description'] = strip_tags($this->filterEmoji($data['description']));
$result = $article->edit($data);
if($result == 1) {
//处理标签
@ -190,7 +229,7 @@ class Forum extends AdminController
}
//删除原有缓存显示编辑后内容
Cache::delete('article_'.$id);
$link = $this->getRouteUrl((int) $id, $article->cate->ename, $article->cate->appname);
$link = $this->getArticleUrl((int) $id, 'index', $article->cate->ename);
hook('SeoBaiduPush', ['link'=>$link]); // 推送给百度收录接口
return Msgres::success('edit_success',$link);
}
@ -198,31 +237,24 @@ class Forum extends AdminController
}
View::assign(['article'=>$article]);
//1.查询分类表获取所有分类
$cateList = Db::name('cate')->where(['status'=>1,'delete_time'=>0])->order('sort','asc')->cache('catename',3600)->select();
//2.将catelist变量赋给模板 公共模板nav.html
View::assign('cateList',$cateList);
return View::fetch();
}
//删除帖子
//删除帖子 多选和单独
public function delete($id)
{
if(Request::isAjax()){
$arr = explode(",",$id);
foreach($arr as $v){
$article = Article::find($v);
$result = $article->together(['comments'])->delete();
}
if($result){
return json(['code'=>0,'msg'=>'删除成功']);
}else{
return json(['code'=>-1,'msg'=>'删除失败']);
}
try {
$arr = explode(",",$id);
foreach($arr as $v){
$article = Article::find($v);
$article->together(['comments'])->delete();
}
return json(['code'=>0,'msg'=>'删除成功']);
} catch (\Exception $e) {
return json(['code'=>-1,'msg'=>'删除失败']);
}
}
}
@ -256,29 +288,6 @@ class Forum extends AdminController
return $this->uploadFiles($type);
}
/**
* 调用百度关键词
*
* @return json
*/
public function getKeywords()
{
$data = Request::only(['flag','keywords','content']);
$keywords = $this->setKeywords($data);
return json(['code'=>0, 'msg' => 'ok', 'data'=> $keywords]);
}
/**
* 标题调用百度关键词词条
* @return Json
*/
public function getWordList()
{
$title = input('title');
return $this->getBdiduSearchWordList($title);
}
/**
* 内容中是否有图片视频音频插入
*
@ -300,21 +309,9 @@ class Forum extends AdminController
return $data;
}
/**
* 获取描述过滤html
*
* @return void
*/
public function getDescription()
{
$data = Request::only(['content']);
$description = getArtContent($data['content']);
return json(['code'=>0,'data'=>$description]);
}
/**
* 分类
* 分类树
* @return Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
@ -336,6 +333,28 @@ class Forum extends AdminController
return json($tree);
}
/**
* 分类
* @return \think\response\Json
*/
public function getCateList()
{
$cateList = Cate::field('id,pid,catename,sort')->where(['status' => 1])->select()->toArray();
// 排序
$cmf_arr = array_column($cateList, 'sort');
array_multisort($cmf_arr, SORT_ASC, $cateList);
$list = getTree($cateList);
$count = count($list);
$tree = [];
if($count){
$tree = ['code'=>0, 'msg'=>'ok','count'=>$count];
$tree['data'] = $list;
}
return json($tree);
}
//array_filter过滤函数
protected function filtr($arr){
if($arr === '' || $arr === null){

View File

@ -74,27 +74,32 @@ class Tag extends AdminController
$data = Request::only(['name','ename','id','keywords','description','title']);
// 把,转换为,并去空格->转为数组->去掉空数组->再转化为带,号的字符串
$data['keywords'] = implode(',',array_filter(explode(',',trim(str_replace('',',',$data['keywords'])))));
$res =$tagModel::update($data);
if($res == true){
try{
$tagModel::update($data);
return json(['code'=>0,'msg'=>'设置成功']);
} catch(\Exception $e) {
return json(['code'=>-1,'msg'=>$e->getMessage()]);
}
}
$tag = $tagModel->getTag(input('id'));
View::assign('tag',$tag);
return view();
}
/**
* 删除
* @return \think\response\Json
*/
public function delete()
{
if(Request::isPost()) {
$tagModel = new TagModel;
$res = $tagModel->delTag(input('id'));
if($res == true){
return json(['code'=>0,'msg'=>'删除成功']);
}
$tagModel = new TagModel;
$res = $tagModel->delTag(input('id'));
if($res){
return json(['code'=>0,'msg'=>'删除成功']);
}
return json(['code'=>-1,'msg'=>'删除失败']);
}
/**

View File

@ -42,12 +42,11 @@ class AuthRule extends AdminController
{
return $this->model->getAuthRuleArray();
}
/**
* 无限极权限树
*
* @return void
*/
/**
* 无限极权限树
* @return \think\response\Json
*/
public function ruleTree()
{
$data = $this->getRoleMenu(1);

View File

@ -16,6 +16,8 @@ use think\facade\Request;
use think\facade\Db;
use app\common\model\User as UserModel;
use app\common\lib\Uploads;
use app\common\validate\User as userValidate;
use think\exception\ValidateException;
class User extends AdminController
@ -79,6 +81,14 @@ class User extends AdminController
//
if(Request::isAjax()){
$data = Request::only(['name','email','user_img','password','phone','sex']);
try{
validate(userValidate::class)
->scene('userReg')
->check($data);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return json(['code'=>-1,'msg'=>$e->getError()]);
}
$data['create_time'] = time();
$salt = substr(md5($data['create_time']),-6);
// 密码
@ -100,18 +110,19 @@ class User extends AdminController
{
if(Request::isAjax()){
$data = Request::only(['id','name','email','user_img','password','phone','sex']);
$user = Db::name('user')->field('create_time')->find($data['id']);
$salt = substr(md5($user['create_time']),-6);
// 密码
$data['password'] = md5(substr_replace(md5($data['password']),$salt,0,6));
$result = Db::name('user')->update($data);
if($result){
$res = ['code'=>0,'msg'=>'编辑成功'];
}else{
$res = ['code'=>-1,'msg'=>'编辑失败'];
}
return json($res);
if(empty($data['password'])) {
unset($data['password']);
} else {
$user = Db::name('user')->field('create_time')->find($data['id']);
$salt = substr(md5($user['create_time']),-6);
$data['password'] = md5(substr_replace(md5($data['password']),$salt,0,6)); // 密码
}
try{
Db::name('user')->update($data);
return json(['code'=>0,'msg'=>'编辑成功']);
} catch (\Exception $e) {
return json(['code'=> -1,'msg'=>$e->getMessage()]);
}
}
$user = Db::name('user')->find(input('id'));
View::assign('user',$user);

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>新增管理员</title>
<title>表单配置</title>
<link rel="stylesheet" href="/static/component/pear/css/pear.css" />
</head>
<body>
@ -24,10 +24,10 @@
{:form_radio($name,$vo.content,['label'=>$vo.title,'tips'=>$vo.tips],$vo.value)}
{/case}
{case value="checkbox"}
{:form_checkbox($name, $vo.content,['label'=>$vo.title, 'verify' =>$vo.rule,'tips'=>$vo.tips,], $vo['value'])};
{:form_checkbox($name, $vo.content,['label'=>$vo.title, 'verify' =>$vo.rule,'tips'=>$vo.tips,], $vo['value'])}
{/case}
{case value="switch"}
{:form_switch($name, $vo.content,['label'=>$vo.title, 'verify' =>$vo.rule,'tips'=>$vo.tips,], $vo['value'])};
{:form_switch($name, $vo.content,['label'=>$vo.title, 'verify' =>$vo.rule,'tips'=>$vo.tips,], $vo['value'])}
{/case}
{case value="select"}
{:form_select($name,$vo.content,['label'=>$vo.title,'verify'=>$vo.rule,'tips'=>$vo.tips,'search'=>1] ,[],$vo.value)}
@ -66,7 +66,7 @@
<script>
layui.use(['upload','toast'], function(){
var $ = layui.$,upload = layui.upload,form = layui.form,notify=layui.notify;
//上传头像
//上传
upload.render({
elem: '.upload-select'
,url: "{:url('addon.addons/uploads')}"

View File

@ -24,7 +24,7 @@
<script type="text/html" id="addons-bar">
{{# if(d.have_newversion === 1){ }}
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="install" data-url="{:url('addon.addons/upgrade')}" data-userlogin="{:url('addon.addons/userLogin')}" data-ispay="{:url('addon.addons/isPay')}"><i class="layui-icon layui-icon-edit"></i>升级</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="install" data-url="{:url('addon.addons/upgrade')}" data-userlogin="{:url('addon.addons/userLogin')}" data-ispay="{:url('addon.addons/isPay')}"><i class="layui-icon layui-icon-upload-circle"></i>升级</a>
{{# } else { }}
{{# if(d.isInstall === 1) { }}
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="config" data-url="{:url('addon.addons/config')}"><i class="layui-icon layui-icon-set"></i>设置</a>
@ -100,7 +100,7 @@
url: LIST_URL,
cols: cols,
page: true,
limit: 10,
limit: 15,
text: "对不起,加载出现异常!",
});

View File

@ -1,11 +1,6 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改页面</title>
<link rel="stylesheet" href="/static/component/pear/css/pear.css" />
</head>
<body>
{extend name="public:admin_form" /}
{block name="body"}
<form class="layui-form" action="">
<div class="mainBox">
<div class="main-container">
@ -21,14 +16,20 @@
<div class="layui-input-block">
<input type="text" name="catename" lay-verify="required" placeholder="分类名*" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">EN别名</label>
<div class="layui-input-block">
<input type="text" name="ename" lay-verify="required" placeholder="英文名*" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">图标</label>
<div class="layui-input-block">
<input type="text" name="icon" placeholder="图标*" id="iconPicker" lay-filter="iconPicker" style="display:none;" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">详情页模板</label>
<div class="layui-input-block">
<select name="detpl" id="tpl" lay-verify="required">
@ -37,10 +38,14 @@
{/volist}
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">描述</label>
<div class="layui-input-block">
<input type="text" name="desc" lay-verify="required" placeholder="描述*" autocomplete="off" class="layui-input">
<textarea type="text" name="desc" lay-verify="required" placeholder="描述*" autocomplete="off" class="layui-textarea"></textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">排序</label>
<div class="layui-input-block">
<input type="text" name="sort" lay-verify="number|required" placeholder="请填数字" autocomplete="off" class="layui-input">
@ -61,8 +66,9 @@
</div>
</div>
</form>
<script src="/static/component/layui/layui.js"></script>
<script src="/static/component/pear/pear.js"></script>
{/block}
{block name="js"}
<script>
layui.use(['form', 'iconPicker', 'xmSelect',], function(){
var $ = layui.jquery
@ -98,9 +104,9 @@
icon: 1,
time: 1000
}, function() {
parent.layer.close(parent.layer.getFrameIndex(window
.name)); //关闭当前页
parent.layui.table.reload("cate-table");
// parent.layui.table.reload("cate-table");
parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页
window.parent.location.reload();
});
} else {
layer.msg(result.msg, {
@ -201,5 +207,4 @@
})
</script>
</body>
</html>
{/block}

View File

@ -1,11 +1,6 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改页面</title>
<link rel="stylesheet" href="/static/component/pear/css/pear.css" />
</head>
<body>
{extend name="public:admin_form" /}
{block name="body"}
<form class="layui-form" action="">
<div class="mainBox">
<div class="main-container">
@ -47,7 +42,7 @@
<div class="layui-form-item">
<label class="layui-form-label">描述</label>
<div class="layui-input-block">
<input type="text" name="desc" lay-verify="required" value="{$cate.desc}" placeholder="描述*" autocomplete="off" class="layui-input">
<textarea type="text" name="desc" lay-verify="required" value="{$cate.desc}" placeholder="描述*" autocomplete="off" class="layui-textarea">{$cate.desc}</textarea>
</div>
</div>
<div class="layui-form-item">
@ -74,8 +69,9 @@
</div>
</div>
</form>
<script src="/static/component/layui/layui.js"></script>
<script src="/static/component/pear/pear.js"></script>
{/block}
{block name="js"}
<script>
layui.use(['form', 'iconPicker', 'xmSelect',], function(){
var $ = layui.jquery
@ -83,8 +79,7 @@
var iconPicker = layui.iconPicker;
var xmSelect = layui.xmSelect;
var initPid = "{$cate.pid}";
let ADD_EDIT = "{:url('content.cate/addEdit')}";
let ADD_EDIT = "{:url('content.cate/addEdit')}";
//初始化图标选择
iconPicker.render({
@ -111,9 +106,8 @@
icon: 1,
time: 1000
}, function() {
parent.layer.close(parent.layer.getFrameIndex(window
.name)); //关闭当前页
parent.layui.table.reload("cate-table");
parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页
window.parent.location.reload();
});
} else {
layer.msg(result.msg, {
@ -166,5 +160,4 @@
})
</script>
</body>
</html>
{/block}

View File

@ -146,7 +146,7 @@
type: 2,
title: '新增',
shade: 0.1,
area: ['450px', '500px'],
area: ['550px', '650px'],
content: 'addEdit.html'
});
}
@ -156,7 +156,7 @@
type: 2,
title: '修改',
shade: 0.1,
area: ['450px', '500px'],
area: ['550px', '650px'],
content: 'addEdit.html?id=' + obj.data.id
});
}

View File

@ -130,7 +130,10 @@
form.on('submit(comment-query)', function(data) {
table.reload('comment-table', {
where: data.field
where: data.field,
page: {
curr: 1 //重新从第 1 页开始
}
})
return false;
});
@ -148,7 +151,7 @@
data:{id:data.id,status:status},
dataType:'json',
success:function(res){
if(res.code == 0){
if(res.code === 0){
layer.msg(res.msg,{
icon:res.icon,
time:2000
@ -170,7 +173,7 @@
window.remove = function(obj) {
layer.confirm('确定要删除该评论吗', {
layer.confirm('确定要删除?', {
icon: 3,
title: '提示'
}, function(index) {
@ -212,7 +215,7 @@
return false;
}
layer.confirm('确定要删除这些评论', {
layer.confirm('确定要删除?', {
icon: 3,
title: '提示'
}, function(index) {
@ -225,7 +228,7 @@
data:{"id":checkIds},
success: function(result) {
layer.close(loading);
if (result.success) {
if (result.code === 0) {
layer.msg(result.msg, {
icon: 1,
time: 1000
@ -244,7 +247,7 @@
}
window.refresh = function(param) {
table.reload('user-table');
table.reload('comment-table');
}

View File

@ -4,6 +4,12 @@
<meta charset="UTF-8">
<title>新增帖子</title>
<link rel="stylesheet" href="/static/component/pear/css/pear.css" />
<style>
#L_title {position: relative;}
.bdsug {height: auto; position: absolute; left: 0; top: 30px; z-index: 100; background: #fff; border-radius: 0 0 10px 10px; border: 1px solid #dadade!important; border-top: 0!important; box-shadow: none;}
.bdsug ul{display: block;margin: 5px 2px 0; padding: 5px 0 7px; background: 0 0; border-top: 0px solid #f5f5f6;}
.bdsug ul>li{margin-top: 0;height:30px;line-height: 25px;}
</style>
</head>
<body>
<form class="layui-form" action="">
@ -13,12 +19,7 @@
<div class="layui-col-md3">
<label class="layui-form-label">{:lang('special column')}</label>
<div class="layui-input-block">
<select lay-verify="required" name="cate_id" lay-filter="column">
<option></option>
{volist name="cateList" id="cate"}
<option value="{$cate.id}" {if ($Request.param.cate == $cate.ename)} selected {/if}>{:cookie('think_lang') == 'en-us' ? $cate.ename : $cate.catename}</option>
{/volist}
</select>
<div id="CateId" class="xm-select-demo"></div>
</div>
</div>
<div class="layui-col-md8">
@ -26,10 +27,6 @@
<div class="layui-input-block">
<input type="text" id="L_title" name="title" required lay-verify="required" autocomplete="off" class="layui-input" style="position:relative;" value=""/>
<input type="hidden" id="L_title_color" name="title_color" autocomplete="off" class="layui-input" />
<div class="layui-input bdsug layui-hide">
<ul class="wordlist">
</ul>
</div>
</div>
</div>
<div class="layui-col-md1">
@ -39,7 +36,7 @@
<div class="layui-form-item layui-form-text">
<div class="layui-input-block">
<textarea id="L_content" name="content" required lay-verify="" placeholder="{:lang('please input the content')}" class="layui-textarea"> </textarea>
<textarea id="L_content" name="content" lay-verify="required" placeholder="{:lang('please input the content')}" class="layui-textarea taonyeditor"> </textarea>
</div>
</div>
<div class="layui-form-item layui-inline">
@ -88,38 +85,40 @@
<script src="/static/component/layui/layui.js"></script>
<script src="/static/component/pear/pear.js"></script>
<script src="/static/addons/taonyeditor/tinymce/tinymce.min.js"></script>
<script src="/static/xm-select.js"></script>
<script>
layui.extend({
editor: '{/}/static/addons/taonyeditor/js/taonyeditor'
}).use(["form", "colorpicker", "upload",'editor','xmSelect'], function () {
layui.use(["form", "colorpicker", "upload",'xmSelect'], function () {
var $ = layui.jquery, form = layui.form, colorpicker = layui.colorpicker, upload = layui.upload;
var editor = layui.editor;
var xmSelect = layui.xmSelect;
editor.render({
selector: 'textarea#L_content',
uploadUrl: "{:url('content.forum/uploads')}",
imagePrependUrl: "{$domain}"
// 分类选择
$.get("{:url('content.forum/getCateList')}",function(res){
// 渲染下拉树
xmSelect.render({
el: '#CateId',
name: 'cate_id',
height: '250px',
layVerify: 'required',
layVerType: 'tips',
data: res.data,
initValue: [res.data[0].id],
model: {label: {type: 'text'}},
prop: {
name: 'catename',
value: 'id'
},
radio: true,
clickClose: true,
tree: {
show: true,
indent: 15,
strict: false,
expandedKeys: true
},
tips: '请选择'
});
});
//获取百度标签标志tag或者word;
var flag = 'word';
// 从详情页自动调用端口过滤,获取描述信息
tinymce.get('L_content').on('mouseleave', function() {
var content = tinymce.get('L_content').getContent({format: 'text'});
content = content.replace(/[\r\n]/g,"").replace(/\n/g, '').replace(/\s/g, '').replace(/\t/g, '');
if(content.length >200) {
content = content.substring(0,200);
}
// var test = tinymce.activeEditor.getContent({format: 'text'});
$('[name="description"]').val(content);
});
// tag标签
$(function(){
//1.渲染标签
@ -143,70 +142,17 @@
});
})
// 通过接口自动获取tag的内容
var conf = "{:empty(config('taoler.baidu.client_id'))}";
if (conf !== "1") {
$("#L_title").on("blur", function () {
var title = $(this).val();
var content = $("#L_content").val();
$.ajax({
type: "post",
url: "{:url('content.forum/getKeywords')}",
data: { keywords: title, content:content, flag: flag },
daType: "json",
success: function (data) {
if (data.code === 0) {
$("input[name='keywords']").val(data.data.join(','));
}
},
});
});
}
// 百度词条
var baidu_title_switch = "{:config('taoler.config.baidu_title_switch')}";
if(baidu_title_switch === 1) {
$("#L_title").bind('input propertychange',function () {
var title = $(this).val();
var str = '';
if(title.length > 0 ) {
$.post("{:url('content.forum/getWordList')}",{title:title},function(res){
// 动态生成ur>li内容
if (res.code === 0) {
// 显示动态框
$(".bdsug").removeClass('layui-hide');
for (var i = 0; i < res.data.length; i++) {
//str += '<li data-key=' + res.data[i].q + '><b>' + res.data[i].q.replace(title,'') + '</b></li>';
str += '<li data-key=' + res.data[i].q + '><b>' + res.data[i].q + '</b></li>';
}
// 清空ul并追加li
$('.wordlist').empty().append(str);
// 点击李获取li值并复制给#L_title input的value
$(".bdsug li").on('click',function(){
var word = $(this).attr('data-key');
var words = title + '(' + word + ')';
$("#L_title").val(words);
// 关闭动态框
$(".bdsug").addClass('layui-hide');
});
} else {
$(".bdsug").addClass('layui-hide');
}
});
} else {
$(".bdsug").addClass('layui-hide');
}
});
}
//上传附件
upload.render({
elem: "#zip-button",
url: "{:url('content.forum/uploads')}", //改成您自己的上传接口
data: { type: "zip" },
accept: "file", //普通文件
accept: "file",
before: function(obj){
layer.load();
},
done: function (res) {
layer.closeAll('loading');
if (res.status === 0) {
$('input[name="upzip"]').val(res.url);
layer.msg("上传成功");
@ -229,7 +175,6 @@
});
form.on('submit(forum-save)', function(data) {
console.log(data)
$.ajax({
url: "{:url('content.forum/add')}",
data: JSON.stringify(data.field),
@ -242,9 +187,8 @@
icon: 1,
time: 1000
}, function() {
parent.layer.close(parent.layer.getFrameIndex(window
.name)); //关闭当前页
parent.layui.table.reload("user-table");
parent.layui.table.reload("forum-table");
parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页
});
} else {
layer.msg(result.msg, {
@ -259,5 +203,10 @@
});
</script>
{:hook('taonyeditor')}
{// 百度标题词条}
{:hook('seoBaiduTitle')}
{// 百度关键词}
{:hook('seoBaiduKeywords')}
</body>
</html>

View File

@ -4,6 +4,12 @@
<meta charset="UTF-8">
<title>修改页面</title>
<link rel="stylesheet" href="/static/component/pear/css/pear.css" />
<style>
#L_title {position: relative;}
.bdsug {height: auto; position: absolute; left: 0; top: 30px; z-index: 100; background: #fff; border-radius: 0 0 10px 10px; border: 1px solid #dadade!important; border-top: 0!important; box-shadow: none;}
.bdsug ul{display: block;margin: 5px 2px 0; padding: 5px 0 7px; background: 0 0; border-top: 0px solid #f5f5f6;}
.bdsug ul>li{margin-top: 0;height:30px;line-height: 25px;}
</style>
</head>
<body>
<form class="layui-form" action="">
@ -14,12 +20,7 @@
<div class="layui-col-md3">
<label class="layui-form-label">{:lang('special column')}</label>
<div class="layui-input-block">
<select lay-verify="required" name="cate_id" lay-filter="column">
<option></option>
{volist name="cateList" id="cate"}
<option value="{$cate.id}" {if $article.cate_id == $cate.id} selected {/if}> {:cookie('think_lang') == 'en-us' ? $cate.ename : $cate.catename}</option>
{/volist}
</select>
<div id="CateId" class="xm-select-demo"></div>
</div>
</div>
<div class="layui-col-md8">
@ -37,7 +38,7 @@
</div>
<div class="layui-form-item layui-form-text">
<div class="layui-input-block">
<textarea id="L_content" name="content" required lay-verify="required" placeholder="详细内容" class="layui-textarea">{$article.content}</textarea>
<textarea id="L_content" name="content" required lay-verify="required" placeholder="详细内容" class="layui-textarea taonyeditor">{$article.content}</textarea>
</div>
</div>
<div class="layui-form-item">
@ -89,27 +90,15 @@
</form>
<script src="/static/component/layui/layui.js"></script>
<script src="/static/component/pear/pear.js"></script>
<script src="/static/addons/taonyeditor/tinymce/tinymce.min.js"></script>
<script src="/static/xm-select.js"></script>
<script>
layui.extend({
editor: '{/}/static/addons/taonyeditor/js/taonyeditor'
}).use(['colorpicker','form','upload', 'editor'], function(){
layui.use(['colorpicker','form','upload','xmSelect'], function(){
var $ = layui.jquery
,colorpicker = layui.colorpicker
,form = layui.form
,upload = layui.upload;
var artId = "{$article.id}";
var editor = layui.editor;
// 初始化编辑器
editor.render({
selector: 'textarea#L_content',
uploadUrl: "{:url('content.forum/uploads')}",
imagePrependUrl: "{$domain}"
});
var xmSelect = layui.xmSelect;
$(function(){
//1.渲染标签
@ -141,54 +130,35 @@
});
})
// 从详情页自动调用端口过滤,获取描述信息
tinymce.get('L_content').on('mouseleave', function() {
var content = tinymce.get('L_content').getContent({format: 'text'});
content = content.replace(/[\r\n]/g,"").replace(/\n/g, '').replace(/\s/g, '').replace(/\t/g, '');
if(content.length >200) {
content = content.substring(0,200);
}
// var test = tinymce.activeEditor.getContent({format: 'text'});
$('[name="description"]').val(content);
});
// 获取描述的内容
$("#L_content").bind('input propertychange', function(){
var content = $(this).val()
$.ajax({
type:"post",
url:"{:url('content.forum/getDescription')}",
data:{"content":content},
daType:"json",
success:function (data){
if (data.code == 0) {
$('[name="description"]').val(data.data);
}
}
// 分类选择
$.get("{:url('content.forum/getCateList')}",function(res){
var INITCID = "{$article.cate_id}";
// 渲染下拉树
xmSelect.render({
el: '#CateId',
name: 'cate_id',
height: '250px',
layVerify: 'required',
layVerType: 'tips',
data: res.data,
initValue: [INITCID],
model: {label: {type: 'text'}},
prop: {
name: 'catename',
value: 'id'
},
radio: true,
clickClose: true,
tree: {
show: true,
indent: 15,
strict: false,
expandedKeys: true
},
tips: '请选择'
});
return false;
})
// 获取tag的内容
var conf = "{:empty(config('taoler.baidu.client_id'))}";
if(conf !== '1'){
$("#L_title").on('blur', function(){
var title = $(this).val();
var flag = 'on';
$.ajax({
type:"post",
url:"{:url('content.forum/getKeywords')}",
data:{"keywords":keywords,"flag":flag},
daType:"json",
success:function (data){
if (data.code === 0) {
$("input[name='keywords']").val("");
}
}
});
return false;
})
}
});
//预定义颜色项
colorpicker.render({
@ -208,8 +178,12 @@
elem: '#zip-button'
,url: "{:url('content.forum/uploads')}" //改成您自己的上传接口
,data: {type:'zip'}
,accept: 'file' //普通文件
,done: function(res){
,accept: 'file',
before: function(obj){
layer.load();
},
done: function(res){
layer.closeAll('loading');
if(res.status === 0){
$('input[name="upzip"]').val(res.url);
layer.msg('上传成功');
@ -232,9 +206,8 @@
icon: 1,
time: 1000
}, function() {
parent.layer.close(parent.layer.getFrameIndex(window
.name)); //关闭当前页
parent.layui.table.reload("user-table");
parent.layui.table.reload("forum-table");
parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页
});
} else {
layer.msg(result.msg, {
@ -249,5 +222,10 @@
});
</script>
{:hook('taonyeditor')}
{// 百度标题词条}
{:hook('seoBaiduTitle')}
{// 百度关键词}
{:hook('seoBaiduKeywords')}
</body>
</html>

View File

@ -5,58 +5,63 @@
<title>用户管理</title>
<link rel="stylesheet" href="/static/component/pear/css/pear.css" />
</head>
<body class="pear-container">
<div class="layui-card">
<div class="layui-card-body">
<form class="layui-form" action="">
<div class="layui-form-item">
<div class="layui-form-item layui-inline">
<label class="layui-form-label">帖子ID</label>
<div class="layui-input-block">
<input type="text" name="id" placeholder="请输入" autocomplete="off" class="layui-input">
<body class="pear-container">
<div class="layui-card">
<div class="layui-card-body">
<form class="layui-form" action="">
<div class="layui-row layui-col-space15 ">
<div class="layui-col-md3">
<label class="layui-form-label">选择类目</label>
<div class="layui-input-block">
<div id="CateId" class="xm-select-demo"></div>
</div>
</div>
<div class="layui-col-md3">
<label class="layui-form-label">帖子ID</label>
<div class="layui-input-block">
<input type="text" name="id" placeholder="请输入" autocomplete="off" class="layui-input">
</div>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">发帖人</label>
<div class="layui-input-block">
<input type="text" name="name" placeholder="请输入" autocomplete="off" class="layui-input">
<div class="layui-col-md3">
<label class="layui-form-label">发帖人</label>
<div class="layui-input-block">
<input type="text" name="name" placeholder="请输入" autocomplete="off" class="layui-input">
</div>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input type="text" name="title" placeholder="请输入" autocomplete="off" class="layui-input">
<div class="layui-col-md3">
<label class="layui-form-label">标题</label>
<div class="layui-input-block">
<input type="text" name="title" placeholder="请输入" autocomplete="off" class="layui-input">
</div>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">状态</label>
<div class="layui-input-block">
<select name="sec">
<option value="">选择状态</option>
<option value="1">正常</option>
<option value="5">禁止</option>
<option value="6">待审</option>
<option value="2">置顶</option>
<option value="3">加精</option>
<option value="4">禁评</option>
</select>
<div class="layui-col-md3">
<label class="layui-form-label">状态</label>
<div class="layui-input-block">
<select name="sec">
<option value="">选择状态</option>
<option value="1">正常</option>
<option value="5">禁止</option>
<option value="6">待审</option>
<option value="2">置顶</option>
<option value="3">加精</option>
<option value="4">禁评</option>
</select>
</div>
</div>
</div>
<div class="layui-form-item layui-inline">
<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="forum-query">
<i class="layui-icon layui-icon-search"></i>
查询
</button>
<button type="reset" class="pear-btn pear-btn-md">
<i class="layui-icon layui-icon-refresh"></i>
重置
</button>
</div>
<div class="layui-col-md3">
<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="forum-query">
<i class="layui-icon layui-icon-search"></i>
查询
</button>
<button type="reset" class="pear-btn pear-btn-md">
<i class="layui-icon layui-icon-refresh"></i>
重置
</button>
</div>
</div>
</form>
</div>
</form>
</div>
</div>
</div>
<div class="layui-card">
<div class="layui-card-body">
<table id="forum-table" lay-filter="forum-table" ></table>
@ -74,7 +79,6 @@
</button>
</script>
<script type="text/html" id="avatarTpl">
<div><img style="width: 25px; height: 25px;" src= "{{ d.avatar }}"></div>
</script>
@ -96,21 +100,19 @@
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove"><i class="layui-icon layui-icon-delete"></i></button>
</script>
</div>
</div>
<script src="/static/component/layui/layui.js"></script>
<script src="/static/component/pear/pear.js"></script>
<script>
const FORUM_List = "{:url('content.forum/list')}";
layui.use(['toast','jquery','form', 'table','common'], function(){
layui.use(['toast','jquery','form', 'table','common','xmSelect'], function(){
var $ = layui.jquery
,form = layui.form
,table = layui.table;
let common = layui.common;
var toast = layui.toast;
var xmSelect = layui.xmSelect;
//如果你是采用模版自带的编辑器,你需要开启以下语句来解析。
var taonystatus = "{:hook('taonystatus')}";
@ -125,6 +127,7 @@
,{field: 'avatar', title: '头像', width: 60, templet: '#avatarTpl'}
,{field: 'poster', title: '账号',width: 80}
,{field: 'title', title: '标题', minWidth: 180,templet: '<div><a href="{{- d.url }}" target="_blank">{{- d.title }}</a></div>'}
,{field: 'cate', title: '类别', width: 120}
,{field: 'content', title: '内容', 'escape':false, minWidth: 200}
,{field: 'posttime', title: '时间',width: 120, sort: true}
,{field: 'top', title: '置顶', templet: '#forum-istop', width: 80, align: 'center'}
@ -149,6 +152,38 @@
}, 'filter', 'print', 'exports']
});
// 动态分类
function getSelectCate() {
// 分类选择
$.get("{:url('content.forum/getCateList')}", function(res){
// 渲染下拉树
xmSelect.render({
el: '#CateId',
name: 'cate_id',
height: '250px',
layVerify: '',
layVerType: 'tips',
data: res.data,
initValue: [],
model: {label: {type: 'text'}},
prop: {
name: 'catename',
value: 'id'
},
radio: true,
clickClose: true,
tree: {
show: true,
indent: 15,
strict: false,
expandedKeys: true
},
tips: '请选择'
});
});
}
getSelectCate();
table.on('tool(forum-table)', function(obj) {
if (obj.event === 'remove') {
window.remove(obj);
@ -169,7 +204,10 @@
form.on('submit(forum-query)', function(data) {
table.reload('forum-table', {
where: data.field
where: data.field,
page: {
curr: 1 //重新从第 1 页开始
}
})
return false;
});
@ -243,7 +281,7 @@
window.remove = function(obj) {
layer.confirm('确定要删除该用户', {
layer.confirm('确定要删除?', {
icon: 3,
title: '提示'
}, function(index) {
@ -274,9 +312,7 @@
}
window.batchRemove = function(obj) {
var checkIds = common.checkField(obj,'id');
if (checkIds === "") {
layer.msg("未选中数据", {
icon: 3,
@ -285,25 +321,25 @@
return false;
}
layer.confirm('确定要删除这些用户', {
layer.confirm('确定要删除?', {
icon: 3,
title: '提示'
}, function(index) {
layer.close(index);
let loading = layer.load();
$.ajax({
url: "{:url('system.admin/delete')}",
url: "{:url('content.forum/delete')}?id=" + checkIds,
dataType: 'json',
type: 'delete',
data:{"id":checkIds},
success: function(result) {
layer.close(loading);
if (result.success) {
if (result.code === 0) {
layer.msg(result.msg, {
icon: 1,
time: 1000
}, function() {
table.reload('user-table');
table.reload('forum-table');
});
} else {
layer.msg(result.msg, {
@ -317,7 +353,7 @@
}
window.refresh = function(param) {
table.reload('user-table');
table.reload('forum-table');
}
});

View File

@ -0,0 +1,91 @@
{extend name="public/admin_form" /}
{block name="body"}
<form class="layui-form" action="">
<div class="mainBox">
<div class="main-container">
<div class="layui-form-item">
<label class="layui-form-label">名称</label>
<div class="layui-input-inline">
<input type="text" name="name" lay-verify="required" placeholder="tag名" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">别名</label>
<div class="layui-input-inline">
<input type="text" name="ename" lay-verify="required" placeholder="英文或者拼音别名" autocomplete="off" class="layui-input" >
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">关键词</label>
<div class="layui-input-inline">
<input type="text" name="keywords" lay-verify="required" placeholder="关键词 多个以逗号,隔开" autocomplete="off" class="layui-input" >
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">摘要</label>
<div class="layui-input-block">
<textarea type="text" name="description" lay-verify="required" placeholder="请输入内容" autocomplete="off" class="layui-textarea"></textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">seo标题</label>
<div class="layui-input-inline">
<input type="text" name="title" lay-verify="required" placeholder="tag标题" autocomplete="off" class="layui-input" >
</div>
</div>
</div>
</div>
<div class="bottom">
<div class="button-container">
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit="" lay-filter="tag-save">
<i class="layui-icon layui-icon-ok"></i>
提交
</button>
<button type="reset" class="pear-btn pear-btn-sm">
<i class="layui-icon layui-icon-refresh"></i>
重置
</button>
</div>
</div>
</form>
{/block}
{block name="js"}
<script>
layui.use(['form', 'jquery', 'upload'], function() {
let form = layui.form;
let $ = layui.jquery;
let ADD_URL = "{:url('content.tag/add')}";
form.on('submit(tag-save)', function(data) {
$.ajax({
url: ADD_URL,
data: JSON.stringify(data.field),
dataType: 'json',
contentType: 'application/json',
type: 'post',
success: function(result) {
if (result.code === 0) {
layer.msg(result.msg, {
icon: 1,
time: 1000
}, function() {
parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页
parent.layui.table.reload("tag-table");
});
} else {
layer.msg(result.msg, {
icon: 2,
time: 1000
});
}
}
})
return false;
});
})
</script>
{/block}

View File

@ -0,0 +1,90 @@
{extend name="public/admin_form" /}
{block name="body"}
<form class="layui-form" action="">
<div class="mainBox">
<div class="main-container">
<div class="layui-form-item">
<label class="layui-form-label">名称</label>
<div class="layui-input-inline">
<input type="text" name="name" lay-verify="required" placeholder="tag名" class="layui-input" value="{$tag.name}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">别名</label>
<div class="layui-input-inline">
<input type="text" name="ename" lay-verify="required" placeholder="英文或者拼音别名" class="layui-input" value="{$tag.ename}" >
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">关键词</label>
<div class="layui-input-inline">
<input type="text" name="keywords" lay-verify="required" placeholder="关键词 多个以逗号,隔开" autocomplete="off" class="layui-input" value="{$tag.keywords}">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">摘要</label>
<div class="layui-input-block">
<textarea type="text" name="description" lay-verify="required" placeholder="请输入内容" autocomplete="off" class="layui-textarea">{$tag.description}</textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">seo标题</label>
<div class="layui-input-inline">
<input type="text" name="title" lay-verify="required" placeholder="tag标题" autocomplete="off" class="layui-input" value="{$tag.title}">
</div>
</div>
</div>
</div>
<div class="bottom">
<div class="button-container">
<input type="text" name="id" lay-verify="required" class="layui-input layui-hide" value="{$tag.id}">
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit="" lay-filter="tag-save">
<i class="layui-icon layui-icon-ok"></i>
提交
</button>
<button type="reset" class="pear-btn pear-btn-sm">
<i class="layui-icon layui-icon-refresh"></i>
重置
</button>
</div>
</div>
</form>
{/block}
{block name="js"}
<script>
layui.use(['form', 'jquery'], function() {
let form = layui.form;
let $ = layui.jquery;
form.on('submit(tag-save)', function(data) {
$.ajax({
url: "{:url('content.tag/edit')}",
data: JSON.stringify(data.field),
dataType: 'json',
contentType: 'application/json',
type: 'post',
success: function(result) {
if (result.code === 0) {
layer.msg(result.msg, {
icon: 1,
time: 1000
}, function() {
parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页
parent.layui.table.reload("tag-table");
});
} else {
layer.msg(result.msg, {
icon: 2,
time: 1000
});
}
}
})
return false;
});
})
</script>
{/block}

View File

@ -0,0 +1,191 @@
{extend name="public/admin_base" /}
{block name="body"}
<div class="layui-card">
<div class="layui-card-body">
<table id="tag-table" lay-filter="tag-table" ></table>
</div>
</div>
<script type="text/html" id="tag-toolbar">
<button class="pear-btn pear-btn-primary pear-btn-md" lay-event="add">
<i class="layui-icon layui-icon-add-1"></i>
新增
</button>
<button class="pear-btn pear-btn-danger pear-btn-md" lay-event="batchRemove">
<i class="layui-icon layui-icon-delete"></i>
删除
</button>
</script>
<script type="text/html" id="tag-table-bar">
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit"><i class="layui-icon layui-icon-edit"></i></button>
<button class="pear-btn pear-btn-danger pear-btn-sm" lay-event="remove"><i class="layui-icon layui-icon-delete"></i></button>
</script>
{/block}
{block name="js"}
<script>
layui.use(['toast', 'common'], function(){
var $ = layui.jquery
,layer = layui.layer
,table = layui.table
,form = layui.form;
let toast = layui.toast;
let common = layui.common;
//第一个实例
table.render({
elem: '#tag-table'
,url: "{:url('content.tag/list')}" //数据接口
,page: true //开启分页
,cols: [[ //表头
{type: 'numbers', fixed: 'left'}
,{field: 'name', title: '名称', width:100}
,{field: 'ename', title: '别名', width:100}
,{field: 'keywords', title: '关键词', width:150}
,{field: 'description', title: '摘要', minWidth:300}
,{field: 'title', title: 'seo标题', width:200}
,{field: 'time', title: '时间', width:120}
,{title:'操作', toolbar: '#tag-table-bar', width:100}
]],
skin: 'line',
toolbar: '#tag-toolbar',
limit: 100,
text: '对不起,加载出现异常!'
});
table.on('tool(tag-table)', function(obj) {
if (obj.event === 'remove') {
window.remove(obj);
} else if (obj.event === 'edit') {
window.edit(obj);
}
});
table.on('toolbar(tag-table)', function(obj) {
if (obj.event === 'add') {
window.add();
} else if (obj.event === 'refresh') {
window.refresh();
} else if (obj.event === 'batchRemove') {
window.batchRemove(obj);
}
});
form.on('submit(Tag-link-search)', function(data){
$.post("{:url('Tag/list')}", {"tag":data.value}, function (data){
if (data.code == -1){
layer.open({content:data.msg,icon:5,anim:6});
}
}
);
//执行重载
table.reload('tag-link', {
where: {tag: data.value}
,page: {
curr: 1 //重新从第 1 页开始
}
});
});
window.add = function() {
layer.open({
type: 2,
title: '新增',
shade: 0.1,
area: [common.isModile()?'100%':'450px', common.isModile()?'100%':'500px'],
content: 'add.html'
});
}
window.edit = function(obj) {
layer.open({
type: 2,
title: '修改',
shade: 0.1,
area: [common.isModile()?'100%':'450px', common.isModile()?'100%':'500px'],
content: 'edit.html?id=' + obj.data.id
});
}
window.remove = function(obj) {
layer.confirm('确定要删除该用户', {
icon: 3,
title: '提示'
}, function(index) {
layer.close(index);
let loading = layer.load();
$.ajax({
url: "{:url('content.tag/delete')}?id=" + obj.data['id'],
dataType: 'json',
type: 'delete',
success: function(result) {
layer.close(loading);
if (result.code === 0) {
layer.msg(result.msg, {
icon: 1,
time: 1000
}, function() {
obj.del();
});
} else {
layer.msg(result.msg, {
icon: 2,
time: 1000
});
}
}
})
});
}
window.batchRemove = function(obj) {
var checkIds = common.checkField(obj,'id');
if (checkIds === "") {
layer.msg("未选中数据", {
icon: 3,
time: 1000
});
return false;
}
layer.confirm('确定要删除这些用户', {
icon: 3,
title: '提示'
}, function(index) {
layer.close(index);
let loading = layer.load();
$.ajax({
url: "{:url('content.tag/delete')}",
dataType: 'json',
type: 'delete',
data:{"id":checkIds},
success: function(result) {
layer.close(loading);
if (result.success) {
layer.msg(result.msg, {
icon: 1,
time: 1000
}, function() {
table.reload('tag-table');
});
} else {
layer.msg(result.msg, {
icon: 2,
time: 1000
});
}
}
})
});
}
window.refresh = function(param) {
table.reload('tag-table');
}
});
</script>
{/block}

File diff suppressed because it is too large Load Diff

View File

@ -108,7 +108,7 @@
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">
<div class="pear-card2">
<div class="title">待审文章</div>
<div class="count pear-text">14</div>
<div class="count pear-text">0</div>
</div>
</div>
<div class="layui-col-md6 layui-col-sm6 layui-col-xs6">

View File

@ -98,13 +98,13 @@
<li class="layui-col-xs6">
<a lay-href="javascript:;" class="layadmin-backlog-body">
<h3>待审商品</h3>
<p><cite>99</cite></p>
<p><cite>0</cite></p>
</a>
</li>
<li class="layui-col-xs6">
<a href="javascript:;" onclick="layer.tips('不跳转', this, {tips: 3});" class="layadmin-backlog-body">
<h3>待发货</h3>
<p><cite>20</cite></p>
<p><cite>0</cite></p>
</a>
</li>
</ul>

View File

@ -243,11 +243,18 @@
</div>
<hr>
<div class="layui-form-item">
<label class="layui-form-label">百度词条</label>
<label class="layui-form-label">菜单位置</label>
<div class="layui-input-inline" style="width: 60px;">
<input type="checkbox" name="baidu_title_switch" lay-skin="switch" lay-text="开启|关闭" value=1 {if config('taoler.config.baidu_title_switch') == 1} checked {/if}>
<input type="checkbox" name="nav_top" lay-skin="switch" lay-text="顶部|子栏" value=1 {if config('taoler.config.nav_top') == 1} checked {/if}>
</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" style="width: 60px;">
<input type="checkbox" name="top_show" lay-skin="switch" lay-text="列表|滚动" value=1 {if config('taoler.config.top_show') == 1} checked {/if}>
</div>
<div class="layui-form-mid layui-word-aux">置顶帖子列表或滚动显示</div>
</div>
<hr>
{if hook('mailserveractivehook')}
@ -412,8 +419,6 @@
}
});
// 获取描述的内容
$("input[name='article_as']").bind('input propertychange', function(){
var content = $(this).val()

View File

@ -12,15 +12,13 @@
<div class="layui-form-item">
<label class="layui-form-label">账号</label>
<div class="layui-input-block">
<input type="text" name="name" lay-verify="title" autocomplete="off" placeholder="请输入标题"
class="layui-input">
<input type="text" name="name" lay-verify="title" autocomplete="off" placeholder="请输入用户名" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">邮箱</label>
<div class="layui-input-block">
<input type="text" name="email" lay-verify="email" autocomplete="off" placeholder="请输入邮箱"
class="layui-input">
<input type="text" name="email" lay-verify="email" autocomplete="off" placeholder="请输入邮箱" class="layui-input">
</div>
</div>
<div class="layui-form-item">
@ -33,15 +31,13 @@
<div class="layui-form-item">
<label class="layui-form-label">密码</label>
<div class="layui-input-block">
<input type="text" name="password" lay-verify="password" autocomplete="off" placeholder="请输入密码"
class="layui-input">
<input type="text" name="password" lay-verify="password" autocomplete="off" placeholder="请输入密码" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">电话</label>
<div class="layui-input-block">
<input type="text" name="phone" lay-verify="title" autocomplete="off" placeholder="请输入标题"
class="layui-input">
<input type="text" name="phone" lay-verify="title" autocomplete="off" placeholder="请输入标题" class="layui-input">
</div>
</div>
<div class="layui-form-item">
@ -55,8 +51,7 @@
</div>
<div class="bottom">
<div class="button-container">
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit=""
lay-filter="user-save">
<button type="submit" class="pear-btn pear-btn-primary pear-btn-sm" lay-submit="" lay-filter="user-save">
<i class="layui-icon layui-icon-ok"></i>
提交
</button>
@ -90,8 +85,8 @@
icon: 1,
time: 1000
}, function() {
parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页
parent.layui.table.reload("user-table");
parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页
});
} else {
layer.msg(result.msg, {

View File

@ -76,6 +76,7 @@
layui.use(['form', 'jquery'], function() {
let form = layui.form;
let $ = layui.jquery;
let upload = layui.upload;
form.on('submit(user-save)', function(data) {
$.ajax({
@ -90,9 +91,8 @@
icon: 1,
time: 1000
}, function() {
parent.layer.close(parent.layer.getFrameIndex(window
.name)); //关闭当前页
parent.layui.table.reload("user-table");
parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页
});
} else {
layer.msg(result.msg, {
@ -104,6 +104,33 @@
})
return false;
});
//上传头像
upload.render({
elem: '#layuiadmin-upload-useradmin'
,url: "{:url('user.user/uploadImg')}"
,data: {type:'image'}
,accept: 'images'
,method: 'get'
,acceptMime: 'image/*'
,done: function(res){
$(this.item).prev("div").children("input").val(res.src);
if(res.code === 0){
layer.msg(res.msg,{
icon:6,
tiye:2000
});
} else {
layer.open({
title:"上传失败",
content:res.msg,
icon:5,
anim:6
});
}
}
});
})
</script>
<script>

View File

@ -13,13 +13,13 @@
<div class="layui-form-item layui-inline">
<label class="layui-form-label">ID</label>
<div class="layui-input-block">
<input type="text" name="id" placeholder="请输入" autocomplete="off" class="layui-input">
<input type="text" name="id" placeholder="请输入ID号" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">用户</label>
<label class="layui-form-label">用户</label>
<div class="layui-input-inline">
<input type="text" name="name" placeholder="" class="layui-input">
<input type="text" name="name" placeholder="用户名" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-inline">
@ -35,7 +35,7 @@
<div class="layui-form-item layui-inline">
<label class="layui-form-label">邮箱</label>
<div class="layui-input-inline">
<input type="text" name="email" placeholder="" class="layui-input">
<input type="text" name="email" placeholder="邮箱" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-inline">
@ -100,9 +100,9 @@
</script>
<script type="text/html" id="user-sex">
{{#if (d.sex == 1) { }}
{{#if (d.sex == 0) { }}
<span></span>
{{# }else if(d.sex == 2){ }}
{{# }else if(d.sex == 1){ }}
<span></span>
{{# } }}
</script>
@ -148,7 +148,7 @@
templet: '#imgTpl'
},
{
title: '账号',
title: '用户',
field: 'username',
align: 'center',
width: 100
@ -191,7 +191,7 @@
align: 'center'
},
{
title: '启用',
title: '状态',
field: 'check',
align: 'center',
width: 95,
@ -212,8 +212,7 @@
{
title: '注册',
field: 'jointime',
align: 'center',
templet: '#user-createTime'
align: 'center'
},
{
title: '操作',

View File

@ -58,11 +58,6 @@ try {
return 1;
}
//根据user area_id查询区域简称
function getAsing($area_id){
return Db::name('user_area')->where('id',$area_id)->cache(3600)->value('asing');
}
//根据用户主键ID查询用户名称
if(!function_exists('getUserName'))
{
@ -84,12 +79,14 @@ if(!function_exists('getUserImg'))
function getArtContent($content)
{
//过滤html标签
$content = strip_tags($content);
// $content = strip_tags($content);
// 去除所有& nbsp和html标签
$content = preg_replace("/(\s|\&nbsp\;|\&ldquo\;|\&rdquo\;| |\xc2\xa0)/", "", strip_tags($content));
// 过滤音视频图片
$content = preg_replace('/(?:img|audio|video)(\(\S+\))?\[\S+\]/','',$content);
$content = preg_replace('/\s*/','',$content);
$content = preg_replace('/\[[^\]]+\]/','',$content);
return mb_substr(strip_tags($content),0,150).'...';
return mb_substr($content,0,150).'...';
}
//根据帖子收藏主键ID查询帖子名称
@ -256,42 +253,66 @@ function getSpaceNmu($level)
return str_repeat('---',$level);
}
//链接投放开关,有设置则打开
function showSlider($type)
{
$sliders = new \app\common\model\Slider();
$sliderArr = $sliders->getSliderList($type);
if(!empty($sliderArr)) {
return true;
} else {
return false;
}
}
//提取内容第一张图片
function getOnepic($str)
{
//匹配格式为 <img src="http://img.com" />
$pattern = "/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.png]))[\'|\"].*?[\/]?>/";
preg_match_all($pattern,$str,$matchContent);
if(isset($matchContent[1][0])){
$img = $matchContent[1][0];
} else {
//$temp="./images/no-image.jpg";//在相应位置放置一张命名为no-image的jpg图片
preg_match($pattern,$str,$matchContent);
if(isset($matchContent[1])){
$img = $matchContent[1];
} else {
//$temp="./images/no-image.jpg";//在相应位置放置一张命名为no-image的jpg图片
//匹配格式为 img[/storage/1/article_pic/20220428/6c2647d24d5ca2c179e4a5b76990c00c.jpg]
$pattern = "/(?<=img\[)[^\]]*(?=\])/";
preg_match($pattern,$str,$matchContent);
if(isset($matchContent[0])){
$img = $matchContent[0];
}else{
return false;
}
//匹配格式为 img[/storage/1/article_pic/20220428/6c2647d24d5ca2c179e4a5b76990c00c.jpg]
$pattern = "/(?<=img\[)[^\]]*(?=\])/";
preg_match($pattern,$str,$matchContent);
if(isset($matchContent[0])){
$img = $matchContent[0];
}else{
return false;
}
}
return $img;
}
if (!function_exists('get_all_img')) {
/**
* 提取字符串中所有图片
* @param $str
* @return array
*/
function get_all_img($str)
{
//匹配格式为 <img src="http://img.com" />的图片
$pattern = "/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.png]))[\'|\"].*?[\/]?>/";
preg_match_all($pattern, $str,$matchContent);
if(isset($matchContent[1][0])) {
return array_unique($matchContent[1]);
}
return [];
}
}
if (!function_exists('get_all_video')) {
/**
* 提取字符串中所有图片
* @param $str
* @return array
*/
function get_all_video($str)
{
//匹配格式为 <video src="http://img.com" > </video> 的视频
$pattern = "/<[video|VIDEO][\s\S]*src=[\'|\"](.*?(?:[\.mp4|\.mkv|\.flv|\.avi]))[\'|\"].*?[<\/video]>/";
preg_match_all($pattern, $str,$matchs);
if(isset($matchs[1][0])) {
return array_unique($matchs[1]);
}
return [];
}
}
//判断蜘蛛函数
function find_spider(){
$useragent = strtolower(empty($useragent) ? Request::header('USER_AGENT') : '');

View File

@ -148,7 +148,7 @@ class AdminController extends \app\BaseController
}
/**
* 获取路由
* 把后台管理文章或帖子的路由转换为实际应用的路由
* @param int $aid
* @param string $appName
* @param string $ename
@ -203,6 +203,14 @@ class AdminController extends \app\BaseController
return $this->getDomain() . str_replace($map_admin, $appName, $articleUrl);
}
//3.admin未绑定域名也未映射
// 1.应用绑定了域名
if($app_bind) {
return $this->getDomain() . $articleUrl;
}
// 2.应用进行了映射
if($app_map){
return $this->getDomain() . str_replace('admin', $app_map, $articleUrl);
}
return str_replace('admin', $appName, $articleUrl);
}

View File

@ -17,9 +17,7 @@ use think\facade\View;
use think\facade\Db;
use think\facade\Session;
use think\facade\Cache;
use app\facade\Article;
use app\BaseController as BaseCtrl;
use app\common\model\Cate;
/**
* 控制器基础类
@ -40,8 +38,6 @@ class BaseController extends BaseCtrl
//变量赋给模板
View::assign([
//显示分类导航
'cateList' => $this->showNav(),
//显示子分类导航
'subcatelist' => $this->showSubnav(),
//当前登录用户
@ -66,29 +62,14 @@ class BaseController extends BaseCtrl
}
}
// 显示导航nav
protected function showNav()
{
$appname = app('http')->getName();
//1.查询分类表获取所有分类
$cate = new Cate();
$cateList = $cate->menu();
$list = getTree($cateList);
// 排序
$cmf_arr = array_column($list, 'sort');
array_multisort($cmf_arr, SORT_ASC, $list);
return $list;
}
// 显示子导航subnav
protected function showSubnav()
{
// dump($this->showNav());
//1.查询父分类id
$pCate = Db::name('cate')->field('id,pid,ename,catename,is_hot')->where(['ename'=>input('ename'),'status'=>1,'delete_time'=>0])->find();
if(empty($pCate)) { // 没有点击任何分类,点击首页获取全部分类信息
$subCateList = $this->showNav();
$subCateList = [];
} else { // 点击分类,获取子分类信息
$parentId = $pCate['id'];
$subCate = Db::name('cate')->field('id,ename,catename,is_hot,pid')->where(['pid'=>$parentId,'status'=>1,'delete_time'=>0])->select()->toArray();
@ -147,21 +128,11 @@ class BaseController extends BaseCtrl
{
//1.查询分类表获取所有分类
$sysInfo = $this->getSystem();
$slider = new \app\common\model\Slider();
//头部链接
$head_links = $slider->getSliderList(10);
//页脚链接
$foot_links = $slider->getSliderList(11);
//友情链接
$friend_links = $slider->getSliderList(9);
//获取热门标签
$hotTag = $this->getHotTag();
$assign = [
'sysInfo' => $sysInfo,
'headlinks' => $head_links,
'footlinks' => $foot_links,
'flinks' => $friend_links,
'hotTag' => $hotTag,
'host' => Request::domain() . '/'
];

View File

@ -34,78 +34,28 @@ class Arts
}
/**
* 获取文章链接地址
* @param int $aid 文章id
* @param string $ename 所属分类ename
* @param string $appname 所属应用名
* 非admin应用的文章url路由地址
* @param int $aid
* @param $ename
* @return string
*/
protected function getRouteUrl(int $aid, string $ename = '', string $appname = '') : string
public function getRouteUrl(int $aid, $ename = '')
{
$indexUrl = $this->getIndexUrl();
$domain = $this->getDomain();
$appName = app('http')->getName();
$articleUrl = (string) url('article_detail', ['id' => $aid]);
// 详情动态路由,$aid, $ename
if(config('taoler.url_rewrite.article_as') == '<ename>/'){
// 分类可变路由
$artUrl = (string) url('article_detail', ['id' => (int) $aid, 'ename'=> $ename]);
//$artUrl = (string) Route::buildUrl('article_detail', ['id' => $aid, 'ename'=> $ename]);
} else {
$artUrl = (string) url('article_detail', ['id' => $aid]);
}
//halt($indexUrl,$artUrl);
//多应用时,文章所属应用 2022.11.17
$app = app('http')->getName();
if(empty($appname)) {
// 获取article所属应用的应用名
$cid = Db::name('article')->where('id',$aid)->value('cate_id');
$appname = Db::name('cate')->where('id',$cid)->value('appname');
$articleUrl = (string) url('article_detail', ['id' => (int) $aid, 'ename'=> $ename]);
}
// 判断index应用是否绑定域名
$bind_index = array_search($appname, config('app.domain_bind'));
// 判断index应用是否域名映射
$map_index = array_search($appname, config('app.app_map'));
// article 所属应用名
$index = $map_index ?: $appname; // index应用名
// // 判断应用是否绑定域名
// $app_bind = array_search($appName, config('app.domain_bind'));
// // 判断应用是否域名映射
// $app_map = array_search($appName, config('app.app_map'));
// 判断是否开启绑定
//$domain_bind = array_key_exists('domain_bind',config('app'));
// 判断index应用是否绑定域名
//$bind_index = array_search('index',config('app.domain_bind'));
// 判断admin应用是否绑定域名
$bind_admin = array_search('admin',config('app.domain_bind'));
// 判断index应用是否域名映射
//$map_index = array_search('index',config('app.app_map'));
// 判断admin应用是否域名映射
$map_admin = array_search('admin',config('app.app_map'));
// $index = $map_index ?: 'index'; // index应用名
$admin = $map_admin ?: 'admin'; // admin应用名
if($bind_index) {
// echo 111;
// index或home前端(非admin应用)域名进行了绑定
// $url = $indexUrl . str_replace($admin . '/','',$artUrl);
$url = $indexUrl . $artUrl;
} else {
if($bind_admin) {
// echo 222;
// admin绑定域名
$url = $indexUrl .'/' . $index . $artUrl;
} elseif ($app == 'admin' && isset($map_admin)) {
// echo 333;
// var_dump($admin, $appname, $artUrl);
// admin进行了映射
$url = $indexUrl . str_replace($admin, $index, $artUrl);
} else {
// echo 444;
// admin未绑定域名
$url = $indexUrl . str_replace($app, $index, $artUrl);
}
}
//halt($url);
return $url;
//a.appName不是admin
return $domain . $articleUrl;
}
/**
@ -118,9 +68,18 @@ class Arts
*/
public function setKeywords(string $flag,string $title,string $content) :array
{
// 获取seo插件配置
$conf = get_addons_config('seo');
$keywords = [];
// seo插件配置
$addon = get_addons_instance('seo');
$config = $addon->getConfig();
$seo_token = $config['baidufenci']['access_token'];
// 百度分词自动生成关键词
if(!empty(config('taoler.baidu.client_id'))) {
if(!empty($seo_token)) {
//headers数组内的格式
$headers = [];
$headers[] = "Content-Type:application/json";
@ -128,16 +87,16 @@ class Arts
switch($flag) {
//分词
case 'word':
$url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?charset=UTF-8&access_token='.config('taoler.baidu.access_token');
$url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?charset=UTF-8&access_token='.$seo_token;
$body = ["text" => $title];
break;
//标签
case 'tag':
$url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/keyword?charset=UTF-8&access_token='.config('taoler.baidu.access_token');
$url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/keyword?charset=UTF-8&access_token='.$seo_token;
$body = ['title' => $title, 'content' => $content];
break;
default:
$url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?charset=UTF-8&access_token='.config('taoler.baidu.access_token');
$url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/lexer?charset=UTF-8&access_token='.$seo_token;
$body = ["text" => $title];
}
@ -181,9 +140,9 @@ class Arts
} else {
// 接口正常但获取数据失败可能参数错误重新获取token
$url = 'https://aip.baidubce.com/oauth/2.0/token';
$post_data['grant_type'] = config('taoler.baidu.grant_type');;
$post_data['client_id'] = config('taoler.baidu.client_id');
$post_data['client_secret'] = config('taoler.baidu.client_secret');
$post_data['grant_type'] = $config['baidufenci']['grant_type'];;
$post_data['client_id'] = $config['baidufenci']['client_id'];
$post_data['client_secret'] = $config['baidufenci']['client_secret'];
$o = "";
foreach ( $post_data as $k => $v )
@ -192,12 +151,11 @@ class Arts
}
$post_data = substr($o,0,-1);
$res = $this->request_post($url, $post_data);
// 写入token
SetArr::name('taoler')->edit([
'baidu'=> [
'access_token' => json_decode($res)->access_token,
]
]);
// 保存token
$conf['baidufenci']['value']['access_token'] = json_decode($res)->access_token;
set_addons_config('seo', $conf);
echo 'api接口数据错误 - ';
echo $dataItem->error_msg;
}
@ -260,8 +218,11 @@ class Arts
*/
public function baiduPushUrl(string $link)
{
// seo插件配置
$addon = get_addons_instance('seo');
$config = $addon->getConfig();
// baidu 接口
$api = config('taoler.baidu.push_api');
$api = $config['baidupush']['push_api'];
if(!empty($api)) {
$url[] = $link;
$ch = curl_init();

View File

@ -4,6 +4,7 @@ declare (strict_types = 1);
namespace app\common\lib;
use think\facade\Lang;
use think\Response;
class Msgres
{
@ -66,13 +67,13 @@ class Msgres
}
/**
* 成功提示
* @param string $strMsg
* @param string|null $url
* @param string $data
* @return string|\think\response\Json
* @param array|$data
* @return Response
*/
public static function success(string $strMsg = '',string $url = null, $data = '') {
public static function success(string $strMsg = '',string $url = null, array $data = []): Response
{
$result = [
'code' => self::getCode('success'),
'msg' => self::getMsg($strMsg),

View File

@ -93,7 +93,7 @@ class Uploads
}
// 解析存储位置 SYS_开头为系统位置
$isSys = stripos($dirName, 'SYS_');
if($isSys !== false) {
if($isSys) {
$disk = 'sys';
$dirName = substr($dirName,4);
$uploadDir = Config::get('filesystem.disks.sys.url');
@ -105,7 +105,7 @@ class Uploads
$rules = ['md5','date','sha1','uniqid'];
// 解析是否自定义文件名
if(!in_array($rule, $rules) && !is_null($rule)) {
if(stripos($rule, '.') == false) {
if(!stripos($rule, '.')) {
$rule = $file->getOriginalName();
}
$savename = Filesystem::disk($disk)->putFileAs($dirName, $file, $rule);
@ -160,7 +160,7 @@ class Uploads
// 解析存储位置 SYS_开头为系统位置
$isSys = stripos($dirName, 'SYS_');
if($isSys !== false) {
if($isSys) {
$disk = 'sys';
$dirName = substr($dirName,4);
$uploadDir = Config::get('filesystem.disks.sys.url');

View File

@ -111,7 +111,7 @@ class Article extends Model
{
return Cache::remember('topArticle', function() use($num){
return $this::field('id,title,title_color,cate_id,user_id,create_time,is_top,pv,upzip,has_img,has_video,has_audio')
return $this::field('id,title,title_color,cate_id,user_id,content,create_time,is_top,pv,upzip,has_img,has_video,has_audio,read_type,art_pass')
->where([['is_top', '=', 1], ['status', '=', 1]])
->with([
'cate' => function ($query) {
@ -140,7 +140,7 @@ class Article extends Model
public function getArtList(int $num)
{
return Cache::remember('indexArticle', function() use($num){
return $this::field('id,title,title_color,cate_id,user_id,create_time,is_hot,pv,jie,upzip,has_img,has_video,has_audio')
return $this::field('id,title,title_color,cate_id,user_id,content,create_time,is_hot,pv,jie,upzip,has_img,has_video,has_audio,read_type,art_pass')
->with([
'cate' => function($query){
$query->where('delete_time',0)->field('id,catename,ename,detpl');
@ -195,7 +195,7 @@ class Article extends Model
{
return Cache::remember('article_'.$id, function() use($id){
//查询文章
return $this::field('id,title,content,status,cate_id,user_id,goods_detail_id,is_top,is_hot,is_reply,pv,jie,upzip,downloads,keywords,description,title_color,create_time,update_time')
return $this::field('id,title,content,status,cate_id,user_id,goods_detail_id,is_top,is_hot,is_reply,pv,jie,upzip,downloads,keywords,description,read_type,art_pass,title_color,create_time,update_time')
->where(['status'=>1])
->with([
'cate' => function($query){
@ -247,7 +247,7 @@ class Article extends Model
$where[] = ['status', '=', 1];
return Cache::remember('cate_list_'.$ename.$type.$page, function() use($where,$page){
return $this::field('id,cate_id,user_id,title,content,title_color,create_time,is_top,is_hot,pv,jie,upzip,has_img,has_video,has_audio')
return $this::field('id,cate_id,user_id,title,content,title_color,create_time,is_top,is_hot,pv,jie,upzip,has_img,has_video,has_audio,read_type,art_pass')
->with([
'cate' => function($query) {
$query->field('id,catename,ename');
@ -381,16 +381,21 @@ class Article extends Model
}
// 获取所有帖子内容
public function getList($limit,$page)
public function getList(array $where, int $limit, int $page)
{
return $this::field('id,user_id,cate_id,title,content,is_top,is_hot,is_reply,status,update_time')->with([
return $this::field('id,user_id,cate_id,title,content,is_top,is_hot,is_reply,status,update_time,read_type,art_pass')
->with([
'user' => function($query){
$query->field('id,name,user_img');
},
'cate' => function($query){
$query->field('id,ename');
$query->field('id,ename,catename');
}
])->paginate([
])
->where(['status' => 1])
->where($where)
->order('create_time', 'desc')
->paginate([
'list_rows' => $limit,
'page' => $page
])->toArray();
@ -406,5 +411,15 @@ class Article extends Model
return (string) url('article_detail',['id' => $data['id']]);
}
// 内容是否加密
public function getContentAttr($value, $data)
{
//解密
if($data['read_type'] == 1 && (session('art_pass_'.$data['id']) !== $data['art_pass'])) {
return '内容已加密!请输入正确密码查看!';
}
return $value;
}
}

View File

@ -46,6 +46,12 @@ class Cate extends Model
return $this->field('ename,catename')->where('pid', $this::where('ename', $ename)->value('id'))->select();
}
// 查询兄弟分类
public function getBrotherCate(string $ename)
{
return $this->field('id,ename,catename')->where('pid', $this::where('ename', $ename)->value('pid'))->append(['url'])->order('sort asc')->select();
}
/**
* 删除分类
* @param $id
@ -81,10 +87,9 @@ class Cate extends Model
// 如果菜单下无内容URl不能点击
public function menu()
{
$appname = app('http')->getName();
try {
return $this->where(['status' => 1, 'appname' => $appname])
->cache('catename' . $appname, 3600)
return $this->where(['status' => 1])
->cache('catename', 3600)
->append(['url'])
->select()
->toArray();
@ -94,6 +99,24 @@ class Cate extends Model
}
// 分类导航菜单
public function getNav()
{
try {
$cateList = $this->where(['status' => 1])
->cache('catename', 3600)
->append(['url'])
->select()
->toArray();
// 排序
$cmf_arr = array_column($cateList, 'sort');
array_multisort($cmf_arr, SORT_ASC, $cateList);
return getTree($cateList);
} catch (DbException $e) {
return $e->getMessage();
}
}
// 获取url
public function getUrlAttr($value,$data)
{

View File

@ -35,12 +35,36 @@ class Comment extends Model
//获取评论
public function getComment($id, $page)
{
return $this::with(['user'])
$comment = $this::withTrashed()->with(['user'=>function($query){
$query->field('id,name,user_img,sign,city,vip');
}])
->where(['article_id'=>(int)$id,'status'=>1])
->order(['cai'=>'asc','create_time'=>'asc'])
->paginate(['list_rows'=>10, 'page'=>$page])
// ->paginate(['list_rows'=>10, 'page'=>$page])
->append(['touser'])
->select()
->toArray();
foreach ($comment as $k => $v)
{
if(empty($v['content'])){
unset($comment[$k]);
}
}
if(count($comment)) {
$data['data'] = getTree($comment);
$data['total'] = count($data['data']);
$arr = array_chunk($data['data'], 10);
//当前页
$page = $page - 1;
return ['total' => $data['total'], 'data' => $arr[$page]];
} else {
return ['total' => 0, 'data' => ''];
}
}
//回帖榜
@ -119,7 +143,26 @@ class Comment extends Model
return $userCommList;
}
public function getCommentList(array $where, int $page = 1, int$limit = 10)
{
return $this->field('id,article_id,user_id,content,status,create_time')
->with([
'user'=> function($query){
$query->field('id,name,user_img');
},
'article' => function($query) {
$query->field('id,title');
}
])
->where($where)
->order(['create_time' => 'desc'])
->paginate([
'list_rows' => $limit,
'page' => $page
])
->toArray();
}
// 获取url
public function getUrlAttr($value,$data)
@ -136,5 +179,36 @@ class Comment extends Model
return (string) url('detail',['id' => $data['id']]);
}
}
// 获取to_user_id
public function getTouserAttr($value,$data)
{
if(isset($data['to_user_id'])) {
return User::where('id', $data['to_user_id'])->value('name');
}
return '';
}
/**
* 评论没有被删除正常显示
* 评论被删除,但它下面有跟评时自身会显示为“评论已删除”,跟评会显示,无跟评且已删除则不显示
* @param $value
* @param $data
* @return string
*/
public function getContentAttr($value,$data)
{
if($data['delete_time'] == 0) {
return $value;
} else {
if($this::getByPid($data['id'])) {
return '<span style="text-decoration:line-through;">评论已删除</span>';
} else {
return '';
}
}
}
}

View File

@ -42,20 +42,16 @@ class Tag extends Model
/**
* 删除数据
*
* @param [type] $id
* @return void
* @param $id
* @return bool
*/
public function delTag($id)
{
//
$res = $this::destroy($id);
if($res == true) {
if($res) {
return true;
} else {
return false;
}
return false;
}
}

View File

@ -51,9 +51,9 @@ class User extends Model
public function login($data)
{
//查询使用邮箱或者用户名登陆
$user = $this::whereOr('email',$data['name'])->whereOr('name',$data['name'])->findOrEmpty();
$user = $this::whereOr('phone',$data['name'])->whereOr('email',$data['name'])->whereOr('name',$data['name'])->findOrEmpty();
if(!($user->isEmpty())){
if(!$user->isEmpty()){
//被禁用和待审核
if($user['status'] == -1){
return Lang::get('Account disabled');

View File

@ -11,34 +11,27 @@
namespace app\common\model;
use think\Model;
//use think\model\concern\SoftDelete;
class UserZan extends Model
{
protected $autoWriteTimestamp = true; //开启自动时间戳
protected $createTime = 'create_time';
//软删除
//use SoftDelete;
//protected $deleteTime = 'delete_time';
//protected $defaultSoftDelete = 0;
public function comment()
{
//评论关联文章
//关联评论
return $this->belongsTo('Comment','comment_id','id');
}
public function user()
{
//评论关联用户
//关联用户
return $this->belongsTo('User','user_id','id');
}
public function article()
{
//评论关联用户
//关联文章
return $this->belongsTo(Article::class);
}

View File

@ -8,12 +8,11 @@
* @FilePath: \TaoLer\app\common\taglib\Article.php
* Copyright (c) 2020~2022 https://www.aieok.com All rights reserved.
*/
//declare (strict_types = 1);
declare (strict_types = 1);
namespace app\common\taglib;
use think\template\TagLib;
use app\common\model\Article as ArticleModel;
class Article extends TagLib
{
@ -21,71 +20,149 @@ class Article extends TagLib
protected $tags = [
// 标签定义: attr 属性列表 close 是否闭合0 或者1 默认1 alias 标签别名 level 嵌套层次
'id' => ['attr' => '', 'close' => 0],
'title' => ['attr' => 'cid', 'close' => 0],
'content' => ['attr' => 'name', 'close' => 0],
'istop' => ['attr' => '', 'close' => 0],
'aname' => ['attr' => 'name', 'close' => 0],
'commentnum' => ['attr' => 'name', 'close' => 0],
'title' => ['attr' => '', 'close' => 0],
'content' => ['attr' => '', 'close' => 0],
'auther' => ['attr' => '', 'close' => 0],
'pv' => ['attr' => '', 'close' => 0],
'title_color' => ['attr' => '', 'close' => 0],
'comment_num' => ['attr' => '', 'close' => 0],
'keywords' => ['attr' => '', 'close' => 0],
'description' => ['attr' => '', 'close' => 0],
'link' => ['attr' => '', 'close' => 0],
'time' => ['attr' => '', 'close' => 0],
'cate' => ['attr' => 'name', 'close' => 0],
'user' => ['attr' => 'name', 'close' => 0],
'list' => ['attr' => '', 'close' => 1],
'comment' => ['attr' => '', 'close' => 1],
'istop' => ['attr' => '', 'close' => 0],
'detail' => ['attr' => 'name', 'close' => 0],
// 'detail' => ['attr' => '', 'close' => 0],
];
// public function __construct($a)
// {
// $id = (int) input('id');
// $this->id = $id;
// $page = input('page') ? (int) input('page') : 1;
// //parent::__construct();
// if(request()->action() == 'detail') {
// $article = new ArticleModel();
// $this->article = $article->getArtDetail($id);
// // dump($this->article);
// }
// }
public function tagId($tag): string
// id
public function tagId(): string
{
//dump($tag);
$parseStr = $this->article;
//return $parseStr;
return '<?php echo "' . $parseStr['id'] . '"; ?>';
return '{$article.id}';
}
public function tagTitle(array $tag, string $content): string
public function tagTitle(): string
{
$cid = (int) $this->tpl->get('cid');
$article = new ArticleModel();
$art = $article->getArtDetail($cid);
//dump($art);
$parseStr = $art['title'];
//$parseStr = 123;
//return $parseStr;
return '<?php echo "' . $parseStr . '"; ?>';
return '{$article.title}';
}
public function tagContent($tag): string
public function tagContent(): string
{
$parseStr = $this->article['content'];
//return $parseStr;
return '<?php echo "' . $parseStr . '"; ?>';
return '{$article.content|raw}';
}
public function tagAname($tag): string
public function tagAuther(): string
{
$parseStr = $this->article['user']['nickname'] ?: $this->article['user']['name'];
// dump($parseStr);
return '{$article.user.nickname ?: $article.user.name}';
}
public function tagPv()
{
return '{$article.pv}';
}
public function tagComment_num(): string
{
return '{$article.comments_count}';
}
public function tagTitle_color(): string
{
return '{$article.title_color ?: "#333"}';
}
public function tagKeywords(): string
{
return '{$article.keywords ?: $article.title}';
}
public function tagDescription(): string
{
return '{$article.description}';
}
public function tagLink(): string
{
return '{$article.url}';
}
public function tagTime(): string
{
return '{$article.create_time}';
}
// 详情分类
public function tagCate($tag): string
{
if($tag['name'] == 'name')
{
return '{$article.cate.catename}';
}
if($tag['name'] == 'ename')
{
return '{$article.cate.ename}';
}
if($tag['name'] == 'id')
{
return '{$article.cate_id}';
}
if($tag['name'] == 'link')
{
return '{:url(\'cate\',[\'ename\'=>$article.cate.ename])}';
}
return '';
}
public function tagUser($tag)
{
if($tag['name'] == 'link') {
return '{:url("user/home",["id"=>'.'$'.'article.user.id'.'])->domain(true)}';
}
return '{$article.user.' . $tag['name'] . '}';
}
public function tagCateName()
{
return '{$article.cate.catename}';
}
public function tagCateename()
{
return '{$article.cate.id}';
}
// 详情
// public function tagDetail($tag)
// {
// return '{$article.' . $tag['name'] . '}';
// }
// 详情
public function tagDetail($tag)
{
$parseStr = '{assign name="id" value="$Request.param.id" /}';
$parseStr .= '<?php ';
$parseStr .= '$__article__ = \app\facade\Article::find($id);';
$parseStr .= ' ?>';
$parseStr .= '{$__article__.'. $tag['name'] .'}';
return $parseStr;
}
public function tagCommentnum($tag): string
{
$parseStr = $this->article['comments_count'];
// dump($parseStr);
return $parseStr;
}
public function tagIstop($tag): string
{
@ -98,18 +175,35 @@ class Article extends TagLib
return $parseStr;
}
// public function tagComment($tag, $content): string
// {
// //
// //$arr = $this->getComments($this->id, $this->page);
// $parse = '<?php ';
// $parse .= '$comment_arr=[[1,3,5,7,9],[2,4,6,8,10]];'; // 这里是模拟数据
// $parse .= '$__LIST__ = $comment_arr[' . $type . '];';
/** $parse .= ' ?>';*/
// $parse .= '{volist name="__LIST__" id="' . $name . '"}';
// $parse .= $content;
// $parse .= '{/volist}';
// return $parse;
// }
// 评论
public function tagComment2($tag, $content): string
{
$parse = '<?php ';
$parse .= ' ?>';
$parse .= '{volist name="comments" id="comment" empty= "还没有内容"}';
$parse .= $content;
$parse .= '{/volist}';
return $parse;
}
// 评论
public function tagComment($tag, $content): string
{
$parse = '<?php ';
$parse .= ' ?>';
$parse .= '{volist name="comments['.'\'data\''.']" id="comment" empty= "还没有内容"}';
$parse .= $content;
$parse .= '{/volist}';
return $parse;
}
// 分类列表
public function tagList($tag, $content): string
{
$parse = '{volist name="artList['.'\'data\''.']" id="article" empty= "还没有内容"}';
$parse .= $content;
$parse .= '{/volist}';
return $parse;
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* @Program: table.css 2023/4/17
* @FilePath: app\common\taglib\Cate.php
* @Description: Cate.php
* @LastEditTime: 2023-04-17 21:19:59
* @Author: Taoker <317927823@qq.com>
* @Copyright (c) 2020~2023 https://www.aieok.com All rights reserved.
*/
namespace app\common\taglib;
use think\template\TagLib;
class Cate extends TagLib
{
protected $tags = [
'brother' => ['attr' => '', 'close' => 1],
'bro_name' => ['attr' => '', 'close' => 0],
'bro_ename' => ['attr' => '', 'close' => 0],
'bro_url' => ['attr' => '', 'close' => 0],
'list' => ['attr' => '', 'close' => 1]
];
public function tagBrother($tag, $content): string
{
$parse = '{assign name="ename" value="$Request.param.ename" /}';
$parse .= '{php}$__brotherCate__ = \app\facade\Cate::getBrotherCate($ename);{/php}';
$parse .= '{volist name="__brotherCate__" id="brother"}';
$parse .= $content;
$parse .= '{/volist}';
return $parse;
}
public function tagBro_name($tag): string
{
return '{$brother.catename}';
}
public function tagBro_ename($tag): string
{
return '{$brother.ename}';
}
public function tagBro_url($tag): string
{
return '{$brother.url}';
}
public function tagList($tag, $content): string
{
//$paras = ;
}
}

View File

@ -0,0 +1,82 @@
<?php
/*
* @Program: table.css 2023/4/16
* @FilePath: app\common\taglib\Comment.php
* @Description: Comment.php 评论标签
* @LastEditTime: 2023-04-16 11:37:01
* @Author: Taoker <317927823@qq.com>
* @Copyright (c) 2020~2023 https://www.aieok.com All rights reserved.
*/
namespace app\common\taglib;
use think\template\TagLib;
/**
* 评论内容
*/
class Comment extends TagLib
{
/**
* @var array[]
*/
protected $tags = [
// 标签定义: attr 属性列表 close 是否闭合0 或者1 默认1 alias 标签别名 level 嵌套层次
'id' => ['attr' => '', 'close' => 0],
'content' => ['attr' => '', 'close' => 0],
'time' => ['attr' => '', 'close' => 0],
'zan' => ['attr' => '', 'close' => 0],
'uid' => ['attr' => '', 'close' => 0],
'uname' => ['attr' => '', 'close' => 0],
'uimg' => ['attr' => '', 'close' => 0],
'ulink' => ['attr' => '', 'close' => 0],
'usign' => ['attr' => '', 'close' => 0],
];
public function tagId()
{
return '{$comment.id}';
}
public function tagContent()
{
return '{$comment.content|raw}';
}
public function tagTime()
{
return '{$comment.create_time}';
}
public function tagZan()
{
return '{$comment.zan}';
}
public function tagUid()
{
return '{$comment.user_id}';
}
public function tagUname()
{
return '{$comment.user.nickname ?: $comment.user.name}';
}
public function tagUimg()
{
return '{$comment.user.user_img}';
}
public function tagUlink()
{
return '{:url("user/home",["id"=>'.'$'.'comment.user_id'.'])->domain(true)}';
}
public function tagUsign()
{
return '{$comment.user.sign|raw}';
}
}

View File

@ -0,0 +1,95 @@
<?php
/**
* @Program: table.css 2023/4/17
* @FilePath: app\common\taglib\Gnav.php
* @Description: Gnav.php
* @LastEditTime: 2023-04-17 15:37:40
* @Author: Taoker <317927823@qq.com>
* @Copyright (c) 2020~2023 https://www.aieok.com All rights reserved.
*/
namespace app\common\taglib;
use think\template\TagLib;
class Gnav extends TagLib
{
protected $tags = [
// 标签定义: attr 属性列表 close 是否闭合0 或者1 默认1 alias 标签别名 level 嵌套层次
//'nav' => ['attr' => '', 'close' => 1],
'id' => ['attr' => '', 'close' => 0],
'pid' => ['attr' => '', 'close' => 0],
'icon' => ['attr' => '', 'close' => 0],
'name' => ['attr' => '', 'close' => 0],
'ename' => ['attr' => '', 'close' => 0],
'title' => ['attr' => '', 'close' => 0],
'detpl' => ['attr' => '', 'close' => 0],
'sort' => ['attr' => '', 'close' => 0],
'desc' => ['attr' => '', 'close' => 0],
'is_hot' => ['attr' => '', 'close' => 0],
'link' => ['attr' => '', 'close' => 0],
'children' => ['attr' => '', 'close' => 0],
];
public function tagId(): string
{
return '{$gnav.id}';
}
public function tagPid(): string
{
return '{$gnav.pid}';
}
public function tagIcon(): string
{
return '{$gnav.icon}';
}
public function tagName($tag): string
{
return '{$gnav.catename}';
}
public function tagEname(): string
{
return '{$gnav.ename}';
}
public function tagTitle(): string
{
return '{:cookie(\'think_lang\') == \'en-us\' ? $gnav.ename : $gnav.catename}';
}
public function tagDetpl(): string
{
return '{$gnav.detpl}';
}
public function tagSort(): string
{
return '{$gnav.sort}';
}
public function tagDesc(): string
{
return '{$gnav.desc}';
}
public function tagIs_hot(): string
{
return '{$gnav.is_hot}';
}
public function tagLink(): string
{
return '{$gnav.url}';
}
public function tagChildren(): string
{
return '{$gnav.children}';
}
}

96
app/common/taglib/Nav.php Normal file
View File

@ -0,0 +1,96 @@
<?php
/**
* @Program: table.css 2023/4/17
* @FilePath: app\common\taglib\Nav.php
* @Description: Nav.php
* @LastEditTime: 2023-04-17 14:25:08
* @Author: Taoker <317927823@qq.com>
* @Copyright (c) 2020~2023 https://www.aieok.com All rights reserved.
*/
namespace app\common\taglib;
use think\template\TagLib;
class Nav extends TagLib
{
protected $tags = [
// 标签定义: attr 属性列表 close 是否闭合0 或者1 默认1 alias 标签别名 level 嵌套层次
//'nav' => ['attr' => '', 'close' => 1],
'id' => ['attr' => '', 'close' => 0],
'pid' => ['attr' => '', 'close' => 0],
'icon' => ['attr' => '', 'close' => 0],
'name' => ['attr' => '', 'close' => 0],
'ename' => ['attr' => '', 'close' => 0],
'title' => ['attr' => '', 'close' => 0],
'detpl' => ['attr' => '', 'close' => 0],
'sort' => ['attr' => '', 'close' => 0],
'desc' => ['attr' => '', 'close' => 0],
'is_hot' => ['attr' => '', 'close' => 0],
'link' => ['attr' => '', 'close' => 0],
'children' => ['attr' => '', 'close' => 0],
];
public function tagId(): string
{
return '{$nav.id}';
}
public function tagPid(): string
{
return '{$nav.pid}';
}
public function tagIcon(): string
{
return '{$nav.icon}';
}
public function tagName($tag): string
{
return '{$nav.catename}';
}
public function tagEname(): string
{
return '{$nav.ename}';
}
public function tagTitle(): string
{
return '{:cookie(\'think_lang\') == \'en-us\' ? $nav.ename : $nav.catename}';
}
public function tagDetpl(): string
{
return '{$nav.detpl}';
}
public function tagSort(): string
{
return '{$nav.sort}';
}
public function tagDesc(): string
{
return '{$nav.desc}';
}
public function tagIs_hot(): string
{
return '{$nav.is_hot}';
}
public function tagLink(): string
{
return '{$nav.url}';
}
public function tagChildren(): string
{
return '{$nav.children}';
}
}

View File

@ -0,0 +1,95 @@
<?php
/**
* @Program: table.css 2023/4/17
* @FilePath: app\common\taglib\Snav.php
* @Description: Snav.php
* @LastEditTime: 2023-04-17 15:37:30
* @Author: Taoker <317927823@qq.com>
* @Copyright (c) 2020~2023 https://www.aieok.com All rights reserved.
*/
namespace app\common\taglib;
use think\template\TagLib;
class Snav extends TagLib
{
protected $tags = [
// 标签定义: attr 属性列表 close 是否闭合0 或者1 默认1 alias 标签别名 level 嵌套层次
//'nav' => ['attr' => '', 'close' => 1],
'id' => ['attr' => '', 'close' => 0],
'pid' => ['attr' => '', 'close' => 0],
'icon' => ['attr' => '', 'close' => 0],
'name' => ['attr' => '', 'close' => 0],
'ename' => ['attr' => '', 'close' => 0],
'title' => ['attr' => '', 'close' => 0],
'detpl' => ['attr' => '', 'close' => 0],
'sort' => ['attr' => '', 'close' => 0],
'desc' => ['attr' => '', 'close' => 0],
'is_hot' => ['attr' => '', 'close' => 0],
'link' => ['attr' => '', 'close' => 0],
'children' => ['attr' => '', 'close' => 0],
];
public function tagId(): string
{
return '{$snav.id}';
}
public function tagPid(): string
{
return '{$snav.pid}';
}
public function tagIcon(): string
{
return '{$snav.icon}';
}
public function tagName($tag): string
{
return '{$snav.catename}';
}
public function tagEname(): string
{
return '{$snav.ename}';
}
public function tagTitle(): string
{
return '{:cookie(\'think_lang\') == \'en-us\' ? $snav.ename : $snav.catename}';
}
public function tagDetpl(): string
{
return '{$snav.detpl}';
}
public function tagSort(): string
{
return '{$snav.sort}';
}
public function tagDesc(): string
{
return '{$snav.desc}';
}
public function tagIs_hot(): string
{
return '{$snav.is_hot}';
}
public function tagLink(): string
{
return '{$snav.url}';
}
public function tagChildren(): string
{
return '{$snav.children}';
}
}

View File

@ -0,0 +1,120 @@
<?php
/**
* @Program: table.css 2023/5/16
* @FilePath: app\common\taglib\System.php
* @Description: System.php
* @LastEditTime: 2023-05-16 21:34:18
* @Author: Taoker <317927823@qq.com>
* @Copyright (c) 2020~2023 https://www.aieok.com All rights reserved.
*/
namespace app\common\taglib;
use think\template\TagLib;
class System extends TagLib
{
protected $tags = [
// 标签定义: attr 属性列表 close 是否闭合0 或者1 默认1 alias 标签别名 level 嵌套层次
'webname' => ['attr' => '', 'close' => 0],
'webtitle' => ['attr' => '', 'close' => 0],
'domain' => ['attr' => '', 'close' => 0],
'template' => ['attr' => '', 'close' => 0],
'logo' => ['attr' => '', 'close' => 0],
'm_logo' => ['attr' => '', 'close' => 0],
'cache' => ['attr' => '', 'close' => 0],
'upsize' => ['attr' => '', 'close' => 0],
'uptype' => ['attr' => '', 'close' => 0],
'copyright' => ['attr' => '', 'close' => 0],
'keywords' => ['attr' => '', 'close' => 0],
'descript' => ['attr' => '', 'close' => 0],
'state' => ['attr' => '', 'close' => 0],
'is_open' => ['attr' => '', 'close' => 0],
'is_comment' => ['attr' => '', 'close' => 0],
'is_reg' => ['attr' => '', 'close' => 0],
'icp' => ['attr' => '', 'close' => 0],
'showlist' => ['attr' => '', 'close' => 0],
'blackname' => ['attr' => '', 'close' => 0],
'sys_version_num'=> ['attr' => '', 'close' => 0],
'key' => ['attr' => '', 'close' => 0],
'clevel' => ['attr' => '', 'close' => 0],
'api_url' => ['attr' => '', 'close' => 0],
'base_url' => ['attr' => '', 'close' => 0],
'upcheck_url' => ['attr' => '', 'close' => 0],
'upgrade_url' => ['attr' => '', 'close' => 0],
'create_time' => ['attr' => '', 'close' => 0],
'update_time' => ['attr' => '', 'close' => 0]
];
public function tagWebname(): string
{
return '{$sysInfo.webname}';
}
public function tagWebtitle(): string
{
return '{$sysInfo.webtitle}';
}
public function tagDomain(): string
{
return '{$sysInfo.domain}';
}
public function tagTemplate(): string
{
return '{$sysInfo.template}';
}
public function tagLogo(): string
{
return '{$sysInfo.logo}';
}
public function tagMlogo(): string
{
return '{$sysInfo.m_logo}';
}
public function tagCopyright(): string
{
return '{$sysInfo.copyright}';
}
public function tagKeywords(): string
{
return '{$sysInfo.keywords}';
}
public function tagDescript(): string
{
return '{$sysInfo.descript}';
}
public function tagState(): string
{
return '{$sysInfo.state}';
}
public function tagIcp(): string
{
return '{$sysInfo.icp}';
}
public function tagSys_version(): string
{
return '{$sysInfo.sys_version_num}';
}
public function tagKey(): string
{
return '{$sysInfo.key}';
}
public function tagCreate_time(): string
{
return '{$sysInfo.create_time}';
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* @Program: table.css 2023/4/15
* @FilePath: app\common\taglib\Taoler.php
* @Description: Taoler.php
* @LastEditTime: 2023-04-15 11:09:54
* @Author: Taoker <317927823@qq.com>
* @Copyright (c) 2020~2023 https://www.aieok.com All rights reserved.
*/
namespace app\common\taglib;
use think\template\TagLib;
class Taoler extends TagLib
{
protected $tags = [
// 标签定义: attr 属性列表 close 是否闭合0 或者1 默认1 alias 标签别名 level 嵌套层次
'nav' => ['attr' => '', 'close' => 1],
'snav' => ['attr' => '', 'close' => 1],
'gnav' => ['attr' => '', 'close' => 1],
'if' => ['condition', 'expression' => true, 'close' => 1],
];
public function tagNav($tag, $content): string
{
$id = $tag['id'] ?? 'nav';
$parse = '{php}$__cate__ = \app\facade\Cate::getNav();{/php}';
$parse .= '{volist name="__cate__" id="'.$id.'"}';
$parse .= $content;
$parse .= '{/volist}';
return $parse;
}
public function tagSnav($tag, $content): string
{
$id = $tag['id'] ?? 'snav';
$parse = '{notempty name="nav.children"}';
$parse .= '{volist name="nav.children" id="'.$id.'"}';
$parse .= $content;
$parse .= '{/volist}';
$parse .= '{/notempty}';
return $parse;
}
public function tagGnav($tag, $content): string
{
$id = $tag['id'] ?? 'gnav';
$parse = '{notempty name="snav.children"}';
$parse .= '{volist name="snav.children" id="'.$id.'"}';
$parse .= $content;
$parse .= '{/volist}';
$parse .= '{/notempty}';
return $parse;
}
public function tagIf($tag, $content): string
{
$condition = !empty($tag['expression']) ? $tag['expression'] : $tag['condition'];
$condition = $this->parseCondition($condition);
$parseStr = '<?php if(' . $condition . '): ?>' . $content . '<?php endif; ?>';
return $parseStr;
// return '{if'.$tag.'}} '.$content.' {/if}';
}
}

View File

@ -17,6 +17,7 @@ class User extends Validate
protected $rule = [
'name|用户名' => 'require|min:2|max:18|chsDash|unique:user',
'email|邮箱' => 'require|email|unique:user',
'phone|手机号' => 'require|mobile|unique:user',
'password|密码' => 'require|min:6|max:20',
'repassword|确认密码'=>'require|confirm:password',
'nickname|昵称' => 'require|min:2|max:20',
@ -48,11 +49,23 @@ class User extends Validate
->remove('email', 'unique');
}
//注册验证场景
//phone登陆验证场景
public function sceneLoginPhone()
{
return $this->only(['phone','password'])
->remove('phone', 'unique');
}
//注册验证场景
public function sceneReg()
{
return $this->only(['name','email','password','repassword']);
}
//后台注册验证场景
public function sceneUserReg()
{
return $this->only(['name','email','phone','password']);
}
//密码找回

View File

@ -3,13 +3,37 @@
// | 模板设置
// +----------------------------------------------------------------------
use think\facade\Db;
use taoler\com\Files;
use think\facade\Cache;
//如果网站安装从数据库查询选择的模板
if(file_exists('./install.lock')){
$template = Db::name('system')->where('id',1)->value('template');
$template = Db::name('system')->where('id',1)->cache(true)->value('template');
} else {
$template = '';
}
$taglib_pre_load = Cache::remember('taglib', function(){
$tagsArr = [];
//获取应用公共标签app/common/taglib
$common_taglib = Files::getAllFile(root_path().'app/common/taglib');
foreach ($common_taglib as $t) {
$tagsArr[] = str_replace('/','\\',strstr(strstr($t, 'app/'), '.php', true));
}
//获取插件下标签 addons/taglib文件
$localAddons = Files::getDirName('../addons/');
foreach($localAddons as $v) {
$dir = root_path(). 'addons'. DIRECTORY_SEPARATOR . $v . DIRECTORY_SEPARATOR .'taglib';
if(!file_exists($dir)) continue;
$addons_taglib = Files::getAllFile($dir);
foreach ($addons_taglib as $a) {
$tagsArr[] = str_replace('/','\\',strstr(strstr($a, 'addons'), '.php', true));
}
}
return implode(',', $tagsArr);
});
return [
// 模板引擎类型使用Think
'type' => 'Think',
@ -19,8 +43,10 @@ return [
'view_dir_name' => 'view' . DIRECTORY_SEPARATOR . $template,
// 模板后缀
'view_suffix' => 'html',
// 定义内置标签
//'taglib_build_in' => 'app\common\taglib\Article',
// 预先加载的标签库
'taglib_pre_load' => 'app\common\taglib\Article',
'taglib_pre_load' => $taglib_pre_load,
// 模板文件名分隔符
'view_depr' => DIRECTORY_SEPARATOR,
// 模板引擎普通标签开始标记

View File

@ -1 +1,2 @@
Api.php
Api.php
Works.php

View File

@ -3,15 +3,15 @@
namespace app\index\controller;
use app\common\controller\BaseController;
use think\App;
use think\facade\View;
use think\facade\Request;
use think\facade\Db;
use think\facade\Cache;
use think\facade\Session;
use think\facade\Config;
use app\common\model\Cate;
use app\common\model\Comment;
use app\common\model\Article as ArticleModel;
use app\common\model\Slider;
use app\common\model\UserZan;
use app\common\model\PushJscode;
use taoler\com\Message;
@ -22,13 +22,19 @@ class Article extends BaseController
protected $middleware = [
'logincheck' => ['except' => ['cate','detail','download'] ],
];
//文章分类
protected $model;
public function __construct(App $app)
{
parent::__construct($app);
$this->model = new \app\common\model\Article();
}
//文章分类
public function cate()
{
$cate = new Cate();
$ad = new Slider();
$article = new ArticleModel();
//动态参数
$ename = Request::param('ename');
$type = Request::param('type','all');
@ -43,13 +49,10 @@ class Article extends BaseController
$path = substr($url,0,strrpos($url,"/"));
//分类列表
$artList = $article->getCateList($ename,$type,$page);
$artList = $this->model->getCateList($ename,$type,$page);
// 热议文章
$artHot = $article->getArtHot(10);
//分类图片
$ad_cateImg = $ad->getSliderList(3);
//分类钻展赞助
$ad_comm = $ad->getSliderList(6);
$artHot = $this->model->getArtHot(10);
$assignArr = [
'ename'=>$ename,
@ -57,8 +60,6 @@ class Article extends BaseController
'type'=>$type,
'artList'=>$artList,
'artHot'=>$artHot,
'ad_cateImg'=>$ad_cateImg,
'ad_comm'=>$ad_comm,
'path'=>$path,
'jspage'=>'jie'
];
@ -74,19 +75,12 @@ class Article extends BaseController
$id = input('id');
$page = input('page',1);
//输出内容
$article = new ArticleModel();
$artDetail = $article->getArtDetail($id);
if(is_null($artDetail)){
// 抛出 HTTP 异常
throw new \think\exception\HttpException(404, '无内容');
}
//用户个人tag标签
$userTags = $article->where(['user_id'=>$artDetail['user_id'],'status'=>1])->where('keywords','<>','')->column('keywords');
//转换为字符串
$tagStr = implode(",",$userTags);
//转换为数组并去重
$tagArr = array_unique(explode(",",$tagStr));
$userTagCount = count($tagArr);
$artDetail = $this->model->getArtDetail($id);
if(is_null($artDetail)){
throw new \think\exception\HttpException(404, '无内容');
}
//被赞
$zanCount = Db::name('user_zan')->where('user_id', $artDetail['user_id'])->count('id');
//赞列表
$userZanList = [];
@ -96,10 +90,9 @@ class Article extends BaseController
$userZanList[] = ['userImg'=>$v->user->user_img,'name'=>$v->user->name];
}
}
// 设置内容的tag内链
$artDetail['content'] = $this->setArtTagLink($artDetail['content']);
$artDetail->content = $this->setArtTagLink($artDetail->content);
// 标签
$tags = [];
@ -112,7 +105,7 @@ class Article extends BaseController
$tags[] = ['name'=>$tag['name'],'url'=> (string) url('tag_list',['ename'=>$tag['ename']])];
}
//相关帖子
$relationArticle = $article->getRelationTags($artTags[0]['tag_id'],$id,5);
$relationArticle = $this->model->getRelationTags($artTags[0]['tag_id'],$id,5);
}
$tpl = Db::name('cate')->where('id', $artDetail['cate_id'])->value('detpl');
@ -121,9 +114,10 @@ class Article extends BaseController
//浏览pv
Db::name('article')->where('id',$id)->inc('pv')->update();
$pv = Db::name('article')->field('pv')->where('id',$id)->value('pv');
$artDetail->pv = $pv;
//上一篇下一篇
$upDownArt = $article->getPrevNextArticle($id,$artDetail['cate_id']);
$upDownArt = $this->model->getPrevNextArticle($id,$artDetail['cate_id']);
if(empty($upDownArt['previous'][0])) {
$previous = '前面已经没有了!';
} else {
@ -137,17 +131,10 @@ class Article extends BaseController
//评论
$comments = $this->getComments($id, $page);
//halt($comments);
//最新评论时间
$lrDate_time = Db::name('comment')->where('article_id', $id)->max('update_time',false) ?? time();
// 热议文章
$artHot = $article->getArtHot(10);
//广告
$ad = new Slider();
//分类图片
$ad_artImg = $ad->getSliderList(4);
//分类钻展赞助
$ad_comm = $ad->getSliderList(7);
$artHot = $this->model->getArtHot(10);
//push
$push_js = Db::name('push_jscode')->where(['delete_time'=>0,'type'=>1])->cache(true)->select();
@ -155,8 +142,6 @@ class Article extends BaseController
'article' => $artDetail,
'pv' => $pv,
'artHot' => $artHot,
'ad_art' => $ad_artImg,
'ad_comm' => $ad_comm,
'tags' => $tags,
'relationArticle' => $relationArticle,
'previous' => $previous,
@ -167,8 +152,9 @@ class Article extends BaseController
'cid' => $id,
'lrDate_time' => $lrDate_time,
'userZanList' => $userZanList,
'userTagCount'=> $userTagCount,
'jspage' => 'jie',
'zanCount' => $zanCount,
'jspage' => 'jie',
'passJieMi' => session('art_pass_'.$id),
$download,
]);
@ -190,8 +176,10 @@ class Article extends BaseController
if (Request::isAjax()){
//获取评论
$data = Request::only(['content','article_id','user_id']);
$data = Request::only(['content','article_id','pid','to_user_id']);
$data['user_id'] = $this->uid;
$sendId = $data['user_id'];
// halt($data);
$art = Db::name('article')->field('id,status,is_reply,delete_time')->find($data['article_id']);
if($art['delete_time'] != 0 || $art['status'] != 1 || $art['is_reply'] != 1){
@ -242,7 +230,7 @@ class Article extends BaseController
// 检验发帖是否开放
if(config('taoler.config.is_post') == 0 ) return json(['code'=>-1,'msg'=>'抱歉,系统维护中,暂时禁止发帖!']);
// 数据
$data = Request::only(['cate_id', 'title', 'title_color', 'content', 'upzip', 'keywords', 'description', 'captcha']);
$data = Request::only(['cate_id', 'title', 'title_color','read_type','art_pass', 'content', 'upzip', 'keywords', 'description', 'captcha']);
$data['user_id'] = $this->uid;
$tagId = input('tagid');
@ -268,13 +256,11 @@ class Article extends BaseController
$data['content'] = $this->downUrlPicsReaplace($data['content']);
// 把中文,转换为英文,并去空格->转为数组->去掉空数组->再转化为带,号的字符串
$data['keywords'] = implode(',',array_filter(explode(',',trim(str_replace('',',',$data['keywords'])))));
$data['description'] = strip_tags($this->filterEmoji($data['description']));
// 获取分类ename,appname
$cateName = Db::name('cate')->field('ename,appname')->find($data['cate_id']);
$article = new ArticleModel();
$result = $article->add($data);
$result = $this->model->add($data);
if ($result['code'] == 1) {
// 获取到的最新ID
$aid = $result['data']['id'];
@ -336,11 +322,10 @@ class Article extends BaseController
*/
public function edit($id)
{
$article = ArticleModel::find($id);
$article = $this->model->find($id);
if(Request::isAjax()){
$data = Request::only(['id','cate_id','title','title_color','user_id','content','upzip','keywords','description','captcha']);
$data['user_id'] = $this->uid;
$data = Request::only(['id','cate_id','title','title_color','read_type','art_pass','content','upzip','keywords','description','captcha']);
$tagId = input('tagid');
// 验证码
@ -364,8 +349,8 @@ class Article extends BaseController
$data['content'] = $this->downUrlPicsReaplace($data['content']);
// 把,转换为,并去空格->转为数组->去掉空数组->再转化为带,号的字符串
$data['keywords'] = implode(',',array_filter(explode(',',trim(str_replace('',',',$data['keywords'])))));
$data['description'] = strip_tags($this->filterEmoji($data['description']));
$result = $article->edit($data);
if($result == 1) {
//处理标签
@ -393,6 +378,8 @@ class Article extends BaseController
//删除原有缓存显示编辑后内容
Cache::delete('article_'.$id);
Session::delete('art_pass_'.$id);
$link = $this->getRouteUrl((int) $id, $article->cate->ename);
hook('SeoBaiduPush', ['link'=>$link]); // 推送给百度收录接口
@ -421,7 +408,7 @@ class Article extends BaseController
*/
public function delete()
{
$article = ArticleModel::find(input('id'));
$article = $this->model->find(input('id'));
$result = $article->together(['comments'])->delete();
if($result) {
return Msgres::success('delete_success');
@ -456,45 +443,11 @@ class Article extends BaseController
return download($zip,'my');
}
/**
* 获取描述过滤html
*
* @return void
*/
public function getDescription()
{
$data = Request::only(['content']);
$description = getArtContent($data['content']);
return json(['code'=>0,'data'=>$description]);
}
/**
* 标题调用百度关键词词条
*
* @return void
*/
public function getWordList()
{
$title = input('title');
return $this->getBdiduSearchWordList($title);
}
/**
* 关键词
* @return \think\response\Json
*/
public function keywords()
{
$data = Request::only(['flag','keywords','content']);
$keywords = $this->setKeywords($data);
return json(['code'=>0, 'msg' => 'ok', 'data'=> $keywords]);
}
// 文章置顶、加精、评论状态
public function jieset()
{
$data = Request::param();
$article = ArticleModel::field('id,is_top,is_hot,is_reply')->find($data['id']);
$article = $this->model->field('id,is_top,is_hot,is_reply')->find($data['id']);
switch ($data['field']){
case 'top':
if($data['rank']==1){
@ -534,7 +487,7 @@ class Article extends BaseController
public function titleColor()
{
$data = Request::param();
$result = ArticleModel::update($data);
$result = $this->model->update($data);
if($result){
//清除文章缓存
Cache::tag(['tagArt','tagArtDetail'])->clear();
@ -618,49 +571,39 @@ class Article extends BaseController
}
public function getCateTree()
{
//
$cate = Db::name('cate')->order(['id' => 'ASC','sort' => 'ASC'])->where(['delete_time'=>0])->select()->toArray();
$cateTree = array2tree($cate);
/**
* 分类树
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getCateTree()
{
$cateList = Cate::field('id,pid,catename,sort')->where(['status' => 1])->select()->toArray();
$list = getTree($cateList);
// 排序
$cmf_arr = array_column($list, 'sort');
array_multisort($cmf_arr, SORT_ASC, $list);
$count = count($list);
$tree = [];
if($count){
$tree = ['code'=>0, 'msg'=>'ok','count'=>$count];
$tree['data'] = $list;
}
$count = count($cateTree);
$tree = [];
if($cateTree){
$tree = ['code'=>0,'msg'=>'','count'=>$count];
$res = []; //auth_rule储存数据表中的表结构
foreach($cateTree as $k => $v){
//第一层子权限
$children = [];
if(isset($v['children'])){
foreach($v['children'] as $m => $j){
//第二层子权限
$chichi = [];
if(isset($j['children'])){
//第三层子权限
foreach($j as $s){
if(isset($s['children'])){
$chichi[] = ['id'=>$s['id'],'catename'=>$s['catename'],'pid'=>$s['pid']]; //子数据的子数据
}
}
}
//if($j['level'] < 3){}
$children[] = ['id'=>$j['id'],'catename'=>$j['catename'],'pid'=>$j['pid'],'children'=>$chichi]; //子数据
}
}
$data[] = ['id'=>$v['id'],'catename'=>$v['catename'],'pid'=>$v['pid'],'children'=>$children];
}
//构造一个顶级菜单pid=0的数组。把权限放入顶级菜单下子权限中
//$tree['data'][] = ['id'=>0,'catename'=>'顶级','pid'=>0,'children'=>$data];
$tree['data'] = $data;
}
return json($tree);
}
return json($tree);
}
public function jiemi()
{
$param = Request::param();
$article = $this->model->find($param['id']);
if($article['art_pass'] == $param['art_pass']) {
session('art_pass_'.$param['id'], $param['art_pass']);
return json(['code' => 0, 'msg' => '解密成功']);
}
return json(['code' => -1, 'msg' => '解密失败']);
}
}

View File

@ -10,10 +10,6 @@ use think\facade\Db;
class Collection extends BaseController
{
// protected $type = [
// 'cid' => 'integer',
// ];
//文章收藏
public function add(){
//$data = Request::param();

View File

@ -2,12 +2,15 @@
namespace app\index\controller;
use app\common\controller\BaseController;
use think\facade\View;
use think\facade\Request;
use think\facade\Session;
use think\facade\Cache;
use app\common\model\Comment as CommentModel;
use app\common\model\Article;
use app\common\model\UserZan;
class Comment extends BaseController
{
//采纳评论
@ -32,9 +35,8 @@ class Comment extends BaseController
//删除评论
public function jiedaDelete()
{
if(!session('?user_id')) return json(['code'=>-1,'msg'=>'未登录']);
$id = input('id');
//$arid = intval($id);
$comms = CommentModel::find($id);
$result = $comms->delete();
if($result){
@ -49,7 +51,7 @@ class Comment extends BaseController
public function getDa()
{
//获取原评论
$this->isLogin();
if(!session('?user_id')) return json(['code'=>-1,'msg'=>'未登录']);
$id = input('id');
$comms = CommentModel::find($id);
$res['rows'] = [];
@ -63,7 +65,7 @@ class Comment extends BaseController
//更新评论
public function updateDa()
{
$this->isLogin();
if(!session('?user_id')) return json(['code'=>-1,'msg'=>'未登录']);
$id = input('id');
$content = input('content');
$comms = CommentModel::find($id);
@ -76,11 +78,30 @@ class Comment extends BaseController
}
return json($res);
}
//更新评论
public function edit()
{
if(!session('?user_id')) return json(['code'=>-1,'msg'=>'未登录']);
if(Request::isAjax()) {
$param = Request::param();
// halt($param);
$result = CommentModel::update($param);
if($result) {
return json(['code' => 0, 'msg' => '编辑成功']);
}
return json(['code' => 0, 'msg' => '编辑失败']);
}
$comms = CommentModel::find(input('id'));
View::assign(['comment' => $comms, 'jspage' => '']);
return View::fetch();
}
//评论点赞
public function jiedaZan()
{
$this->isLogin();
if(!session('?user_id')) return json(['code'=>-1,'msg'=>'未登录']);
$data['comment_id'] = input('post.id');
$data['user_id'] = session('user_id');
//查询是否已存在点赞

View File

@ -16,10 +16,7 @@ use think\facade\View;
use think\facade\Request;
use think\facade\Db;
use app\facade\Article;
use app\common\model\Slider;
use app\common\lib\Msgres;
use yzh52521\EasyHttp\Http;
use QL\QueryList;
class Index extends BaseController
{
@ -33,39 +30,18 @@ class Index extends BaseController
public function index()
{
$types = input('type');
$slider = new Slider();
//幻灯
$sliders = Request::isMobile() ? $slider->getSliderList(12) : $slider->getSliderList(1);
//置顶文章
$artTop = Article::getArtTop(5);
//首页文章列表,显示20个
$artList = Article::getArtList(22);
//首页文章列表,显示10个
$artList = Article::getArtList(15);
//热议文章
$artHot = Article::getArtHot(10);
//首页广告
$indexAd = $slider->getSliderList(13);
//温馨通道
$fast_links = $slider->getSliderList(8);
//首页赞助
$ad_index = $slider->getSliderList(5);
//首页右栏图片
$ad_comm = $slider->getSliderList(2);
//友情链接申请
$adminEmail = Db::name('user')->where('id',1)->cache(true)->value('email');
$vs = [
'slider' => $sliders,
'artTop' => $artTop,
'artList' => $artList,
'artHot' => $artHot,
'ad_index_r'=> $indexAd,
'type' => $types,
'ad_index' => $ad_index,
'ad_comm' => $ad_comm,
'fastlinks' => $fast_links,
'adminEmail' => $adminEmail,
'jspage' => '',
];
View::assign($vs);

View File

@ -54,8 +54,24 @@ class Login extends BaseController
//邮箱正则表达式
$pattern = "/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,3}(\\.[a-z]{2})?)$/i";
//判断输入的是邮箱还是用户名
if (preg_match($pattern, $data['name'])){
if(preg_match("/^1[34578]\d{9}$/",$data['name']))
{
//手机验证登录
$data['phone'] = $data['name'];
unset($data['name']);
try{
validate(userValidate::class)
->scene('loginPhone')
->check($data);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
return json(['code'=>-1,'msg'=>$e->getError()]);
}
$data['name'] = $data['phone'];
unset($data['phone']);
} elseif (preg_match($pattern, $data['name'])){
//输入邮箱email登陆验证
$data['email'] = $data['name'];
unset($data['name']);
@ -89,7 +105,7 @@ class Login extends BaseController
return Msgres::error($res);
}
}
return View::fetch('login');
}

View File

@ -15,7 +15,6 @@ use app\common\controller\BaseController;
use think\facade\View;
use think\facade\Request;
use app\facade\Article;
use app\common\model\Slider;
class Search extends BaseController
{
@ -25,9 +24,6 @@ class Search extends BaseController
$ser = Request::only(['keywords']);
$artList = Article::getSearchKeyWord($ser['keywords']);
$counts = $artList->count();
$slider = new Slider();
//首页右栏
$ad_comm = $slider->getSliderList(2);
// 查询热议
$artHot = Article::getArtHot(10);
@ -35,7 +31,6 @@ class Search extends BaseController
'artList' => $artList,
'keywords' => $ser['keywords'],
'counts' => $counts,
'ad_comm'=>$ad_comm,
'artHot'=>$artHot,
'jspage'=>''
];

View File

@ -133,7 +133,7 @@ class User extends BaseController
$validate = new userValidate;
$result = $validate->scene('Set')->check($data);
if(!$result){
$this->error($validate->getError());
return json(['code'=>-1,'msg' =>$validate->getError()]);
} else {
//防止重复的email
$resEmail = Db::name('user')->where('email',$data['email'])->where('id','<>',$this->uid)->find();
@ -151,7 +151,7 @@ class User extends BaseController
Cache::tag('user')->clear();
return json(['code'=>0,'msg'=>'资料更新成功']);
} else {
$this->error($result);
return json(['code'=>-1,'msg' =>$result]);
}
}
}
@ -275,7 +275,8 @@ class User extends BaseController
$validate = new userValidate;
$res = $validate->scene('setPass')->check($data);
if(!$res){
return $this->error($validate->getError());
return json(['code'=>-1,'msg' =>$validate->getError()]);
}
$user = new userModel;
$result = $user->setpass($data);
@ -284,7 +285,7 @@ class User extends BaseController
Cookie::delete('auth');
return $this->success('密码修改成功 请登录', (string) url('login/index'));
} else {
return $this->error($result);
return json(['code'=>-1,'msg' =>$result]);
}
}
}
@ -298,9 +299,8 @@ class User extends BaseController
//Cookie::delete('user_id');
if(Session::has('user_id')){
return json(['code' => -1, 'msg' => '退出失败']);
} else {
return json(['code' => 200, 'msg' => '退出成功', 'url' => '/']);
}
return json(['code' => 200, 'msg' => '退出成功', 'url' => '/']);
}
}

View File

@ -30,7 +30,7 @@ return [
'index' => 'index',
'home page' => '首页',
'user center' => '用户中心',
'set info' => '设置',
'set info' => '个人设置',
'my message' => '我的消息',
'my page' => '我的主页',

View File

@ -1 +1,2 @@
myroute.php
myroute.php
a.php

View File

@ -9,6 +9,7 @@
* Copyright (c) 2020~2022 https://www.aieok.com All rights reserved.
*/
use think\facade\Route;
use think\facade\Request;
//详情页URL别称
$detail_as = config('taoler.url_rewrite.article_as');
@ -50,6 +51,9 @@ Route::group(function () {
->middleware(\app\middleware\CheckRegister::class);
});
// comment
Route::rule('comment/edit/[:id]','comment/edit');
// article
Route::group('art',function () use($detail_as,$cate_as){
Route::rule('add/[:cate]','Article/add')->name('add_article');
@ -65,19 +69,24 @@ Route::group('art',function () use($detail_as,$cate_as){
Route::get('tag','tag/getAllTag')->name('get_all_tag');
Route::get('arttag','tag/getArticleTag')->name('get_art_tag');
Route::rule('search/[:keywords]', 'index/search'); // 搜索
// article分类和详情路由 !放到最后!
Route::group(function () use($detail_as, $cate_as){
// 动态路径路由会影响下面的路由,所以动态路由放下面
Route::get($detail_as . ':id$', 'article/detail')->name('article_detail');
Route::get($detail_as . '<id>/<page>$', 'article/detail')->name('article_comment');
//分类
Route::get($cate_as . '<ename>$','article/cate')->name('cate');
Route::get($cate_as . '<ename>/<type>$', 'article/cate')->name('cate_type');
Route::get($cate_as . '<ename>/<type>/<page>$', 'article/cate')->name('cate_page');
})->pattern([
'ename' => '\w+',
'ename' => '[\w|\-]+',
'type' => '\w+',
'page' => '\d+',
'id' => '\d+',
]);
Route::rule('search/[:keywords]', 'index/search'); // 搜索

View File

@ -3,7 +3,6 @@ namespace app\install\controller;
use app\common\controller\BaseController;
use think\facade\View;
use think\facade\Db;
use think\facade\Request;
use think\facade\Session;
@ -12,135 +11,107 @@ class Index extends BaseController
// 检测是否安装过
protected function initialize(){
if(file_exists('./install.lock')){
echo "<script>alert('已经成功安装了TaoLer社区系统安装系统已锁定。如需重新安装请删除根目录下的install.lock文件')</script>";
die();
echo '<script src="/static/layui/layui.js"></script>'.
'<script>var layer = layui.layer; layer.alert("TaoLer系统已被锁定。<br>如需重新安装请删除public目录下的install.lock文件")</script>';
die();
}
}
//安装首页
// 安装首页
public function index()
{
Session::set('install',1);
return View::fetch('agreement');
return View::fetch('step');
}
//test
public function test()
{
if(Session::get('install') == 1){
Session::set('install',2);
return View::fetch('test');
} else {
return redirect('index.html');
}
}
//create
public function create(){
if(Session::get('install') == 2){
Session::set('install',3);
return View::fetch('create');
} else {
return redirect('test.html');
}
}
// 安装
public function install(){
//if(Session::get('install') != 3){
// return redirect('./create.html');
//}
public function install()
{
if(Request::isAjax()){
$data = Request::param();
//var_dump($data);
if (!preg_match("/^[a-zA-Z]{1}([0-9a-zA-Z]|[._]){4,19}$/", $data['admin_user'])) {
return json(['code'=>-1,'msg'=>"管理用户名至少包含5个字符需以字母开头"]);
}
if(Request::isAjax()){
$data = Request::param();
//var_dump($data);
if (!preg_match("/^[a-zA-Z]{1}([0-9a-zA-Z]|[._]){4,19}$/", $data['admin_user'])) {
return json(['code'=>-1,'msg'=>"管理用户名至少包含5个字符需以字母开头"]);
}
if (!preg_match("/^[\@A-Za-z0-9\!\#\$\%\^\&\*\.\~]{6,22}$/", $data['admin_pass'])) {
return json(['code'=>-1,'msg'=>'登录密码至少包含6个字符。可使用字母数字和符号']);
}
if ($data['admin_pass'] != $data['admin_pass2']) {
return json(['code'=>-1,'msg'=>'两次输入的密码不一致']);
//die("<script>alert('两次输入的密码不一致');history.go(-1)</script>");
}
if (!preg_match("/^[\@A-Za-z0-9\!\#\$\%\^\&\*\.\~]{6,22}$/", $data['admin_pass'])) {
return json(['code'=>-1,'msg'=>'登录密码至少包含6个字符。可使用字母数字和符号']);
}
if ($data['admin_pass'] != $data['admin_pass2']) {
return json(['code'=>-1,'msg'=>'两次输入的密码不一致']);
}
$email = $data['admin_email'];
$user = $data['admin_user'];
$create_time = time();
$salt = substr(md5($create_time),-6);
$pass = md5(substr_replace(md5($data['admin_pass']),$salt,0,6));
$webname = $data['webname'];
$webtitle = $data['webtitle'];
$web = Request::host();
//数据库配置
$dbhost = $data['DB_HOST'];
$dbuser = $data['DB_USER'];
$dbpass = $data['DB_PWD'];
$dbport = $data['DB_PORT'];
$dbname = $data['DB_NAME'];
$prefix = $data['DB_PREFIX'];
if ($data['DB_TYPE'] == 'mysql') {
//创建数据库
try {
$conn = new \PDO("mysql:host=$dbhost", $dbuser, $dbpass);
}
catch(\PDOException $e)
{
return json(['code'=>-1,'msg'=>"数据库信息错误" . $e->getMessage()]);
}
$sql = 'CREATE DATABASE IF NOT EXISTS '.$dbname.' DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci';
// 使用 exec() ,没有结果返回
$conn->exec($sql);
//echo $dbname."数据库创建成功<br>";
$conn = null;
//写入数据表
try {
$db = new \PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
}
catch(\PDOException $e)
{
return json(['code'=>-1,'msg'=>"数据库连接失败" . $e->getMessage()]);
}
//创建表
$res = create_tables($db,$prefix);
if(!$res){
return json(['code'=>-1,'msg'=>"数据表创建失败"]);
}
//写入初始配置
$table_admin = $data['DB_PREFIX'] . "admin";
$table_user = $data['DB_PREFIX'] . "user";
$table_system = $data['DB_PREFIX'] . "system";
$sql_a = "UPDATE $table_admin SET username='{$user}',email='{$email}',password='{$pass}',status=1,auth_group_id=1,create_time='{$create_time}' WHERE id = 1";
$sql_u = "UPDATE $table_user SET name='{$user}',email='{$email}',password='{$pass}',auth=1,status=1,create_time='{$create_time}' WHERE id = 1";
$sql_s = "UPDATE $table_system SET webname='{$webname}',webtitle='{$webtitle}',domain='{$web}',create_time='{$create_time}' WHERE id = 1";
$res_a = $db->exec($sql_a);
//var_dump($db->errorInfo());
if($res_a == 0){
return json(['code'=>-1,'msg'=>"管理员账号写入失败"]);
}
$res_u = $db->exec($sql_u);
if($res_u == 0){
return json(['code'=>-1,'msg'=>"前台管理员写入失败"]);
}
$res_s = $db->exec($sql_s);
if($res_s == 0){
return json(['code'=>-1,'msg'=>"网站配置写入失败"]);
}
$db = null;
$email = $data['admin_email'];
$user = $data['admin_user'];
$create_time = time();
$salt = substr(md5($create_time),-6);
$pass = md5(substr_replace(md5($data['admin_pass']),$salt,0,6));
$webname = $data['webname'];
$webtitle = $data['webtitle'];
$web = Request::host();
//数据库配置
$dbhost = $data['DB_HOST'];
$dbuser = $data['DB_USER'];
$dbpass = $data['DB_PWD'];
$dbport = $data['DB_PORT'];
$dbname = $data['DB_NAME'];
$prefix = $data['DB_PREFIX'];
if ($data['DB_TYPE'] == 'mysql') {
//创建数据库
try {
$conn = new \PDO("mysql:host=$dbhost", $dbuser, $dbpass);
}
catch(\PDOException $e)
{
return json(['code'=>-1,'msg'=>"数据库信息错误" . $e->getMessage()]);
}
$sql = 'CREATE DATABASE IF NOT EXISTS '.$dbname.' DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci';
// 使用 exec() ,没有结果返回
$conn->exec($sql);
//echo $dbname."数据库创建成功<br>";
$conn = null;
//写入数据表
try {
$db = new \PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
} catch(\PDOException $e) {
return json(['code'=>-1,'msg'=>"数据库连接失败" . $e->getMessage()]);
}
//创建表
$res = create_tables($db, $prefix);
if(!$res){
return json(['code'=>-1,'msg'=>"数据表创建失败"]);
}
//写入初始配置
$table_admin = $data['DB_PREFIX'] . "admin";
$table_user = $data['DB_PREFIX'] . "user";
$table_system = $data['DB_PREFIX'] . "system";
$sql_a = "UPDATE $table_admin SET username='{$user}',email='{$email}',password='{$pass}',status=1,auth_group_id=1,create_time='{$create_time}' WHERE id = 1";
$sql_u = "UPDATE $table_user SET name='{$user}',email='{$email}',password='{$pass}',auth=1,status=1,create_time='{$create_time}' WHERE id = 1";
$sql_s = "UPDATE $table_system SET webname='{$webname}',webtitle='{$webtitle}',domain='{$web}',create_time='{$create_time}' WHERE id = 1";
$res_a = $db->exec($sql_a);
//var_dump($db->errorInfo());
if($res_a == 0){
return json(['code'=>-1,'msg'=>"管理员账号写入失败"]);
}
$res_u = $db->exec($sql_u);
if($res_u == 0){
return json(['code'=>-1,'msg'=>"前台管理员写入失败"]);
}
$res_s = $db->exec($sql_s);
if($res_s == 0){
return json(['code'=>-1,'msg'=>"网站配置写入失败"]);
}
$db = null;
$db_str = <<<php
$db_str = <<<EOV
<?php
return [
// 默认使用的数据库连接配置
@ -171,7 +142,7 @@ return [
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
'charset' => 'utf8mb4',
// 数据库表前缀
'prefix' => env('database.prefix', '{$data['DB_PREFIX']}'),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
@ -196,32 +167,46 @@ return [
// 更多的数据库配置信息
],
];
php;
// 创建数据库链接配置文件
$database = '../config/database.php';
if (file_exists($database)) {
if(is_writable($database)){
$fp = fopen($database,"w");
$resf = fwrite($fp, $db_str);
fclose($fp);
if(!$resf){
$res = json(['code' => -1,'msg'=>'数据库配置文件创建失败!']);
}
} else {
$res = json(['code' => -1,'msg'=>'config/database.php 无写入权限']);
}
}
EOV;
// 创建数据库链接配置文件
$database = config_path() . 'database.php';
if (file_exists($database) && is_writable($database)) {
$fp = fopen($database,"w");
$resf = fwrite($fp, $db_str);
fclose($fp);
if(!$resf) return json(['code' => -1,'msg'=>'数据库配置文件创建失败!']);
} else {
return json(['code' => -1,'msg'=>'config/database.php 无写入权限']);
}
}
}
$env = <<<ENV
APP_DEBUG = false
//安装上锁
file_put_contents('./install.lock', 'lock');
Session::clear();
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
$res = json(['code' => 0,'msg'=>'安装成功','url'=>(string) url('success/complete')]);
} else {
$res = json(['code' => -1,'msg'=>'请求失败']);
}
return $res;
[DATABASE]
TYPE = mysql
HOSTNAME = {$data['DB_HOST']}
DATABASE = {$data['DB_NAME']}
USERNAME = {$data['DB_USER']}
PASSWORD = {$data['DB_PWD']}
HOSTPORT = {$data['DB_PORT']}
CHARSET = utf8mb4
DEBUG = false
[LANG]
default_lang = zh-cn
ENV;
file_put_contents(root_path() . '.env', $env);
//安装上锁
file_put_contents('./install.lock', 'lock');
Session::clear();
return json(['code' => 0,'msg'=>'安装成功','url'=>(string) url('success/complete')]);
}
return json(['code' => -1,'msg'=>'请求失败']);
}
}

View File

@ -5,7 +5,7 @@
Target Server Version : 80020 (8.0.20)
File Encoding : 65001
Date: 14/03/2023 19:57:43
Date: 8/06/2023 19:57:43
*/
SET NAMES utf8mb4;
@ -48,7 +48,7 @@ DROP TABLE IF EXISTS `tao_article`;
CREATE TABLE `tao_article` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`title` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '标题',
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '内容',
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '内容',
`status` enum('0','-1','1') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '1' COMMENT '状态1显示0待审-1禁止',
`cate_id` int NOT NULL COMMENT '分类id',
`user_id` int NOT NULL COMMENT '用户id',
@ -266,6 +266,11 @@ INSERT INTO `tao_auth_rule` VALUES (120, 'content.cate/edit', '编辑分类', 1,
INSERT INTO `tao_auth_rule` VALUES (121, 'content.cate/delete', '删除分类', 1, 1, 117, 2, '', 2, 50, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (122, 'content.cate/hot', '热点分类', 1, 1, 117, 2, '', 2, 50, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (123, 'content.cate/getAppNameView', '分类应用模板', 1, 1, 117, 2, '', 2, 50, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (124, 'content.tag/index', '标签管理', 1, 1, 4, 1, '', 1, 50, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (125, 'content.tag/list', '标签列表', 1, 1, 124, 2, '', 2, 50, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (126, 'content.tag/add', '添加标签', 1, 1, 124, 2, '', 2, 50, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (127, 'content.tag/edit', '编辑标签', 1, 1, 124, 2, '', 2, 50, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (128, 'content.tag/delete', '删除标签', 1, 1, 124, 2, '', 2, 50, '', 0, 0, 0);
-- ----------------------------
-- Table structure for tao_cate
@ -313,36 +318,29 @@ CREATE TABLE `tao_collection` (
PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '文章收藏表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tao_collection
-- ----------------------------
-- ----------------------------
-- Table structure for tao_comment
-- ----------------------------
DROP TABLE IF EXISTS `tao_comment`;
CREATE TABLE `tao_comment` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '评论id',
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '评论',
`article_id` int NOT NULL COMMENT '文章id',
`user_id` int NOT NULL COMMENT '评论用户',
`zan` tinyint NOT NULL DEFAULT 0 COMMENT '',
`cai` enum('1','0') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '0求解1采纳',
`status` enum('0','-1','1') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '1通过0待审-1禁止',
`create_time` int NOT NULL DEFAULT 0 COMMENT '创建时间',
`update_time` int NOT NULL DEFAULT 0 COMMENT '更新时间',
`delete_time` int NOT NULL DEFAULT 0 COMMENT '删除时间',
`id` int NOT NULL AUTO_INCREMENT COMMENT '评论id',
`pid` int NOT NULL DEFAULT 0 COMMENT '父id',
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '评论',
`article_id` int NOT NULL COMMENT '文章id',
`user_id` int NOT NULL COMMENT '评论用户',
`to_user_id` int NULL DEFAULT NULL COMMENT '给用户留言',
`zan` tinyint NOT NULL DEFAULT 0 COMMENT '',
`cai` enum('1','0') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0' COMMENT '0求解1采纳',
`status` enum('0','-1','1') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1' COMMENT '1通过0待审-1禁止',
`type` tinyint(1) NOT NULL DEFAULT 1 COMMENT '评论类型1帖子2其它',
`create_time` int NOT NULL DEFAULT 0 COMMENT '创建时间',
`update_time` int NOT NULL DEFAULT 0 COMMENT '更新时间',
`delete_time` int NOT NULL DEFAULT 0 COMMENT '删除时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `aiticle_id`(`article_id` ASC) USING BTREE COMMENT '文章评论索引',
INDEX `user_id`(`user_id` ASC) USING BTREE COMMENT '评论用户索引'
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '评论表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tao_comment
-- ----------------------------
INSERT INTO `tao_comment` VALUES (1, 'https://www.aieok.com', 1, 1, 0, '0', '1', 1555127897, 1578977505, 0);
INSERT INTO `tao_comment` VALUES (2, 'face[嘻嘻] ddddd', 1, 1, 0, '0', '1', 1677900207, 1677975943, 1677975943);
INSERT INTO `tao_comment` VALUES (3, 'ddddfdfd', 1, 1, 0, '0', '1', 1677900215, 1677975943, 1677975943);
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '评论表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for tao_cunsult
@ -359,10 +357,6 @@ CREATE TABLE `tao_cunsult` (
PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '反馈表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tao_cunsult
-- ----------------------------
-- ----------------------------
-- Table structure for tao_friend_link
-- ----------------------------
@ -376,14 +370,12 @@ CREATE TABLE `tao_friend_link` (
`update_time` int NOT NULL COMMENT '更新时间',
`delete_time` int NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '友情链接' ROW_FORMAT = Dynamic;
) ENGINE = MyISAM AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '友情链接' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tao_friend_link
-- ----------------------------
INSERT INTO `tao_friend_link` VALUES (1, 'taobao', 'https://www.taobao.com', '', 0, 0, 0);
INSERT INTO `tao_friend_link` VALUES (2, 'baidu', 'https://www.baidu.com', '', 0, 0, 0);
INSERT INTO `tao_friend_link` VALUES (3, 'tensent', 'https://www.qq.com', '', 0, 0, 0);
INSERT INTO `tao_friend_link` VALUES (1, 'taoler', 'https://www.aieok.com', '', 0, 0, 0);
-- ----------------------------
-- Table structure for tao_mail_server
@ -421,13 +413,7 @@ CREATE TABLE `tao_message` (
`update_time` int NOT NULL DEFAULT 0 COMMENT '更新时间',
`delete_time` int NOT NULL DEFAULT 0 COMMENT '删除时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '消息表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tao_message
-- ----------------------------
INSERT INTO `tao_message` VALUES (1, '测试后台帖子', '评论通知', 1, 'http://www.tp6.com/index/ask/1.html', 2, 1677900207, 1677900207, 0);
INSERT INTO `tao_message` VALUES (2, '测试后台帖子', '评论通知', 1, 'http://www.tp6.com/index/ask/1.html', 2, 1677900215, 1677900215, 0);
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '消息表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for tao_message_to
@ -444,13 +430,7 @@ CREATE TABLE `tao_message_to` (
`update_time` int NOT NULL DEFAULT 0 COMMENT '更新时间',
`delete_time` int NOT NULL DEFAULT 0 COMMENT '删除时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '消息详细表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tao_message_to
-- ----------------------------
INSERT INTO `tao_message_to` VALUES (1, 1, 1, '1', 2, 0, 1677900207, 1677900207, 0);
INSERT INTO `tao_message_to` VALUES (2, 1, 1, '2', 2, 0, 1677900215, 1677900215, 0);
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '消息详细表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for tao_push_jscode
@ -467,10 +447,6 @@ CREATE TABLE `tao_push_jscode` (
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '站长平台自动推送js代码' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tao_push_jscode
-- ----------------------------
-- ----------------------------
-- Table structure for tao_slider
-- ----------------------------
@ -489,13 +465,7 @@ CREATE TABLE `tao_slider` (
`update_time` int NOT NULL DEFAULT 0 COMMENT '更新时间',
`delete_time` int NOT NULL DEFAULT 0 COMMENT '删除时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tao_slider
-- ----------------------------
INSERT INTO `tao_slider` VALUES (1, 'CODING', 1, '/storage/slider/F1.jpg', '#', '', 1574870400, 1575043200, '1', 0, 0, 0);
INSERT INTO `tao_slider` VALUES (2, '通用右栏底部广告', 2, '/storage/slider/20200101/851c0b88a72590293bcb45454bdce056.jpg', 'https://www.aieok.com', '', 1571155200, 1609344000, '1', 0, 0, 0);
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for tao_system
@ -556,10 +526,6 @@ CREATE TABLE `tao_tag` (
INDEX `ename`(`ename` ASC) USING BTREE COMMENT 'ename查询tag索引'
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '文章tag表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tao_tag
-- ----------------------------
-- ----------------------------
-- Table structure for tao_taglist
-- ----------------------------
@ -655,10 +621,6 @@ CREATE TABLE `tao_user_sign` (
PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户签到表' ROW_FORMAT = Fixed;
-- ----------------------------
-- Records of tao_user_sign
-- ----------------------------
-- ----------------------------
-- Table structure for tao_user_signrule
-- ----------------------------
@ -714,15 +676,11 @@ DROP TABLE IF EXISTS `tao_user_zan`;
CREATE TABLE `tao_user_zan` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '点赞主键id',
`article_id` int NULL DEFAULT NULL COMMENT '文章id',
`comment_id` int NOT NULL COMMENT '评论id',
`comment_id` int NULL DEFAULT NULL COMMENT '评论id',
`user_id` int NOT NULL COMMENT '用户id',
`type` tinyint NOT NULL DEFAULT 2 COMMENT '1文章点赞2评论点赞',
`create_time` int NOT NULL DEFAULT 0 COMMENT '点赞时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Fixed;
-- ----------------------------
-- Records of tao_user_zan
-- ----------------------------
SET FOREIGN_KEY_CHECKS = 1;

View File

@ -0,0 +1,474 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>引导安装</title>
<link rel="stylesheet" href="/static/component/pear/css/pear.css" />
<link rel="stylesheet" href="/static/admin/css/install.css">
</head>
<body class="pear-container">
<div class="layui-row layui-col-space10">
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card">
<div class="layui-card-body" style="padding-top: 40px;">
<div class="layui-carousel" id="stepForm" lay-filter="stepForm" style="margin: 0 auto;">
<div carousel-item>
<div>
<form class="layui-form" action="javascript:void(0);" style="margin: 0 auto;max-width: 750px;padding-top: 20px;">
<div class="inside2">
<div class="inwp cl">
<h2>TaoLerCMS - 建站系统以下简称TaoLer安装协议</h2>
<hr>
<p>1、欢迎使用TaoLer系统她是一款轻量化、快速、便捷、简单的综合社区内容管理系统。</p>
<p>2、适用于学校、企业、社团组织、社区、政府、本地华商圈等综合型服务类型</p>
<p>3、本系统在作者能力范围内做到安全可靠代码严禁并力争进行长期更新支持、及时修复BUG减少使用者的使用成本。</p>
<p>4、尽管程序在发布前已经过安全测试但仍不能完全保证漏洞的存在和丢失数据的风险作者不承担商业风险。</p>
<p>5、本程序版权归开发者所有在未经过作者同意的情况下严禁转售、赠送他人。</p>
<p>6、您可以在完全遵守本许可协议的基础上免费下载安装使用商业应用请联系作者授权。</p>
<p>7、无论您是个人或组织、盈利与否、用途如何包括以学习和研究为目的均需仔细阅读本协议包括免除或者限制开发团队责任的免责条款及对您的权利限制。请您审阅并接受或不接受本服务条款。如您不同意本服务条款及/或随时对其的修改,您应不使用或主动取消产品。否则,您的任何对产品中的相关服务的注册、登陆、下载、查看等使用行为将被视为您对本服务条款全部的完全接受,包括接受对服务条款随时所做的任何修改。</p>
<p>8、本协议一旦发生变更, TaoLer开发团队将在网页上公布修改内容。修改后的服务条款一旦在网站管理后台上公布即有效代替原来的服务条款。如果您选择接受本条款即表示您同意接受协议各项条件的约束。如果您不同意本服务条款则不能获得使用本服务的权利。您若有违反本条款规定TaoLer有权随时中止或终止您对本程序的使用资格并保留追究相关法律责任的权利。</p>
<p>9、在理解、同意、并遵守本协议的全部条款后方可开始使用本程序。本许可协议条款的解释效力及纠纷的解决适用于中华人民共和国大陆法律。</p>
<p>10、您使用本系统需要遵循许可协议一旦安装表示您已接受该系统各项条款。</p>
</div>
</br>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<input type="checkbox" name="agrement" title="同意" checked>
<button class="pear-btn pear-btn-success" lay-submit lay-filter="formStep">
&emsp;下一步&emsp;
</button>
</div>
</div>
</form>
</div>
<div>
<form class="layui-form" action="javascript:void(0);" style="margin: 0 auto;max-width: 600px;padding-top: 20px;">
<div class="layui-form-item inside2">
<div class="inwp cl">
<h2>环境检测:</h2>
<table style="width:600px;">
<tr>
<th style="width:25%;">坏境</th>
<th style="width:25%;">最低配置</th>
<th style="width:25%;">当前配置</th>
<th style="width:25%;">是否符合</th>
</tr>
<tr>
<td>操作系统</td>
<td>不限</td>
<td>
<?php echo php_uname('s'); ?>
</td>
<td class="yes"></td>
</tr>
<tr>
<td>php版本</td>
<td>&gt;7.4.0</td>
<td>
<?php echo PHP_VERSION ?>
</td>
<td>
<?php if (version_compare(PHP_VERSION, '7.4.0', '>=')): ?>
<span class="yes"></span>
<?php else: ?>
×
<?php endif ?>
</td>
</tr>
</table>
<h2>扩展检测:</h2>
<table style="width:600px;">
<tr>
<th width="25%">坏境</th>
<th width="25%">最低配置</th>
<th width="25%">当前配置</th>
<th width="25%">是否符合</th>
</tr>
<tr>
<td>数据库</td>
<td>Mysqli</td>
<td><?php
$pdo = false;
if(class_exists('PDO', false))
{
if(defined('PDO::MYSQL_ATTR_USE_BUFFERED_QUERY'))
{
echo 'PDO_MYSQL';
$pdo = true;
}
else
{
echo '不支持PDO_MYSQL';
}
}
else
{
echo '不支持PDO_MYSQL';
}
if(!$pdo)
{
if (function_exists('mysqli_close'))
{
echo 'MySQLi';
$pdo = true;
}
}
?>
</td>
<td>
<?php if ($pdo): ?>
<span class="yes"></span>
<?php else: ?>
×
<?php endif; ?>
</td>
</tr>
<tr>
<td>PDO</td>
<td>支持</td>
<td>
<?php if(extension_loaded('pdo')): ?>
Yes
<?php else: ?>
No
<?php endif; ?>
</td>
<td>
<?php if(extension_loaded('pdo')): ?>
<span class="yes"></span>
<?php else: ?>
×
<?php endif; ?>
</td>
</tr>
<tr>
<td>fileinfo</td>
<td>支持</td>
<td>
<?php if(get_extension_funcs('fileinfo')): ?>
Yes
<?php else: ?>
No
<?php endif; ?>
</td>
<td>
<?php if(get_extension_funcs('fileinfo')): ?>
<span class="yes"></span>
<?php else: ?>
×
<?php endif; ?>
</td>
</tr>
</table>
<h2>目录权限:</h2>
<table style="width:600px;">
<tr>
<th width="25%">坏境</th>
<th width="25%">最低配置</th>
<th width="25%">当前配置</th>
<th width="25%">是否符合</th>
</tr>
<tr>
<td>app</td>
<td>可写</td>
<td>
<?php if (is_writable('../app')): ?> 可写
<?php else: ?> 不可写
<?php endif ?>
</td>
<td>
<?php if (is_writable('../app')): ?>
<span class="yes"></span>
<?php else: ?>
×
<?php endif ?>
</td>
</tr>
<tr>
<td>config</td>
<td>可写</td>
<td>
<?php if (is_writable('../config')): ?> 可写
<?php else: ?> 不可写
<?php endif ?>
</td>
<td>
<?php if (is_writable('../config')): ?>
<span class="yes"></span>
<?php else: ?> ×
<?php endif ?>
</td>
</tr>
<tr>
<td>public</td>
<td>可写</td>
<td>
<?php if (is_writable('../public')): ?> 可写
<?php else: ?> 不可写
<?php endif ?>
</td>
<td>
<?php if (is_writable('../public')): ?>
<span class="yes"></span>
<?php else: ?>
×
<?php endif ?>
</td>
</tr>
<tr>
<td>runtime</td>
<td>可写</td>
<td>
<?php if (is_writable('../runtime')): ?> 可写
<?php else: ?> 不可写
<?php endif ?>
</td>
<td>
<?php if (is_writable('../runtime')): ?>
<span class="yes"></span>
<?php else: ?>
×
<?php endif ?>
</td>
</tr>
<tr>
<td>view</td>
<td>可写</td>
<td>
<?php if (is_writable('../view')): ?> 可写
<?php else: ?> 不可写
<?php endif ?>
</td>
<td>
<?php if (is_writable('../view')): ?>
<span class="yes"></span>
<?php else: ?>
×
<?php endif ?>
</td>
</tr>
</table>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" class="pear-btn pear-btn-success pre">上一步</button>
<button class="pear-btn pear-btn-success" lay-submit lay-filter="formStep2">
&emsp;下一步&emsp;
</button>
</div>
</div>
</form>
</div>
<div class="inside2">
<div class="inwp cl">
<form class="layui-form" action="javascript:void(0);" style="margin: 0 auto;max-width: 600px;padding-top: 20px;" >
<h2>创建数据库:</h2>
<input type="hidden" name="DB_TYPE" value="mysql">
<div class="layui-form-item">
<label class="layui-form-label">数据库地址</label>
<div class="layui-input-block">
<input type="text" name="DB_HOST" value="127.0.0.1" required lay-verify="required" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">数据库账号</label>
<div class="layui-input-block">
<input type="text" name="DB_USER" value="root" required lay-verify="required" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">数据库密码</label>
<div class="layui-input-block">
<input type="text" name="DB_PWD" required lay-verify="required" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">数据库端口</label>
<div class="layui-input-block">
<input type="text" name="DB_PORT" value="3306" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">数据库名</label>
<div class="layui-input-block">
<input type="text" type="text" name="DB_NAME" required lay-verify="required" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">设置表前缀</label>
<div class="layui-input-block">
<input type="text" name="DB_PREFIX" value="tao_" required lay-verify="required" autocomplete="off" class="layui-input">
</div>
</div>
<h2>网站信息:</h2>
<div class="layui-form-item">
<label class="layui-form-label">网站名称</label>
<div class="layui-input-block">
<input type="text" name="webname" placeholder="请输入网站名称" required lay-verify="required" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">副标题</label>
<div class="layui-input-block">
<input type="text" name="webtitle" placeholder="请输入网站副标题" required lay-verify="required" autocomplete="off" class="layui-input">
</div>
</div>
<h2>管理员账号:</h2>
<div class="layui-form-item">
<label class="layui-form-label">用户名</label>
<div class="layui-input-block">
<input type="text" name="admin_user" placeholder="至少5字符" required lay-verify="required" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">邮箱</label>
<div class="layui-input-block">
<input type="text" name="admin_email" placeholder="请输入正确邮箱" required lay-verify="email" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">登录密码</label>
<div class="layui-input-block">
<input type="password" name="admin_pass" placeholder="至少包含6个字符。可使用字母数字和符号" required lay-verify="required" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密码确认</label>
<div class="layui-input-block">
<input type="password" name="admin_pass2" required lay-verify="required" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" class="pear-btn pear-btn-success pre">上一步</button>
<button class="pear-btn pear-btn-success" lay-submit lay-filter="formStep3">
&emsp;下一步&emsp;
</button>
</div>
</div>
</form>
</div>
</div>
<div>
<div style="text-align: center;margin-top: 90px;">
<i class="layui-icon layui-circle" style="color: white;font-size:30px;font-weight:bold;background: #52C41A;padding: 20px;line-height: 80px;">&#xe605;</i>
<div style="font-size: 24px;color: #333;font-weight: 500;margin-top: 30px;">
安装成功
</div>
<div style="font-size: 14px;color: #666;margin-top: 20px;">恭喜您心愿达成,祝马到成功!</div>
</div>
<div style="text-align: center;margin-top: 50px;">
<a href="/" class="pear-btn pear-btn-success next" target="_blank">去前端查看</a>
<a href="/admin" class="pear-btn pear-btn-success" target="_blank">去管理后台</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="/static/component/layui/layui.js"></script>
<script src="/static/component/pear/pear.js"></script>
<script>
layui.use(['form', 'step','code','element','toast'], function() {
var $ = layui.$,
form = layui.form,
step = layui.step;
let toast = layui.toast;
layui.code();
step.render({
elem: '#stepForm',
filter: 'stepForm',
width: '100%',
stepWidth: '750px',
height: '950px',
stepItems: [{
title: '协议'
}, {
title: '检测'
}, {
title: '安装'
}, {
title: '成功'
}
]
});
//协议
form.on('submit(formStep)', function(data) {
if(data.field.agrement == 'on') {
// 同意协议进行下一步
step.next('#stepForm');
} else {
toast.error({title:"错误消息",message:"您未同意协议,将要退出安装!"});
// 不同意关闭安装页码
// var userAgent = navigator.userAgent;
// if (userAgent.indexOf("Firefox") != -1 || userAgent.indexOf("Chrome") != -1) {
// location.href = "about:blank";
// } else {
// window.opener = null;
// window.open('', '_self');
// }
// window.close();
}
return false;
});
// 配置检测
form.on('submit(formStep2)', function(data) {
if ($('.yes').length < 10) {
toast.error({title:"错误消息",message:"您的配置或权限不符合要求,请检查"});
} else {
step.next('#stepForm');
}
return false;
});
// 数据库信息
form.on('submit(formStep3)', function(data) {
$.post("{:url('index/install')}", data.field, function(res){
if(res.code === 0) {
// 安装成功
step.next('#stepForm');
} else {
toast.error({title:"错误消息",message: res.msg});
}
})
return false;
});
// 上一步
$('.pre').click(function() {
step.pre('#stepForm');
return false;
});
// $('.next').click(function() {
// step.next('#stepForm');
// return false;
// });
})
</script>
</body>
</html>

View File

@ -25,16 +25,18 @@ class UserLogin
*/
public function handle($user)
{
$type = $user->user['type'];
$id = $user->user['id'];
$u = User::find($id);
//日志
if($type == 'log'){
//$name = $user->user['name'];
$ip = request()->ip();
$url = 'http://ip-api.com/json/' . $ip . '?lang=zh-CN&fields=57361';
$city = 'earth';
$type = $user->user['type'];
$id = $user->user['id'];
$u = User::find($id);
$ip = request()->ip();
$url = 'http://ip-api.com/json/' . $ip . '?lang=zh-CN&fields=57361';
$city = 'earth';
//日志
if($type == 'log'){
//$name = $user->user['name'];
try{
$ipInfo = HttpHelper::get($url)->toJson();
if($ipInfo->status == 'success')
@ -61,21 +63,22 @@ class UserLogin
// $city = $arr[2];
// }
// }
$u->allowField(['city','last_login_ip','last_login_time','login_error_num'])->save(
[
'city' => $city,
'last_login_ip' => $ip,
'last_login_time' => time(),
'login_error_num' => 0
]
);
Log::channel('login')->info('login:{user} {ip}',['user'=>$u->name,'ip'=>$ip]);
}
if($type == 'logError'){
$res = $u->allowField(['login_error_num','login_error_time'])->save(['login_error_num'=>$u->login_error_num + 1,'login_error_time'=>time()]);
}
}
if($type == 'logError'){
$u->allowField(['login_error_num','login_error_time'])->save(['login_error_num'=>$u->login_error_num + 1,'login_error_time'=>time()]);
}
$u->allowField(['city','last_login_ip','last_login_time','login_error_num'])->save(
[
'city' => $city,
'last_login_ip' => $ip,
'last_login_time' => time(),
'login_error_num' => 0
]
);
Log::channel('login')->info('login:{user} {ip}',['user'=>$u->name,'ip'=>$ip]);
}
}

View File

@ -1,6 +1,6 @@
{
"name": "taoser/taoler",
"description": "the new thinkphp taoler bbs system",
"description": "the new thinkphp taolerCMS system",
"type": "project",
"keywords": [
"taoler",
@ -24,7 +24,6 @@
"topthink/think-view": "^1.0",
"topthink/think-captcha": "^3.0",
"phpmailer/phpmailer": "^6.1",
"firebase/php-jwt": "^5.2",
"lotofbadcode/phpspirit_databackup": "^1.1",
"wamkj/thinkphp6.0-databackup": "^1.0",
"taoser/think-addons": "^1.0",

727
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@ return [
// 应用名,此项不可更改
'appname' => 'TaoLer',
// 版本配置
'version' => '2.2.7',
'version' => '2.3.9',
// 加盐
'salt' => 'taoler',
// 数据库备份目录

View File

@ -14,6 +14,7 @@ use think\Response;
class Api
{
public $code;
/**
* @param $url
* @param $data

View File

@ -28,9 +28,10 @@ class Files
$arr = array();
$data = scandir($path);
foreach ($data as $value){
if($value !='.' && $value != '..' && !stripos($value,".") && $value != '.gitignore'){
$arr[] = strtolower($value);
}
if (in_array($value, ['.', '..','.gitignore'])) continue;
if(!stripos($value,".")) {
$arr[] = strtolower($value);
}
}
//return array_merge(array_diff($arr, array('install')));
return $arr;

View File

@ -282,7 +282,7 @@ class FormHlp
$switchStr = $switchArr ? lang($switchArr[1]) . '|' . lang($switchArr[0]) : lang('open') . '|' . 'close';
$str = '<div class="layui-form-item">' .$this->label($label,$options) . '
<div class="layui-input-block">
<input ' . $this->addextend($options) . ' ' . $this->addstyle($options) . ' class="' . $this->addClass($options) . '" type="checkbox" value="' . $value . '" checked="" name="' . $name . '" ' . $this->verify($options) . $this->filter($options) . $this->readonlyOrdisabled($options) . ' lay-skin="switch" lay-text="' . $switchStr . '" data-text="' . lang($value) . '"/>
<input ' . $this->addextend($options) . ' ' . $this->addstyle($options) . ' class="' . $this->addClass($options) . '" type="checkbox" value="' . $value . '" checked="'.$checked.'" name="' . $name . '" ' . $this->verify($options) . $this->filter($options) . $this->readonlyOrdisabled($options) . ' lay-skin="switch" lay-text="' . $switchStr . '" data-text="' . lang($value) . '"/>
' . $this->tips($options) . '
</div>
</div>';

View File

@ -32,9 +32,9 @@ if (!function_exists('form_switch')) {
* @param $value
* @return string
*/
function form_switch($name,$switch=[] , $option=[],$value='')
function form_switch($name, $switch=[], $option=[], $value='')
{
return FormHelper::switchs($name,$switch , $option,$value);
return FormHelper::switchs($name, $switch, $option, $value);
}
}
if (!function_exists('form_checkbox')) {

View File

@ -0,0 +1,34 @@
body{background:#fff}
.cl{zoom:1}
.cl:after{content:'\20';display:block;height:0;clear:both;visibility:hidden}
.z{float:left}
.y{float:right}
.logo {height:37px;padding:10px 0 0 10px;}
.header{background:#009688;height:60px;width:100%;position:fixed;left:0;top:0;z-index:999}
.header a{font-size:18px;padding:0 30px 0 0;line-height:60px;font-weight:100;color:#fff}
.header h2{font-size:18px;padding:0 0 0 30px;line-height:60px;font-weight:100;color:#fff}
.header a:hover{color:#fff}
.inside{width:100%;min-width:1000px;height:65px;background:#393D49}
.inside h2 img{float:left;padding:0}
.inside ul{width:120px;height:65px;float:left;margin-left:68px}
.inside .innumber1{background:#FF5722!important;color:#fff!important}
.inside .innumber{margin-top:12px;width:40px;height:40px;line-height:40px;text-align:center;font-size:20px;border-radius:50%;background:#fff;float:left;color:#009688}
.inside .inword{width:80px;height:65px;float:left;line-height:65px;text-indent:10px;font-size:16px;color:#fff}
.inwp{width:100%;margin:0 auto}
.inout1 a{float:left;border:1px solid #C9C9C9;background-color:#fff;color:#555;padding:8px 18px;border-radius:2px;margin-right:10px;margin-top:20px}
.inout2 a{float:left;color:#fff;padding:9px 18px;background:#009688;border-radius:2px;margin-top:20px}
.inout1 a:hover{color:#555;opacity:.8;filter:alpha(opacity=80)}
.inout2 a:hover{color:#fff;opacity:.8;filter:alpha(opacity=80)}
.inout2 input{float:left;color:#fff;padding:9px 18px;background:#009688;border-radius:2px;margin-top:20px;border:none}
.inout2 input:hover{color:#fff;opacity:.8;filter:alpha(opacity=80)}
.inside2 h2{font-size:20px;margin:20px 0}
.inside2 h3{font-size:16px;margin:20px 0 10px 0;color:#FF5722}
.inside2 p{font-size:14px;line-height:28px;margin-bottom:10px}
.inside2 tr{border:1px solid #EAEAEA}
.inside2 tr th{border-left:1px solid #EAEAEA;background:#F9F9F9;line-height:45px}
.inside2 tr td{border-left:1px solid #EAEAEA;line-height:40px;padding-left:20px}

File diff suppressed because one or more lines are too long

View File

@ -14,14 +14,36 @@
/>
<missing-glyph />
<glyph glyph-name="edge" unicode="&#59019;" d="M240.185509 821.062741C322.180562 871.479699 415.37494 897.48813 509.969233 895.934224 845.948962 895.934224 1023.938224 648.353161 1023.938224 456.964708c-0.199988-65.396055-25.998431-127.79229-71.795669-174.389479-45.797237-46.397201-107.993485-72.995596-173.389539-73.995536-150.390927 0-182.98896 46.197213-182.98896 63.996139 0 7.599542 2.399855 12.399252 9.599421 18.798866l1.99988 2.399855 0.799951 3.199807c20.998733 22.998612 31.798082 52.396839 31.798082 83.194981 0 157.390504-164.390082 285.382782-367.977799 285.382782-75.075471 0.599964-149.071006-17.798926-215.027027-53.796754 53.996742 115.03306 165.430019 195.188224 182.628981 207.627473 1.599903 1.099934 0.599964 1.679899 0.599964 1.679899z m31.198118-636.081624c-2.799831-59.99638 9.199445-119.992761 32.798021-174.389479 27.198359-52.796815 65.396055-101.993847 112.993183-138.591638-118.992821 22.998612-222.966548 87.794703-298.781974 178.589225C42.237452 143.383627 0 259.176641 0 380.169341c0 102.393822 124.792471 188.78861 271.983591 188.78861 73.195584 1.199928 144.791264-21.798685 203.587717-65.396054l-7.199566-2.399856c-102.993786-35.197876-196.988115-181.389056-196.988115-316.180924zM939.543315 95.986486l-1.399915-0.199987c-23.598576-37.597732-51.796875-70.195765-84.394908-98.994028-61.596284-55.996622-136.191783-90.99451-217.586873-99.793979-37.197756-0.599964-73.59556 6.399614-107.593509 22.798624-51.196911 20.598757-94.194317 59.99638-123.192567 105.993605-28.798263 47.797116-42.197454 103.393762-37.997708 159.190396-1.199928 40.197575 10.799348 80.595138 29.99819 116.392978 27.798323-66.196006 74.995475-122.592604 135.191844-161.590251 60.196368-38.997647 130.992097-58.996441 202.787766-57.196549 61.99626-0.599964 124.192507 13.399192 180.389116 40.997526l3.799771 1.799892c7.799529 4.599722 15.399071 7.799529 23.1986 0 8.999457-9.799409 3.599783-18.39889-2.399855-27.998311-0.399976-0.399976-0.599964-0.99994-0.799952-1.399916z" horiz-adv-x="1024" />
<glyph glyph-name="leaf" unicode="&#59137;" d="M1017.948269 886.876437c-4.863707 5.785251-12.031275 9.113051-19.557222 9.113051l-26.110427 0c-258.032454 0.102394-461.847374 0.153591-611.905533-35.735447-80.635142-19.301237-142.992985-48.432282-190.606116-89.031436-51.401703-43.82456-86.420393-101.216302-107.155144-175.554223-13.77197-49.353826-20.222782-138.487656 6.96278-227.160714 10.034595-32.766026 25.700852-63.688963 46.589193-92.103251-62.255449-97.530124-116.063407-225.983185-116.063407-378.805977 0-14.130349 11.468109-25.598458 25.598458-25.598458s25.598458 11.468109 25.598458 25.598458c0 235.761795 139.665185 410.650458 222.91137 493.845446 59.7468 59.7468 127.275532 110.175762 195.367429 145.808815 63.381781 33.175601 123.947732 51.4529 170.536925 51.4529 14.130349 0 25.598458 11.468109 25.598458 25.598458s-11.468109 25.598458-25.598458 25.598458c-55.497456 0-122.667809-19.813206-194.241097-57.340545-72.597226-38.039308-144.477695-91.591282-207.80828-154.973063-26.72479-26.72479-58.876453-62.357843-90.823328-105.977615-12.389654 19.506025-22.014674 40.189579-28.619076 61.794677-25.598458 83.553366-16.178225 164.034917-6.604402 198.388047 73.211589 262.384191 351.313233 263.049751 855.858835 262.896161-60.156376-321.926204-172.328817-530.29765-333.599101-619.533873-149.597387-82.785412-297.966048-37.629733-354.845821-14.335136-11.980078 4.914904-24.06255 10.95614-35.786644 17.91892-12.133669 7.218765-27.851122 3.225406-35.069887-8.908263s-3.225406-27.851122 8.908263-35.069887c13.925561-8.2939 28.260697-15.461468 42.595834-21.349114 31.844481-13.004017 83.143791-29.694211 146.679163-35.172281 14.027955-1.228726 27.902319-1.791892 41.674289-1.791892 75.208269 0 145.860012 18.072511 210.675307 53.910352 82.375837 45.565255 153.641943 119.749585 211.904033 220.351524 68.296685 118.00889 119.698388 274.51786 152.720399 465.175173 1.279923 7.423553-0.767954 15.051893-5.631661 20.837145z" horiz-adv-x="1025" />
<glyph glyph-name="folder" unicode="&#60094;" d="M970.666667 682.666667H542.173333L429.793333 795.046667A52.986667 52.986667 0 0 1 392.08 810.666667H96a53.393333 53.393333 0 0 1-53.333333-53.333334v-704a53.393333 53.393333 0 0 1 53.333333-53.333333h874.666667a53.393333 53.393333 0 0 1 53.333333 53.333333V629.333333a53.393333 53.393333 0 0 1-53.333333 53.333334zM96 768h296.08a10.573333 10.573333 0 0 0 7.54-3.126667L481.826667 682.666667H96a53.546667 53.546667 0 0 1-10.666667-1.073334V757.333333a10.666667 10.666667 0 0 0 10.666667 10.666667z m885.333333-714.666667a10.666667 10.666667 0 0 0-10.666666-10.666666H96a10.666667 10.666667 0 0 0-10.666667 10.666666V629.333333a10.666667 10.666667 0 0 0 10.666667 10.666667h874.666667a10.666667 10.666667 0 0 0 10.666666-10.666667z" horiz-adv-x="1024" />
<glyph glyph-name="folder-open" unicode="&#60097;" d="M1003.153333 491.04a52.933333 52.933333 0 0 1-42.38 20.96H896V629.333333a53.393333 53.393333 0 0 1-53.333333 53.333334H461.253333a10.573333 10.573333 0 0 0-7.54 3.126666L344.46 795.046667A52.986667 52.986667 0 0 1 306.746667 810.666667H53.333333a53.393333 53.393333 0 0 1-53.333333-53.333334v-704a53.393333 53.393333 0 0 1 53.333333-53.333333h796.893334a53.453333 53.453333 0 0 1 51.453333 39.333333l110.546667 405.333334a52.953333 52.953333 0 0 1-9.073334 46.373333zM53.333333 768h253.413334a10.573333 10.573333 0 0 0 7.54-3.126667l109.253333-109.253333A52.986667 52.986667 0 0 1 461.253333 640H842.666667a10.666667 10.666667 0 0 0 10.666666-10.666667v-117.333333H173.773333a53.453333 53.453333 0 0 1-51.453333-39.333333L42.666667 180.633333V757.333333a10.666667 10.666667 0 0 0 10.666666 10.666667z m917.726667-312.14l-110.546667-405.333333a10.666667 10.666667 0 0 0-10.286666-7.86H63.226667a10.666667 10.666667 0 0 0-10.286667 13.473333l110.546667 405.333333A10.666667 10.666667 0 0 0 173.773333 469.333333h787a10.666667 10.666667 0 0 0 10.286667-13.473333z" horiz-adv-x="1024" />
<glyph glyph-name="gitee" unicode="&#59035;" d="M512-128C229.222-128 0 101.222 0 384S229.222 896 512 896s512-229.222 512-512-229.222-512-512-512z m259.149 568.883h-290.74a25.293 25.293 0 0 1-25.292-25.293l-0.026-63.206c0-13.952 11.315-25.293 25.267-25.293h177.024c13.978 0 25.293-11.315 25.293-25.267v-12.646a75.853 75.853 0 0 0-75.853-75.853h-240.23a25.293 25.293 0 0 0-25.267 25.293V478.797a75.853 75.853 0 0 0 75.827 75.853h353.946a25.293 25.293 0 0 1 25.267 25.292l0.077 63.207a25.293 25.293 0 0 1-25.268 25.293H417.152a189.62 189.62 0 0 1-189.62-189.645V124.85c0-13.977 11.316-25.293 25.294-25.293h372.94a170.65 170.65 0 0 1 170.65 170.65V415.616a25.293 25.293 0 0 1-25.293 25.267z" horiz-adv-x="1024" />
<glyph glyph-name="github" unicode="&#59047;" d="M512 883.32190493c275.66730126 0 499.32190493-223.65460366 499.32190493-499.32190493 0-220.40901063-143.01411555-407.65472541-341.32813256-473.98131826-25.34058667-4.53550763-34.45321159 11.06830222-34.45321159 24.05067207 0 16.26957255 0.6657627 70.19633778 0.66576271 137.18869334 0 46.81142841-15.60380985 76.72913237-33.7874489 92.33294222 111.18234397 12.35821682 228.19011015 54.63413874 228.1901113 246.41536 0 54.63413874-19.51516445 98.82412715-51.34693604 133.9431003 5.20127033 13.02397952 22.09499477 63.70515285-5.20127033 132.61157604-41.61015922 13.02397952-137.18869333-51.34693603-137.18869333-51.34693604a469.36259015 469.36259015 0 0 1-249.6609519 0S291.63259904 689.58500523 250.02244096 676.56102571c-27.29626397-68.90642318-10.40253952-119.62920619-5.20127033-132.61157604-31.87338126-35.11897429-51.34693603-79.3089627-51.34693604-133.9431003 0-191.15706937 116.38361429-234.05714318 227.56595826-246.41536-14.31389411-13.02397952-27.29626397-35.11897429-31.87338126-66.95074588-28.62778937-13.02397952-101.44556715-35.11897429-144.96979285 41.61015921-27.29626397 47.47719111-76.72913237 51.34693603-76.72913351 51.34693604-48.76710571 0.6657627-3.24559189-30.54185699-3.2455919-30.541857 32.49753429-14.93804715 55.25829063-72.81777778 55.25829064-72.81777777 29.25194126-89.08735033 168.39631189-59.16964523 168.39631302-59.16964523 0-41.61015922 0.6657627-80.5988773 0.66576157-92.95709525 0-13.02397952-9.11262493-28.62778937-34.45321045-24.05067094C155.77543111-23.61311459000001 12.76131555 163.63259903999995 12.76131555 384.04160967c0 275.66730126 223.65460366 499.32190493 499.32190493 499.32190492zM201.87948715 166.21242937c1.28991459 2.62144-0.6657627 5.86703189-4.53550763 7.78109952-3.91135459 1.28991459-7.15694763 0.6657627-8.44686222-1.2899146-1.28991459-2.62144 0.6657627-5.86703189 4.53550763-7.78109952 3.24559189-1.9556773 7.15694763-1.28991459 8.44686222 1.2899146z m20.13931634-22.13660444c2.62144 1.9556773 1.9556773 6.49118493-1.2899146 10.40253952-3.24559189 3.24559189-7.78109952 4.53550763-10.40253952 1.95567729-2.62144-1.9556773-1.9556773-6.49118493 1.2899146-10.40253952 3.24559189-3.24559189 7.78109952-4.53550763 10.40253952-1.95567729z m19.51516444-29.25194127c3.24559189 2.62144 3.24559189 7.78109952 0 12.35821682-2.62144 4.53550763-7.78109952 6.49118493-11.06830222 3.91135459-3.24559189-1.9556773-3.24559189-7.15694763 0-11.69245411s8.44686222-6.49118493 11.06830222-4.53550763z m27.29626396-27.2962651c2.62144 2.62144 1.28991459 8.44686222-2.62144 12.35821795-4.53550763 4.53550763-10.40253952 5.20127033-13.02397952 1.9556773-3.24559189-2.62144-1.9556773-8.44686222 2.62144-12.35821682 4.53550763-4.53550763 10.40253952-5.20127033 13.02397952-1.95567843z m37.0746516-16.26957141c1.28991459 3.91135459-2.62144 8.44686222-8.44686223 10.40253952-5.20127033 1.28991459-11.06830222-0.6657627-12.35821681-4.53550763s2.62144-8.44686222 8.44686222-9.73677682c5.20127033-1.9556773 11.06830222 0 12.35821682 3.9113546z m40.94439651-3.24559304c0 4.53550763-5.20127033 7.78109952-11.06830222 7.15694763-5.86703189 0-10.40253952-3.24559189-10.40253952-7.15694763 0-4.53550763 4.53550763-7.78109952 11.06830222-7.15694648 5.86703189 0 10.40253952 3.24559189 10.40253952 7.15694648z m37.69880349 6.49118493c-0.6657627 3.91135459-5.86703189 6.49118493-11.69245412 5.86703303-5.86703189-1.28991459-9.73677682-5.20127033-9.11262492-9.73677796 0.6657627-3.91135459 5.86703189-6.49118493 11.69245411-5.20126918s9.73677682 5.20127033 9.11262493 9.11262492z" horiz-adv-x="1024" />
<glyph glyph-name="disabled" unicode="&#59084;" d="M509.20496914 834c-245.9627332 0-447.20496914-201.24223594-447.20496914-447.20496914s201.24223594-447.20496914 447.20496914-447.20496914 447.20496914 201.24223594 447.20496914 447.20496914-201.24223594 447.20496914-447.20496914 447.20496914zM509.20496914-10.09937930000001C291.19254628-10.09937930000001 112.31055898 168.78260888 112.31055898 386.79503086c0 95.03105625 33.54037295 184.4720499 95.03105625 257.14285752l553.41614883-553.41614883C693.67701904 23.440993649999996 604.23602451-10.09937930000001 509.20496914-10.09937930000001z m296.27329131 134.16149092l-559.00621055 553.41614883C319.14285752 738.96894375 408.58385117 778.0993793 509.20496914 778.0993793c218.01242197 0 396.89441016-178.8819873 396.89441016-396.89441016 0-95.03105625-39.13043467-190.06211162-100.62111885-257.14285752z" horiz-adv-x="1024" />
<glyph glyph-name="moon" unicode="&#59074;" d="M696.832 680.448c98.816-62.976 162.304-173.056 162.304-294.912 0-192.512-156.672-349.184-349.184-349.184-121.856 0-232.448 63.488-294.912 162.816h5.12c263.168 0 477.184 214.016 477.184 477.184-0.512 1.536-0.512 3.072-0.512 4.096m-78.336 103.936c9.216-34.304 14.336-70.656 14.336-108.032 0-228.352-184.832-413.184-413.184-413.184-37.376 0-73.728 5.12-108.544 14.336 47.616-175.616 207.872-305.152 398.848-305.152 228.352 0 413.184 184.832 413.184 413.184 0 190.976-129.024 351.232-304.64 398.848z" horiz-adv-x="1024" />
<glyph glyph-name="error" unicode="&#59027;" d="M512-60.09287109000002c-245.26845703 0-444.09550781 198.82880859-444.09550781 444.09550781s198.82705078 444.09287109 444.09550781 444.09287109c245.26669922 0 444.09550781-198.82880859 444.09550781-444.09550781s-198.82880859-444.09287109-444.09550781-444.09287109zM512 772.58378906c-214.60166016 0-388.58378906-173.97861328-388.58378906-388.58378906s173.98125-388.58115234 388.58378906-388.58115234c214.60166016 0 388.58115234 173.97861328 388.58115234 388.58115234s-173.97861328 388.58378906-388.58115234 388.58378906zM551.41103516 383.85585937999997l117.60029297-117.62138672c10.84306641-10.82460938 10.84306641-28.40625 0-39.24580079-10.83955078-10.84306641-28.42119141-10.84306641-39.24580079 0l-117.62138671 117.60029297-118.39570313-118.39570312c-10.93271484-10.93095703-28.64091797-10.93095703-39.55517578 0-10.93271484 10.93095703-10.93271484 28.64091797 0 39.55693359l118.39570312 118.41240235-117.60292968 117.60292968c-10.84130859 10.84130859-10.84130859 28.40625 0 39.24931641 10.84306641 10.83955078 28.40625 10.83955078 39.2493164 0l117.60292969-117.60292969 119.28164063 119.28164063c10.93095703 10.91513672 28.64091797 10.91513672 39.55693359 0 10.93095703-10.93095703 10.93095703-28.64091797 0-39.57363281l-119.26757813-119.26582032z" horiz-adv-x="1024" />
<glyph glyph-name="success" unicode="&#59031;" d="M661.31818174 521.04545479c10.22727305 12.27272695 30.68181826 14.31818174 42.95454521 4.09090868 12.27272695-10.22727305 14.31818174-30.68181826 4.09090957-42.95454521l-204.54545478-243.40909131c-10.22727305-12.27272695-30.68181826-14.31818174-42.95454522-4.09090869L327.90909131 345.13636347c-12.27272695 10.22727305-14.31818174 30.68181826-4.09090957 42.95454522 10.22727305 12.27272695 30.68181826 14.31818174 42.95454521 4.09090957l110.4545461-92.04545478 184.09090869 220.90909131zM512-66C262.45454521-66 62 134.45454521 62 384S262.45454521 834 512 834s450-200.45454521 450-450-200.45454521-450-450-450z m0 40.90909131c225 0 409.09090869 184.09090869 409.09090869 409.09090869S737 793.09090869 512 793.09090869 102.90909131 609 102.90909131 384s184.09090869-409.09090869 409.09090869-409.09090869z" horiz-adv-x="1024" />
<glyph glyph-name="question" unicode="&#59033;" d="M468.125 159a37.50000029 37.50000029 0 1 1 37.50000029 37.50000029 37.50000029 37.50000029 0 0 1-37.50000029-37.50000029z m37.50000029 92.62500029h-3.00000058a31.5 31.5 0 0 0-28.49999942 34.49999971A203.24999971 203.24999971 0 0 0 549.50000029 400.12500029c56.62500029 56.62500029 57.75000029 74.99999971 58.5 93.74999942a81.37500029 81.37500029 0 0 1-23.25000058 60.75A98.62499971 98.62499971 0 0 1 512 584.99999971a94.5 94.5 0 0 1-94.5-94.5 31.5 31.5 0 1 0-63.37500029 0A157.5 157.5 0 0 0 512 646.50000029a162.37500029 162.37500029 0 0 0 117.74999971-50.25000058 144.37500029 144.37500029 0 0 0 39.75000029-105.75c-2.25-40.87500029-14.625-72.74999971-77.24999971-135-31.5-31.5-51.75-55.50000029-53.62500058-74.99999971a31.5 31.5 0 0 0-31.12499971-29.99999971z m277.875-139.87500029A386.62499971 386.62499971 0 1 0 361.99999971 740.24999971a386.62499971 386.62499971 0 0 0 423.37500029-629.62499971zM512 834a450 450 0 1 1 450-450A450 450 0 0 1 512 834z" horiz-adv-x="1024" />
<glyph glyph-name="lock" unicode="&#59034;" d="M512-66A450 450 0 1 0 962 384 450.39130401 450.39130401 0 0 0 512-66z m0 860.86956533A410.86956533 410.86956533 0 1 1 922.86956533 384 411.26086934 411.26086934 0 0 1 512 794.86956533zM665.78260888 398.86956533h-14.47826132v78.26086934a139.69565244 139.69565244 0 0 1-279-7.82608711v-70.04347823h-11.73912979a19.95652177 19.95652177 0 0 1-19.95652178-20.34782577v-199.56521778a19.95652177 19.95652177 0 0 1 19.95652178-20.34782578h302.86956445a19.95652177 19.95652177 0 0 1 19.95652179 20.34782578v199.56521778a20.73913067 20.73913067 0 0 1-17.60869513 19.95652177z m-254.34782665 70.43478223a100.56521777 100.56521777 0 0 0 200.73913066 4.69565244v-74.73913067H411.43478223z" horiz-adv-x="1024" />
<glyph glyph-name="eye" unicode="&#59029;" d="M513.92 449.493333a64 64 0 1 0-64-64 64 64 0 0 0 64 64m0 64a128 128 0 1 1 128-128 128 128 0 0 1-128 128zM512 606.2933330000001c128 0 257.706667-67.84 397.226667-207.146666a21.333333 21.333333 0 0 0 0-30.08C770.133333 229.54666699999996 640 161.70666700000004 512 161.70666700000004s-257.28 67.84-396.8 207.146666a21.333333 21.333333 0 0 0 0 30.08c139.52 139.52 268.8 207.36 396.8 207.36m0 64c-145.92 0-291.84-75.306667-442.453333-225.92a85.333333 85.333333 0 0 1 0-120.746666C220.586667 173.013333 366.506667 97.70666700000004 512 97.70666700000004s292.266667 75.306667 442.666667 225.92a85.333333 85.333333 0 0 1 0 120.746666C804.266667 594.986667 658.346667 670.293333 512 670.293333z" horiz-adv-x="1024" />
<glyph glyph-name="eye-invisible" unicode="&#59030;" d="M386.346667 391.466667l121.813333 121.813333a128 128 0 0 1-121.813333-121.813333z m238.72 57.6L576 400.213333a64 64 0 0 0-76.8-76.8l-48.853333-48.853333a128 128 0 0 1 174.506666 174.506667zM109.013333 384a21.333333 21.333333 0 0 0 6.186667 15.146667c139.52 139.306667 268.8 207.146667 396.8 207.146666a372.266667 372.266667 0 0 0 79.786667-8.96l52.266666 52.266667a443.52 443.52 0 0 1-132.053333 21.333333c-145.92 0-291.84-75.306667-442.453333-225.92a85.333333 85.333333 0 0 1 0-120.746666 1063.04 1063.04 0 0 1 134.186666-115.2l45.866667 45.866666a985.813333 985.813333 0 0 0-134.4 114.133334 21.333333 21.333333 0 0 0-6.186667 14.933333z m845.653334 60.373333a966.613333 966.613333 0 0 1-185.813334 149.333334l-46.72-46.72a877.653333 877.653333 0 0 0 187.306667-147.2 21.333333 21.333333 0 0 0 0-30.08C770.133333 229.54666699999996 640 161.70666700000004 512 161.70666700000004a393.386667 393.386667 0 0 0-145.706667 29.013333l-48.64-48.64A466.133333 466.133333 0 0 1 512 97.70666700000004c145.92 0 291.84 75.306667 442.453333 225.92a85.333333 85.333333 0 0 1 0.213334 120.746666zM777.267604 692.049287m22.627417-22.627417l0 0q22.627417-22.627417 0-45.254834l-527.973064-527.973063q-22.627417-22.627417-45.254834 0l0 0q-22.627417 22.627417 0 45.254834l527.973064 527.973063q22.627417 22.627417 45.254834 0Z" horiz-adv-x="1024" />
<glyph glyph-name="backspace" unicode="&#59028;" d="M484.46100645 268.09861505000003a28.76779355 28.76779355 0 0 0-20.34016344 49.107957l174.2671828 174.27268816a28.76779355 28.76779355 0 0 0 40.68473118-40.68032687l-174.2671828-174.27819355a28.6940215 28.6940215 0 0 0-20.34456774-8.42322581zM658.72708818 268.09861505000003a28.68301076 28.68301076 0 0 0-20.34016345 8.42322581l-174.26718279 174.27709248a28.76228818 28.76228818 0 0 0 0 40.68032687 28.75127742 28.75127742 0 0 0 40.68142795 0l174.2671828-174.27268816a28.77990537 28.77990537 0 0 0-20.34126451-49.107957zM834.5379785 74.81145805999995H340.57028818c-28.46940215 0-55.25305806 12.53684301-73.49016775 34.39428818L75.75838279 339.01887310999996c-10.54830108 13.06205592-16.20232258 28.91974194-16.1968172 44.98663226 0.00660645 15.39083011 4.67406452 29.85015053 13.50248602 41.81333334 0.33803011 0.45694624 0.68266666 0.90288172 1.04822366 1.33009892L266.70685592 658.36593548a95.32449032 95.32449032 0 0 0 73.86233118 34.82921291H834.5379785c51.98286452 0 94.27516559-42.28789677 94.27516558-94.27076129v-429.83776344c0-51.98286452-42.29230108-94.27516559-94.27516558-94.2751656zM119.01522581 391.16579785c-0.90728602-1.35872689-1.91587097-3.52344086-1.91587097-7.17680861 0-2.92005161 1.14952258-6.01517419 3.15568172-8.50140214l191.02114409-229.45307528a38.55965592 38.55965592 0 0 1 29.29300645-13.69297203H834.5379785a36.78472258 36.78472258 0 0 1 36.74508387 36.74508387v429.83776344a36.78472258 36.78472258 0 0 1-36.74508387 36.73957849H340.5691871a38.60590108 38.60590108 0 0 1-29.53524302-13.96934193L119.01522581 391.16579785z" horiz-adv-x="1024" />
<glyph glyph-name="help-circle" unicode="&#59260;" d="M505.181 153.98199999999997c-26.499 0-47.972-21.481-47.972-47.968s21.474-47.977 47.972-47.977c26.48 0 47.948 21.488 47.948 47.977s-21.469 47.968-47.948 47.968zM505.181 825.872c-246.883 0-447.689-200.826-447.689-447.683 0-246.874 200.806-447.705 447.689-447.705 246.849 0 447.683 200.83 447.683 447.705 0 246.858-200.836 447.683-447.683 447.683zM505.181-5.273000000000025c-211.46 0-383.455 172.045-383.455 383.459 0 211.431 171.995 383.436 383.455 383.436 211.391 0 383.455-172.003 383.455-383.436 0-211.417-172.064-383.459-383.455-383.459zM505.162 664.795c-88.146 0-159.892-71.093-159.892-158.448 0-17.648 14.347-31.981 31.981-31.981 17.675 0 31.985 14.332 31.985 31.981 0 52.987 42.167 94.498 95.946 94.498 52.873 0 95.926-43.366 95.926-96.677 0-21.324-26.753-48.058-52.634-73.965-35.309-35.267-75.282-75.237-75.282-127.563v-54.067c0-17.663 14.341-31.985 31.989-31.985 17.634 0 31.97 14.363 31.97 32.016v54.071c0 25.807 28.719 54.524 56.54 82.282 35.074 35.074 71.383 71.346 71.383 119.221-0.002 88.573-71.718 160.617-159.914 160.617z" horiz-adv-x="1024" />
<glyph glyph-name="tips-fill" unicode="&#60206;" d="M512 832C264.6 832 64 631.4 64 384s200.6-448 448-448 448 200.6 448 448S759.4 832 512 832z m-32-232c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-272c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8V600z m32-440c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48z" horiz-adv-x="1024" />
<glyph glyph-name="test" unicode="&#59026;" d="M513.058-31.072000000000003c-56.004 0-110.35 10.976-161.528 32.622-49.416 20.901-93.789 50.816-131.887 88.914-38.098 38.099-68.013 82.472-88.915 131.888-21.646 51.178-32.622 105.524-32.622 161.528s10.976 110.35 32.622 161.528c20.901 49.416 50.816 93.789 88.915 131.887s82.471 68.013 131.887 88.915c51.178 21.646 105.524 32.622 161.528 32.622 64.817 0 126.912-14.538 184.56-43.209 54.937-27.323 104.055-67.35 142.042-115.754 10.911-13.903 8.486-34.019-5.417-44.93-13.903-10.91-34.018-8.485-44.929 5.417-67.071 85.461-167.763 134.476-276.256 134.476-193.516 0-350.952-157.436-350.952-350.952s157.436-350.952 350.952-350.952c200.075 0 350.952 141.419 350.952 328.952 0 17.673 14.327 32 32 32s32-14.327 32-32c0-109.988-43.501-210.61-122.49-283.33-76.785-70.692-180.65-109.622-292.462-109.622zM636.555 275.40700000000004c-5.39 0-10.85 1.362-15.862 4.23-15.34 8.776-20.66 28.327-11.884 43.667L781.3 624.79c8.776 15.341 28.33 20.661 43.667 11.884 15.34-8.777 20.66-28.327 11.884-43.667L664.359 291.52099999999996c-5.908-10.327-16.703-16.114-27.804-16.114zM628.023 263.38199999999995a31.856 31.856 0 0 0-19.204 6.424L403.383 424.242c-14.127 10.62-16.97 30.681-6.35 44.807 10.62 14.127 30.68 16.97 44.807 6.35l205.437-154.438c14.127-10.619 16.97-30.68 6.35-44.807-6.289-8.363-15.888-12.772-25.604-12.772zM219.079 140.418a31.849 31.849 0 0 0-18.931 6.222c-14.238 10.47-17.293 30.499-6.823 44.737l202.489 275.372c10.468 14.239 30.499 17.294 44.737 6.823 14.238-10.47 17.293-30.499 6.823-44.737L244.885 153.46299999999997c-6.271-8.528-15.974-13.045-25.806-13.045z" horiz-adv-x="1024" />
@ -46,8 +68,6 @@
<glyph glyph-name="chrome" unicode="&#59018;" d="M515.436 583.685H914.285C840.842 730.955 688.748 832.132 513 832.132c-141.284 0-267.274-65.395-349.42-167.546l151.66-262.682c8.535 102.325 95.704 181.781 200.196 181.781zM514.218 550.803c-91.476 0-165.631-74.155-165.631-165.631s74.155-165.631 165.631-165.631c52.7 0 99.615 24.642 129.95 62.999l1.428 2.474 0.355-0.205c21.252 27.852 33.898 62.624 33.898 100.363 0 84.774-63.702 154.626-145.841 164.413l-6.393 0.632c-4.424 0.354-8.882 0.586-13.397 0.586zM929.561 549.585H627.443c52.209-36.066 86.506-96.297 86.506-164.413 0-45.547-18.268-81.598-41.12-121.192L483.898-63.257c9.624-0.617 19.322-0.966 29.102-0.966 247.521 0 448.177 200.656 448.177 448.177 0 58.508-11.225 114.391-31.616 165.631zM514.218 185.441c-83.583 0-144.927 54.804-185.034 124.651l-0.235-0.136-187.482 324.727C93.081 563.124 64.823 476.84 64.823 383.954c0-225.02 165.839-411.288 381.958-443.298l152.278 263.752c-25.769-12.143-54.518-18.967-84.841-18.967z" horiz-adv-x="1024" />
<glyph glyph-name="edge" unicode="&#59019;" d="M854.794 669.297C797.923 743.783 683.626 823.59 548.62 830.822 136.707 852.889 85.742 435.448 85.742 435.448c55.449 53.038 58.01 97.116 163.936 154.293C673.983 818.768 676.394 476.432 676.394 476.432H346.111c-7.232 65.092 62.681 137.417 62.681 137.417-202.509-98.844-216.974-284.477-216.974-284.477s-28.93-279.655 219.385-364.034 452.029 42.189 452.029 42.189V193.16c-59.065-32.546-102.292-54.405-153.087-63.887-361.623-67.503-364.034 188.044-364.034 188.044h585.83c0 0.001 39.075 199.761-77.147 351.98z" horiz-adv-x="1024" />
<glyph glyph-name="heart" unicode="&#59020;" d="M512 4.100000000000023c-108.9 0-447.3 277.5-447.3 522.2 0 131 106.6 237.6 237.6 237.6 94.9 0 174.8-50.2 209.7-76.1 34.9 25.9 114.8 76.1 209.7 76.1 131 0 237.6-106.6 237.6-237.6 0-244.7-338.4-522.2-447.3-522.2zM302.3 708c-100.2 0-181.7-81.5-181.7-181.7 0-221 326.8-466.3 391.4-466.3s391.4 245.3 391.4 466.3c0 100.2-81.5 181.7-181.7 181.7-103.9 0-190.2-76-191.1-76.8-10.6-9.5-26.7-9.5-37.3 0-0.8 0.8-87.7 76.8-191 76.8z" horiz-adv-x="1024" />
<glyph glyph-name="key" unicode="&#59011;" d="M819.2 588.8c0-172.8-140.8-307.2-307.2-307.2-172.8 0-307.2 140.8-307.2 307.2C204.8 755.2 339.2 896 512 896S819.2 755.2 819.2 588.8L819.2 588.8zM512 838.4c-140.8 0-249.6-115.2-249.6-249.6 0-134.4 108.8-256 249.6-256s256 115.2 256 249.6S652.8 838.4 512 838.4L512 838.4zM480 300.79999999999995l64 0L544-128l-64 0L480 300.79999999999995 480 300.79999999999995zM512 192l192 0 0-64L512 128 512 192 512 192zM512 64l192 0 0-64L512 0 512 64 512 64z" horiz-adv-x="1024" />

Before

Width:  |  Height:  |  Size: 309 KiB

After

Width:  |  Height:  |  Size: 322 KiB

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
.pear-nav-tree {
width: 230px;
width: 230px !important;
border-radius: 0px;
background-color: #28333E;
}

View File

@ -55,6 +55,14 @@
font-size: 15px !important;
}
.layui-table-cell .pear-btn {
margin-right: 5px;
}
.layui-table-cell .pear-btn:last-child {
margin-right: 0px;
}
.layui-table-page {
height: 45px !important;
padding-top: 10px !important;

View File

@ -70,71 +70,70 @@ layui.define(["table", "form",'toast','common'], function (exports) {
// });
var api = {
userinfo: {
get: function () {
var userinfo = localStorage.getItem("taoleradmin_userinfo");
return userinfo ? JSON.parse(userinfo) : null;
},
set: function (data) {
if (data) {
localStorage.setItem("taoleradmin_userinfo", JSON.stringify(data));
} else {
localStorage.removeItem("taoleradmin_userinfo");
}
userinfo: {
get: function () {
var userinfo = localStorage.getItem("taoleradmin_userinfo");
return userinfo ? JSON.parse(userinfo) : null;
},
set: function (data) {
if (data) {
localStorage.setItem("taoleradmin_userinfo", JSON.stringify(data));
} else {
localStorage.removeItem("taoleradmin_userinfo");
}
}
}
}
}
//监听工具条
table.on("tool(addons-list)", function (obj) {
var data = obj.data;
var event = obj.event;
var url = $(this).data('url')
var data = obj.data;
var event = obj.event;
var url = $(this).data('url')
// 安装
var install = function (data,url,userLoginUrl,userIsPayUrl){
// 安装
var install = function (data,url,userLoginUrl,userIsPayUrl){
var userinfo = api.userinfo.get(); // 检测权限
if(userinfo) {
layer.confirm("确认安装吗?", "vcenter",function(index){
$.post(url, { name: data.name, version: data.version, uid: userinfo.uid, token: userinfo.token }, function (res) {
// 需要支付
if (res.code === -2) {
layer.close(index);
layer.open({
type: 2,
area: [common.isModile()?'100%':'800px', common.isModile()?'100%':'600px'],
fixed: false, //不固定
maxmin: true,
content: 'pay.html'+ "?id=" + data.id+ "&name=" + data.name + "&version=" + data.version + "&uid=" + userinfo.uid + "&price=" + data.price,
success: function (layero, index){
// 订单轮询
var intervalPay = setInterval(function() {
$.post(userIsPayUrl,{name:data.name, userinfo:userinfo},function (res){
if(res.code === 0) {
layer.close(index);
clearInterval(intervalPay);
install(data,url,userLoginUrl,userIsPayUrl);
}
layer.confirm("确认安装吗?", "vcenter",function(index){
layer.close(index);
let loading = layer.load();
$.post(url, { name: data.name, version: data.version, uid: userinfo.uid, token: userinfo.token }, function (res) {
layer.close(loading);
// 需要支付
if (res.code === -2) {
layer.open({
type: 2,
area: [common.isModile()?'100%':'800px', common.isModile()?'100%':'600px'],
fixed: false, //不固定
maxmin: true,
content: 'pay.html'+ "?id=" + data.id+ "&name=" + data.name + "&version=" + data.version + "&uid=" + userinfo.uid + "&price=" + data.price,
success: function (layero, index){
// 订单轮询
var intervalPay = setInterval(function() {
$.post(userIsPayUrl,{name:data.name, userinfo:userinfo},function (res){
if(res.code === 0) {
layer.close(index);
clearInterval(intervalPay);
install(data,url,userLoginUrl,userIsPayUrl);
}
});
},3000);
}
});
},3000);
}
// 安装成功
if (res.code === 0) {
toast.success({title:"安装成功",message:res.msg,position: 'topRight'});
}
// 安装失败
if (res.code === -1) {
toast.error({title:"安装失败",message:res.msg,position: 'topRight'});
}
// 重载
table.reloadData("addons-list",{},'deep');
});
}
// 安装成功
if (res.code === 0) {
layer.close(index);
toast.success({title:"安装成功",message:res.msg,position: 'topRight'});
}
// 安装失败
if (res.code === -1) {
layer.close(index);
toast.error({title:"安装失败",message:res.msg,position: 'topRight'});
}
// 重载
table.reloadData("addons-list",{},'deep');
});
});
} else {
// 未登录时
layer.confirm('你当前还未登录TaoLer社区账号,请登录后操作!', {
@ -189,15 +188,15 @@ layui.define(["table", "form",'toast','common'], function (exports) {
}
}
//安装插件
if (event === "install" || event === "upgrade") {
//安装插件
if (event === "install" || event === "upgrade") {
var userLoginUrl = $(this).data('userlogin');
var userIsPayUrl = $(this).data('ispay');
install(data,url,userLoginUrl,userIsPayUrl);
}
// 卸载插件
if (event === "uninstall") {
// 卸载插件
if (event === "uninstall") {
layer.confirm("是否卸载?", "vcenter",function(index) {
$.post(url, { name: data.name }, function (res) {
if (res.code === 0) {
@ -212,8 +211,8 @@ layui.define(["table", "form",'toast','common'], function (exports) {
});
}
// 配置插件
if (event === "config") {
// 配置插件
if (event === "config") {
$.post(url,{name:data.name},function (res){
// 无配置项拦截
if (res.code === -1) {

View File

@ -177,7 +177,7 @@ layui.define(['table', 'laypage','jquery', 'element'], function(exports) {
function createCard(elem, linenum, item, no) {
var line = 12 / linenum;
var card =
'<div id=' + item.id + ' onclick="cardTableCheckedCard(' + elem + ',this)" class="layui-col-md' + line + ' ew-datagrid-item" data-index="' + no+'" data-number="1"> <div class="project-list-item"> <div class="project-list-item-cover" style="background-image: url(' +item.image + ');"></div> <div class="project-list-item-body"> <h2 class="layui-elip">' + item.title + '</h2> <div class="project-list-item-text layui-text">' + item.remark + '</div> <div class="project-list-item-desc"> <span class="time">' +item.time + '</span> <div class="ew-head-list"></div> </div> </div > </div > </div > '
'<div id=' + item.id + ' onclick="cardTableCheckedCard(' + elem + ',this)" class="layui-col-md' + line + ' ew-datagrid-item" data-index="' + no+'" data-number="1"> <div class="project-list-item"> <img class="project-list-item-cover" src="' + item.image + '"> <div class="project-list-item-body"> <h2 class="layui-elip">' + item.title + '</h2> <div class="project-list-item-text layui-text">' + item.remark + '</div> <div class="project-list-item-desc"> <span class="time">' +item.time + '</span> <div class="ew-head-list"></div> </div> </div > </div > </div > '
return card;
}

View File

@ -1,119 +1,114 @@
layui.define(['jquery', 'element','table'], function(exports) {
"use strict";
layui.define(['jquery', 'element', 'table'], function (exports) {
"use strict";
/**
* 常用封装类
* */
var MOD_NAME = 'common',
$ = layui.jquery,
table = layui.table,
element = layui.element;
/**
* 常用封装类
* */
var MOD_NAME = 'common',
$ = layui.jquery,
table = layui.table,
element = layui.element;
var common = new function() {
/**
* 获取当前表格选中字段
* @param obj 表格回调参数
* @param field 要获取的字段
* */
this.checkField = function(obj, field) {
let data = table.checkStatus(obj.config.id).data;
if (data.length === 0) {
return "";
}
let ids = "";
for (let i = 0; i < data.length; i++) {
ids += data[i][field] + ",";
}
ids = ids.substr(0, ids.length - 1);
return ids;
}
/**
* 当前是否为与移动端
* */
this.isModile = function(){
if ($(window).width() <= 768) {
return true;
}
return false;
}
/**
* 提交 json 数据
* @param href 必选 提交接口
* @param data 可选 提交数据
* @param ajaxtype 可选 提交方式(默认为get)
* @param table 可选 刷新父级表
* @param callback 可选 自定义回调函数
* @param dataType 可选 返回数据类型 智能猜测可以是xml, json, script, html
* @param is_async 可选 请求是否异步处理默认是 true
* @param is_cache 可选 浏览器是否缓存被请求页面默认是 true
* */
this.submit = function(href,data,ajaxtype,table,callback,dataType,is_async,is_cache){
if(ajaxtype=='' || ajaxtype==undefined){ ajaxtype='get';}
var common = new function () {
if(data!==undefined){
$.ajaxSetup({data:JSON.stringify(data)});
}else {
$.ajaxSetup({data:''});
}
if(is_cache!==undefined){
$.ajaxSetup({dataType:dataType });
}
if(is_async!==undefined){
$.ajaxSetup({async:is_async });
}
if(is_cache!==undefined){
$.ajaxSetup({cache:is_cache });
}
$.ajax({
url:href,
contentType:'application/json',
type:ajaxtype,
success:callback !=null?callback:function(result){
if(result.code==1){
layer.msg(result.msg,{icon:1,time:1000},function(){
if(parent.layer.getFrameIndex(window.name)!=undefined){
parent.layer.close(parent.layer.getFrameIndex(window.name));//关闭当前页
if(table!=null){parent.layui.table.reload(table);}
}else {
if(table!=null){layui.table.reload(table);}
}
});
}else{
layer.msg(result.msg,{icon:2,time:1000});
}
},
error:function(xhr){
if(xhr.status==401)
{
layer.msg('权限不足,您无法访问受限资源或数据',{icon: 5});
}
if(xhr.status==404)
{
layer.msg('请求url地址错误请确认后刷新重试',{icon: 5});
}
if(xhr.status==419)
{
layer.msg('长时间未操作,自动刷新后重试!',{icon: 5});
setTimeout(function () { window.location.reload();}, 2000);
}
if(xhr.status==429)
{
layer.msg('尝试次数太多,请一分钟后再试',{icon: 5});
}
if(xhr.status==500)
{
layer.msg(xhr.responseJSON.message,{icon: 5});
}
}
,complete:function (xhr,status){
/**
* 获取当前表格选中字段
* @param obj 表格回调参数
* @param field 要获取的字段
* */
this.checkField = function (obj, field) {
let data = table.checkStatus(obj.config.id).data;
if (data.length === 0) {
return "";
}
let ids = "";
for (let i = 0; i < data.length; i++) {
ids += data[i][field] + ",";
}
ids = ids.substring(0, ids.length - 1);
return ids;
}
}
})
}
}
exports(MOD_NAME, common);
/**
* 当前是否为与移动端
* */
this.isModile = function () {
return $(window).width() <= 768;
}
/**
* 提交 json 数据
* @param href 必选 提交接口
* @param data 可选 提交数据
* @param ajaxtype 可选 提交方式(默认为get)
* @param table 可选 刷新父级表
* @param callback 可选 自定义回调函数
* @param dataType 可选 返回数据类型 智能猜测可以是xml, json, script, html
* @param is_async 可选 请求是否异步处理默认是 true
* @param is_cache 可选 浏览器是否缓存被请求页面默认是 true
* */
this.submit = function (href, data, ajaxtype, table, callback, dataType, is_async, is_cache) {
if (data !== undefined) {
$.ajaxSetup({data: JSON.stringify(data)});
} else {
$.ajaxSetup({data: ''});
}
if (dataType !== undefined) {
$.ajaxSetup({dataType: dataType});
}
if (is_async !== undefined) {
$.ajaxSetup({async: is_async});
}
if (is_cache !== undefined) {
$.ajaxSetup({cache: is_cache});
}
$.ajax({
url: href,
contentType: 'application/json',
type: ajaxtype || 'get',
success: callback != null ? callback : function (result) {
if (result.code === 1) {
layer.msg(result.msg, {icon: 1, time: 1000}, function () {
let frameIndex = parent.layer.getFrameIndex(window.name);
if (frameIndex) {
parent.layer.close(frameIndex);//关闭当前页
}
table && parent.layui.table.reload(table);
});
} else {
layer.msg(result.msg, {icon: 2, time: 1000});
}
},
error: function (xhr) {
if (xhr.status === 401) {
layer.msg('权限不足,您无法访问受限资源或数据', {icon: 5});
return;
}
if (xhr.status === 404) {
layer.msg('请求url地址错误请确认后刷新重试', {icon: 5});
return;
}
if (xhr.status === 419) {
layer.msg('长时间未操作,自动刷新后重试!', {icon: 5});
setTimeout(function () {
window.location.reload();
}, 2000);
return;
}
if (xhr.status === 429) {
layer.msg('尝试次数太多,请一分钟后再试', {icon: 5});
return;
}
if (xhr.status === 500) {
layer.msg(xhr.responseJSON.message, {icon: 5});
}
}
, complete: function (xhr, status) {
}
})
}
}
exports(MOD_NAME, common);
});

View File

@ -0,0 +1,111 @@
/**
images压缩扩展模块
changlin_zhao@qq.com
2021.5.25
**/
layui.define(['upload','layer'],function(exports){
var upload = layui.upload;
var layer = layui.layer;
var compressImage = {
uploads: function(obj){
//obj.preview(function(index, file, result){
//执行实例
var files = obj.pushFile();
var filesArry = [];
for (var key in files) { //将上传的文件转为数组形式
filesArry.push(files[key])
}
var index = filesArry.length - 1;
var file = filesArry[index]; //获取最后选择的图片,即处理多选情况
if (navigator.appName == "Microsoft Internet Explorer" && parseInt(navigator.appVersion.split(";")[1]
.replace(/[ ]/g, "").replace("MSIE", "")) < 9) {
return obj.upload(index, file)
}
canvasDataURL(file, function (blob) {
var aafile = new File([blob], file.name, {
type: file.type
})
var isLt1M;
if (file.size < aafile.size) {
isLt1M = file.size
} else {
isLt1M = aafile.size
}
if (isLt1M / 1024 / 1024 > 2) {
return layer.alert('上传图片过大!')
} else {
if (file.size < aafile.size) {
return obj.upload(index, file)
}
obj.upload(index, aafile)
}
})
function canvasDataURL(file, callback) { //压缩转化为base64
var reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = function (e) {
const img = new Image()
const quality = 0.8 // 图像质量
const canvas = document.createElement('canvas')
const drawer = canvas.getContext('2d')
img.src = this.result
img.onload = function () {
var originWidth = img.width,/* 图片的宽度 */
originHeight = img.height; /* 图片的高度 */
// 设置最大尺寸限制将所有图片都压缩到小于1m
const maxWidth = 2560, maxHeight = 1600;
// 需要压缩的目标尺寸
let targetWidth = originWidth, targetHeight = originHeight;
// 等比例计算超过最大限制时缩放后的图片尺寸
if (originWidth > maxWidth || originHeight > maxHeight) {
if (originWidth / originHeight > 1) {
// 宽图片
targetWidth = maxWidth;
targetHeight = Math.round(maxWidth * (originHeight / originWidth));
} else {
// 高图片
targetHeight = maxHeight;
targetWidth = Math.round(maxHeight * (originWidth / originHeight));
}
}
canvas.width = targetWidth;
canvas.height = targetHeight;
drawer.drawImage(img, 0, 0, canvas.width, canvas.height)
convertBase64UrlToBlob(canvas.toDataURL(file.type, quality), callback);
}
}
}
function convertBase64UrlToBlob(urlData, callback) { //将base64转化为文件格式
const arr = urlData.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
callback(new Blob([u8arr], {
type: mime
}));
}
//})
}
}
//输出 imgcom 接口
exports('imgcom', compressImage);
});

View File

@ -137,4 +137,4 @@ layui.define(['table', 'jquery', 'element'], function (exports) {
}
exports(MOD_NAME, new message());
})
})

View File

@ -80,7 +80,7 @@ layui.define(['form', 'upload'], function(exports){
var field = data.field;
var URL = $(this).data('url');
$.post(URL, field,function(res){
if(res.code == 0){
if(res.code === 0){
layer.msg(res.msg,{icon:6,tiye:2000},function(){
location.reload();
});

View File

@ -9,43 +9,43 @@ layui.config({
base: rootPath + "module/",
version: "3.30.0"
}).extend({
admin: "admin", // 框架布局组件
common: "common", // 公共方法封装
menu: "menu", // 数据菜单组件
frame: "frame", // 内容页面组件
tab: "tab", // 多选项卡组件
echarts: "echarts", // 数据图表组件
echartsTheme: "echartsTheme", // 数据图表主题
encrypt: "encrypt", // 数据加密组件
select: "select", // 下拉多选组件
drawer: "drawer", // 抽屉弹层组件
notice: "notice", // 消息提示组件
step:"step", // 分布表单组件
tag:"tag", // 多标签页组件
popup:"popup", // 弹层封装
treetable:"treetable", // 树状表格
dtree:"dtree", // 树结构
tinymce:"tinymce/tinymce", // 编辑器
area:"area", // 省市级联
count:"count", // 数字滚动
topBar: "topBar", // 置顶组件
button: "button", // 加载按钮
design: "design", // 表单设计
card: "card", // 数据卡片组件
loading: "loading", // 加载组件
cropper:"cropper", // 裁剪组件
convert:"convert", // 数据转换
yaml:"yaml", // yaml 解析组件
context: "context", // 上下文组件
http: "http", // ajax请求组件
theme: "theme", // 主题转换
message: "message", // 通知组件
toast: "toast", // 消息通知
iconPicker: "iconPicker",// 图标选择
nprogress: "nprogress", // 进度过渡
watermark:"watermark/watermark", //水印
fullscreen:"fullscreen", //全屏组件
popover:"popover/popover" //汽泡组件
admin: "admin", // 框架布局组件
common: "common", // 公共方法封装
menu: "menu", // 数据菜单组件
frame: "frame", // 内容页面组件
tab: "tab", // 多选项卡组件
echarts: "echarts", // 数据图表组件
echartsTheme: "echartsTheme",// 数据图表主题
encrypt: "encrypt", // 数据加密组件
select: "select", // 下拉多选组件
drawer: "drawer", // 抽屉弹层组件
notice: "notice", // 消息提示组件
step:"step", // 分布表单组件
tag:"tag", // 多标签页组件
popup:"popup", // 弹层封装
treetable:"treetable", // 树状表格
dtree:"dtree", // 树结构
tinymce:"tinymce/tinymce", // 编辑器
area:"area", // 省市级联
count:"count", // 数字滚动
topBar: "topBar", // 置顶组件
button: "button", // 加载按钮
design: "design", // 表单设计
card: "card", // 数据卡片组件
loading: "loading", // 加载组件
cropper:"cropper", // 裁剪组件
convert:"convert", // 数据转换
yaml:"yaml", // yaml 解析组件
context: "context", // 上下文组件
http: "http", // 网络请求组件
theme: "theme", // 主题转换
message: "message", // 通知组件
toast: "toast", // 消息通知
iconPicker: "iconPicker", // 图标选择
nprogress: "nprogress", // 进度过渡
watermark:"watermark/watermark", //水印组件
fullscreen:"fullscreen", //全屏组件
popover:"popover/popover" //汽泡组件
}).use(['layer', 'theme'], function () {
layui.theme.changeTheme(window, false);
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 299 KiB

After

Width:  |  Height:  |  Size: 322 KiB

File diff suppressed because one or more lines are too long

View File

@ -1,14 +1,10 @@
/**
@Name: Fly社区
@Author: 贤心
@Site: fly.layui.com
*/

/* 全局 */
html,body{overflow-x: hidden;}
html body{margin-top: 61px;}
html{background-color: #F2F2F2;}
i{font-style: normal;}
h1,h2,h3 {font-weight: 400;}
/* 布局 */
.layui-mm{position: fixed; top: 100px; bottom: 0;}
@ -30,7 +26,7 @@ i{font-style: normal;}
.site-mobile .site-menu{left: 0;}
.site-mobile .site-mobile-shade-top{content: ''; position: fixed; top: 0; bottom: 0; left: 0; right: 0; background-color: rgba(0,0,0,.8); z-index: 999;}
.site-tree-mobile-top i{font-size: 30px;}
/* 底部伸缩菜单栏 */
.site-tree-mobile{display: block!important; position: fixed; z-index: 16666669; bottom: 15px; left: 15px; width: 30px; height: 30px; line-height: 30px; border-radius: 2px; text-align: center; background-color: #009688; color: #fff;}
.site-home .site-tree-mobile{display: none!important;}
@ -39,7 +35,7 @@ i{font-style: normal;}
.site-tree-mobile i{font-size: 20px;}
.site-mobile .layui-side{left: 0;}
.site-mobile .layui-side-child{top: 50%; left: 200px; height: 300px; margin-top: -100px;}
}
/* 图标 */
@ -185,9 +181,11 @@ pre{overflow-y: auto;
/* 头部 */
.fly-header{position: fixed; left: 0; top: 0; z-index: 10000; width: 100%; height: 60px; border-bottom: 1px solid #404553; border-right: 1px solid #404553; border-radius: 0;}
.fly-logo{position: absolute; left: 15px; top: 11px;}
.fly-logo-m{position: absolute; left:calc(50% - 45px); top: 11px;}
.fly-nav{margin-left: 200px;}
.fly-header .layui-container{position: relative; height: 100%; line-height: 60px; text-align: center;}
.fly-logo{position: absolute; left: 15px;}
.fly-logo img {width:135px; height: 37px;}
.fly-logo-m{width: 91px;}
.fly-nav{position: absolute; left: 200px;}
.fly-nav a i{position: absolute; left: 15px; top: 0; padding-right: 10px; font-size: 22px;}
.fly-nav a .icon-shouye, .nav a .icon-shezhi{top: 2px;}
@ -198,7 +196,7 @@ pre{overflow-y: auto;
.fly-nav-avatar .fly-badge-vip{position: relative; margin-left: 10px;}
.fly-nav-user .layui-nav-child a i{position: relative; top: 2px; margin-right: 10px; font-size: 26px;}
.fly-nav-msg{position:absolute; top: 50%; right: 5px; height: 20px; line-height: 20px; margin-top: -10px; padding:0 6px; background-color: #FF7200; color: #fff; border-radius: 2px;}
.fly-nav-msg{position:absolute; top: 10px; right: 1px; width:16px; height: 16px; line-height: 16px; background-color: #FF7200; color: #fff; font-size:12px; border-radius: 10px;}
.fly-nav-msg:hover{color:#fff;}
.fly-header .layui-nav{padding: 0; background: none;}
@ -212,19 +210,30 @@ pre{overflow-y: auto;
.fly-header .layui-nav .layui-nav-bar,
.fly-header .fly-nav-user .layui-nav-more{display: none !important;}
.fly-header .fly-nav-user .layui-nav-child{left: auto; right: 0; width: 120px; min-width: 0;}
/*
.fly-html-layui .fly-nav-avatar .layui-nav-more{display: none !important;}
.fly-header .fly-nav-user .layui-nav-child{left: auto; right: 0; width: 120px; min-width: 0;}
.fly-html-layui .fly-nav-msg{left: -30px;}
.fly-html-layui .layui-header .layui-nav-child dd{text-align: center;}
.fly-html-layui .layui-header .layui-nav-item a cite{padding: 0 0 0 10px;}
.fly-html-layui .layui-header .layui-nav .fly-layui-user{margin: 0; margin-left: 40px;}
.fly-html-layui .layui-header .layui-nav .fly-layui-user a{padding: 0;}
.fly-layui-user .layui-nav-child{left: auto; right: 0; min-width: 0; width: 120px;}
*/
/*第二排导航*/
.layui-nav.layui-bg-white {
background-color: #FFFFFF !important;
color: #2F363C !important;
}
.layui-nav.layui-bg-white li a {
height: 50px;
color: #0A0E11;
}
.layui-nav.layui-bg-white li a:hover {
color: #0A0E11;
}
.layui-nav.layui-bg-white .layui-this:after {
content: none !important;
}
.layui-nav.layui-bg-white .layui-nav-item {
height: 50px;
line-height: 50px;
text-align: center;
}
/* 搜索 */
.fly-search{display: inline-block; vertical-align: top; width: 50px; height: 50px; padding-top:20px;margin-right: 10px; text-align: center; cursor: pointer; font-size: 20px;}
.fly-search{display: inline-block; width: 50px; margin-right: 10px; cursor: pointer; font-size: 20px;}
.fly-search .layui-icon{font-size: 20px;}
.fly-search:hover{color: #5FB878;}
.fly-layer-search input{height: 75px; line-height: 75px; width: 500px; padding: 0 15px; font-size: 20px; border: none 0; background: none;}
@ -383,7 +392,7 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
.que-body .que-user-info .que-avatar i{position: absolute; left: 35px; top: 15px; }
.que-body .que-user-info span{display: inline-block; font-size: 12px; padding-left: 5px;}
/* 签到 */
/* 签到 */
.fly-signin cite{padding: 0 5px; color: #FF5722; font-style: normal;}
.fly-signin .layui-badge-dot{top: -7px; margin-left: 0px;}
.fly-signin-list{padding: 0; line-height: 30px;}
@ -462,7 +471,7 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
/*详情页管理工具条*/
.detail-assist{
position: fixed;
width: 35px;
width: 35px;
right: calc(50% - 625px);
top: 200px;
margin: 0 auto;
@ -516,7 +525,7 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
*/
.layui-form-pane{position:relative; width:100%;}
.que-comments{position:absolute;right:20px;bottom:5px;}
.que-comments{position:absolute; right:15px; bottom:15px;}
.wenda-user{height:200px; margin: 0,auto; text-align: center; pardding-top:20px;}
.wenda-user .user-img{posation:relative; width:100%;}
@ -529,7 +538,7 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
.detail-zan span{padding-right:5px; color:#999; cursor:pointer;}
.detail-zan span:hover{color:#666;}
.detail-zan span .icon-zan{font-size: 22px;}
.detail-zan span img{height: 25px; border-radius: 100%;}
.detail-zan span img{height: 25px; width:25px; border-radius: 100%; object-fit: cover;}
/* 详情页的底部操作条 */
@ -569,7 +578,7 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
.detail-about-reply .detail-hits{left: 0; bottom: 0;}
.detail-about-reply .fly-avatar{left: 0; top: 0;}
.jieda-body{margin: 25px 0 20px; min-height: 0; line-height: 24px; font-size:14px;}
.jieda-body{margin: 10px 0; min-height: 0; line-height: 24px; font-size:14px;}
.jieda-body p{margin-bottom: 10px;}
.jieda-body a{color:#4f99cf}
.jieda-reply{position:relative; font-size: 14px}
@ -591,6 +600,10 @@ body .fly-user-main{position: relative; min-height: 600px;}
.fly-user-main .fly-none{min-height: 0;}
.fly-panel-user[pad20]{padding-top: 5px;}
@media screen and (min-width: 768px) {
.fly-panel-user{height: calc(100vh - 280px)}
}
.fly-form-app{margin-top:30px;}
.fly-form-app .iconfont{font-size:26px; padding: 0 5px;}
.fly-form-app .icon-qq{color:#7CA9C9}
@ -673,7 +686,7 @@ body .fly-user-main{position: relative; min-height: 600px;}
.fly-case-tab .tab-this{background-color: #009688; color: #fff;}
.fly-case-list{margin-top: 15px; font-size: 0;}
.fly-case-list li,
.fly-case-list li,
.layer-ext-ul li{display: inline-block; vertical-align: middle; *display: inline; *zoom:1; font-size: 14px; background-color: #fff;}
.fly-case-list{width: 110%;}
.fly-case-list li{width: 239px; margin: 0 15px 15px 0; padding: 10px;}
@ -712,7 +725,7 @@ body .fly-user-main{position: relative; min-height: 600px;}
@media screen and (max-width: 768px) {
.fly-main{width: 100%;}
.fly-main{width: 100%;}
/* 顶边距 */
.fly-marginTop{margin-top: 0;}
@ -826,7 +839,7 @@ blockquote {
@media (max-width:767px) {.footer-col {margin-right:0}
}
@media (max-width:1239px) {
.footer-col-logo {display:none}
.footer-col-logo {display:none}
}
.footer-col-logo img {display:block;max-width:160px;max-height:60px;height:auto}
.footer-col-sns {float:right;margin-right:0}
@ -856,19 +869,19 @@ blockquote {
@media (min-width: 768px) {
.container {
width:750px;
width:750px;
}
}
@media (min-width: 992px) {
.container {
width:970px;
width:970px;
}
}
@media (min-width: 1200px) {
.container {
width:1170px;
width:1170px;
}
}
@ -882,4 +895,190 @@ blockquote {
/* 右下角固定栏*/
.layui-fixbar li {
border-radius:100%;
}
}
/*首页列表新增*/
.section {
display: block;
}
.list-grid.list-grid-padding .list-item {
padding: 1rem;
}
.list-grid .list-item {
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
}
.list-item {
position: relative;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
min-width: 0;
word-wrap: break-word;
}
.list-grid .list-item .media {
border-radius: inherit;
}
.media {
position: relative;
display: block;
overflow: hidden;
padding: 0;
-webkit-flex-shrink: 0;
-ms-flex-negative: 0;
flex-shrink: 0;
border-radius: inherit;
}
.media-content img{
width: 233px;
height: 155px;
border-radius: 5px;
object-fit: cover;
}
.d-none {
display: none !important;
}
.media {
display: -ms-flexbox;
display: flex;
-ms-flex-align: start;
align-items: flex-start;
}
.col-4 {
-ms-flex: 0 0 33.333333%;
flex: 0 0 33.333333%;
max-width: 33.333333%;
}
.card, .block {
background: #fff;
border-width: 0;
border-radius: 2px;
-webkit-box-shadow: 0 0 10px -2px rgba(158,158,158,.2);
box-shadow: 0 0 10px -2px rgba(158,158,158,.2);
}
.list-grid.list-grid-padding .list-content {
padding: 0 0 0 1rem;
}
.list-width {
width: 100%;
}
.list-content {
padding: 1rem 0;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
-webkit-box-flex: 1;
flex: 1 1 auto;
-webkit-box-pack: center;
justify-content: center;
min-width: 0;
}
.list-body {
-webkit-box-flex: 1;
flex: 1 1 auto;
}
.h-3x {
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
line-height: 1.7;
}
.text-secondary {
color: #5e646d !important;
}
.text-sm {
font-size: .875rem !important;
}
.text-secondary {
color: #6c757d !important;
}
.mb-3, .my-3 {
margin-bottom: 1rem !important;
}
.mt-3, .my-3 {
margin-top: 1rem !important;
}
@media (min-width: 768px) {
.d-md-block {
display: block !important;
}
}
figure {
margin: 0;
}
@media (min-width: 768px){
.ml-md-2, .mx-md-2 {
margin-left: .5rem !important;
}
}
@media (min-width: 768px){
.mr-md-2, .mx-md-2 {
margin-right: .5rem !important;
}
}
.ml-1, .mx-1 {
margin-left: .25rem !important;
}
.mr-1, .mx-1 {
margin-right: .25rem !important;
}
.d-inline-block {
display: inline-block !important;
}
.text-muted {
color: #9ca0ad !important;
}
.text-xs {
font-size: .75rem !important;
}
.text-muted {
color: #6c757d !important;
}
.align-items-center {
-ms-flex-align: center !important;
align-items: center !important;
}
.flex-fill {
-ms-flex: 1 1 auto !important;
flex: 1 1 auto !important;
}
.list-footer {
margin-top: .5rem;
}
.d-flex {
display: -ms-flexbox !important;
display: flex !important;
}
@media (min-width: 768px) and (max-width: 991.98px) {
.card, .block {margin-bottom: 1rem;}
}

View File

@ -0,0 +1,105 @@
/**
images压缩扩展模块
changlin_zhao@qq.com
2023.5.23
**/
layui.define(['upload','layer'],function(exports){
var layer = layui.layer;
var Compressor = {
upload: function (obj) {
// opthions = {
// width: option[0],
// height: option[1],
// quality: option[2]
// }
obj.preview(function(index, file, result){
canvasDataURL(result, {quality: 0.7}, function(base64Codes){
obj.upload(index, convertBase64UrlTo(base64Codes, file.name));
});
});
}
}
// 已知 base64
// canvasDataURL(base64, {quality: 0.7}, function(base64Codes){
// // base64Codes 为压缩后的
// // 其中 convertBase64UrlTo(base64Codes, file.name) 可返回 File 对象和 Blob
// obj.upload(index, convertBase64UrlTo(base64Codes, file.name));
// });
// 未知 base64
// imageCompress(file, {quality: 0.7}, function(base64Codes){
// // base64Codes 为压缩后的
// obj.upload(index, convertBase64UrlTo(base64Codes, file.name));
// });
/**
* 读取文件
* @param {file or Blob} file 上传文件
* @param {object} config 压缩配置 可配置压缩长宽质量等
* @param {function} callback
*/
function imageCompress(file, config, callback){
var ready = new FileReader();
ready.readAsDataURL(file);
ready.onload=function(){
canvasDataURL(this.result, config, callback)
}
}
/**
*
* @param {string} path
* @param {object} config -- {width: '', height: '', quality: 0.7}
* @param {function} callback
*/
function canvasDataURL(path, config, callback){
var img = new Image();
img.src = path;
img.onload = function(){
var that = this, quality = 0.7;
var w = that.width, h = that.height, scale = w / h;
w = config.width || w;
h = config.height || (w / scale);
//生成canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var anw = document.createAttribute("width");
anw.nodeValue = w;
var anh = document.createAttribute("height");
anh.nodeValue = h;
canvas.setAttributeNode(anw);
canvas.setAttributeNode(anh);
ctx.drawImage(that, 0, 0, w, h);
if(config.quality && config.quality <= 1 && config.quality > 0){
quality = config.quality;
}
callback(canvas.toDataURL('image/jpeg', quality));
}
}
/**
* 将图片 base64 转为 File 对象或者 Blob
* @param {*} urlData 图片 base64
* @param {*} filename 图片名 没有图片名将转为 Blob
*/
function convertBase64UrlTo(urlData, filename = null){
var base64Arr = urlData.split(','), mime = base64Arr[0].match(/:(.*?);/)[1],
bstr = atob(base64Arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return filename ? new File([u8arr], filename, {type:mime}) : new Blob([u8arr], {type:mime});
}
//输出 imagecut接口
exports('imagecut', Compressor);
});

View File

@ -696,42 +696,6 @@ layui.define(['layer', 'laytpl', 'form', 'element', 'upload', 'util', 'imgcom'],
//console.log(othis.attr('src'));
});
//头条轮播
if($('#FLY_topline')[0]){
layui.use('carousel', function(){
var carousel = layui.carousel;
var ins = carousel.render({
elem: '#FLY_topline'
,width: '100%'
,height: '172px'
,anim: 'fade'
});
var resizeTopline = function(){
var width = $(this).prop('innerWidth');
if(width >= 1200){
ins.reload({
height: '172px'
});
} else if(width >= 992){
ins.reload({
height: '141px'
});
} else if(width >= 768){
ins.reload({
height: '166px'
});
}
};
resizeTopline()
$(window).on('resize', resizeTopline);
});
}
//签到
//活跃榜

View File

@ -205,57 +205,58 @@ layui.define('fly', function(exports){
});
}
,edit: function(li){ //编辑评论
fly.json(commentGetDa, {
id: li.data('id')
}, function(res){
var data = res.rows;
layer.prompt({
formType: 2
,value: data.content
,maxlength: 100000
,title: '编辑回帖'
,area: ['738px', '310px']
,success: function(layero){
if(taonystatus == 0) {
if(taonystatus == 0) {
fly.layEditor({
elem: layero.find('textarea')
});
} else {
// 编辑器
fly.json(commentGetDa, {
id: li.data('id')
}, function (res) {
var data = res.rows;
layer.prompt({
formType: 2
, value: data.content
, maxlength: 100000
, title: '编辑回帖'
, area: ['738px', '310px']
, success: function (layero) {
fly.layEditor({
elem: layero.find('textarea')
});
}
}
}, function(value, index){
fly.json(commentUpdateDa, {
id: li.data('id')
,content: value
}, function(res){
layer.close(index);
layer.msg(res.msg);
li.find('.detail-body').html(fly.content(value));
}, function (value, index) {
fly.json(commentUpdateDa, {
id: li.data('id')
, content: value
}, function (res) {
layer.close(index);
layer.msg(res.msg);
li.find('.detail-body').html(fly.content(value));
});
});
});
});
}
}
,del: function(li){ //删除评论
layer.confirm('确认删除该回答么?', function(index){
layer.close(index);
fly.json(commentJiedaDelete, {
id: li.data('id')
}, function(res){
if(res.status === 0){
var count = dom.jiedaCount.text()|0;
dom.jiedaCount.html(--count);
li.remove();
//如果删除了最佳答案
if(li.hasClass('jieda-daan')){
$('.jie-status').removeClass('jie-status-ok').text('求解中');
,del: function(span){ //删除评论
if(taonystatus == 0) {
layer.confirm('确认删除该回答么?', function(index){
layer.close(index);
fly.json(commentJiedaDelete, {
id: li.data('id')
}, function(res){
if(res.status === 0){
var count = dom.jiedaCount.text()|0;
dom.jiedaCount.html(--count);
li.remove();
//如果删除了最佳答案
if(li.hasClass('jieda-daan')){
$('.jie-status').removeClass('jie-status-ok').text('求解中');
}
} else {
layer.msg(res.msg);
}
} else {
layer.msg(res.msg);
}
});
});
});
}
}
};

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More