Compare commits

...

11 Commits

Author SHA1 Message Date
taoser
fd06749715 修复数据库改前缀写入问题 2024-04-14 12:12:11 +08:00
taoser
06cc3caf77 修复热帖delete_time 2024-04-14 12:10:25 +08:00
taoser
a8943fa6aa 优化查询速度 2024-04-14 12:08:53 +08:00
taoser
fe2d08ca8e addons 2024-04-14 12:06:40 +08:00
taoser
27daa029f4 优化sql 2024-04-14 12:03:38 +08:00
taoser
91bd9d28c2 优化流量日志中间件 2024-04-01 10:24:38 +08:00
taoser
a5acd6cb6e 帖子相关 2024-04-01 10:22:13 +08:00
taoser
38ac88505b 优化模板 2024-04-01 10:20:25 +08:00
taoser
59db926938 新增插件管理插件系统 2024-04-01 10:17:53 +08:00
taoser
d9bd397475 修复登场错误锁定次数 2024-04-01 10:08:12 +08:00
taoser
d82f29fbe5 更新组件 2024-04-01 10:04:16 +08:00
358 changed files with 138985 additions and 6726 deletions

View File

@ -45,6 +45,13 @@ abstract class BaseController
*/
protected $middleware = [];
/**
* article content
*
* @var string
*/
protected $content = '';
/**
* 构造方法
* @access public
@ -202,16 +209,15 @@ abstract class BaseController
protected function getArticleAllpic($str)
{
//正则匹配<img src="http://img.com" />
$pattern = "/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.png]))[\'|\"].*?[\/]?>/";
$pattern = "/<[img|IMG].*?src=[\'|\"](.*?(?:[\.gif|\.jpg|\.png|\.jpeg]))[\'|\"].*?[\/]?>/";
preg_match_all($pattern,$str,$matchContent);
if(isset($matchContent[1])){
$img = $matchContent[1];
$imgArr = $matchContent[1];
}else{
$temp = "./images/no-image.jpg";//在相应位置放置一张命名为no-image的jpg图片
}
return $img;
return $imgArr;
}
//下载远程图片
@ -222,7 +228,7 @@ abstract class BaseController
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
$file = curl_exec($ch);
curl_close($ch);
return $this->saveAsImage($url, $file);
@ -234,9 +240,9 @@ abstract class BaseController
{
$filename = pathinfo($url, PATHINFO_BASENAME);
//$dirname = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_DIRNAME);
$dirname = date('Ymd',time());
//路径
$path = 'storage/download/article_pic/' . $dirname . '/';
$path = 'storage/download/article_pic/' . date('Ymd',time()) . '/';
//绝对文件夹
$fileDir = public_path() . $path;
//文件绝对路径
@ -266,23 +272,24 @@ abstract class BaseController
//下载网络图片到本地并替换
public function downUrlPicsReaplace($content)
{
$this->content = $content;
// 批量下载网络图片并替换
$images = $this->getArticleAllpic($content);
$images = $this->getArticleAllpic($this->content);
if(count($images)) {
foreach($images as $image){
//1.带http地址的图片2.非本站的网络图片 3.非带有?号等参数的图片
if((stripos($image,'http') !== false) && (stripos($image, Request::domain()) === false) && (stripos($image, '?') === false)) {
if((stripos($image,'http') !== false) && (stripos($image, Request::domain()) === false) && (stripos($image, '?') == false)) {
// 如果图片中没有带参数或者加密可下载
//下载远程图片(可下载)
$newImageUrl = $this->downloadImage($image);
//替换图片链接
$content = str_replace($image,Request::domain().$newImageUrl,$content);
$this->content = str_replace($image, Request::domain().$newImageUrl, $this->content);
}
}
//不可下载的图片如加密或者带有参数的图片如type=jpeg,直接返回content
}
return $content;
return $this->content;
}
/**

View File

@ -21,6 +21,7 @@ use app\admin\model\Cunsult;
use think\facade\Config;
use taoler\com\Api;
use app\common\lib\facade\HttpHelper;
use app\common\model\Comment;
class Index extends AdminController
{
@ -61,15 +62,28 @@ class Index extends AdminController
public function console2()
{
// 评论、帖子状态
$comm = Db::name('comment')->field('id')->where(['delete_time'=>0,'status'=>0])->select();
$comm = Db::name('comment')->field('id,content,create_time')->where(['delete_time'=>0,'status'=>0])->select();
$forum = Db::name('article')->field('id')->where(['delete_time'=>0,'status'=>0])->select();
$user = Db::name('user')->field('id')->where(['delete_time'=>0,'status'=>0])->select();
// 回复评论
$comments = Comment::field('id,article_id,content,create_time,delete_time')->where(['delete_time'=>0])->order('create_time desc')->limit(10)->select();
$commData = [];
foreach($comments as $v) {
$commData[] = [
'id' => $v->id,
'content' => strip_tags($v['content']),
'create_time' => $v['create_time'],
'url' => $this->getArticleUrl($v['article_id'], 'index', $v->article->cate->ename)
];
}
View::assign([
'pendComms' => count($comm),
'pendForums' => count($forum),
'pendUser' => count($user),
'comments' => $commData,
]);
return View::fetch('console2');
}

View File

@ -341,11 +341,11 @@ class Addons extends AdminController
{
$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])) {
@ -359,6 +359,9 @@ class Addons extends AdminController
$value = $params[$k];
$v['content'] = $value;
$v['value'] = $value;
} elseif ($v['type'] == 'select'){
$value = [(int)$params[$k]];
$v['value'] = $value;
} else {
$value = $params[$k];
}
@ -371,7 +374,7 @@ class Addons extends AdminController
}
return json(['code'=>0,'msg'=>'配置成功!']);
}
//halt($config);
//模板引擎初始化
$view = ['formData'=>$config,'title'=>'title'];
View::assign($view);

View File

@ -166,7 +166,29 @@ class Comment extends AdminController
return json(['code'=>0,'msg'=>'评论被禁止','icon'=>5]);
}
return json(['code'=>-1,'msg'=>'审核出错']);
}
/**
* 多选批量审核
*
* @return Json
*/
public function checkSelect()
{
$param = Request::param('data');
$data = [];
foreach($param as $v) {
$data[] = ['id' => (int)$v['id'], 'status' => $v['check'] == '1' ? '-1' : '1'];
}
//获取状态
$res = $this->model->saveAll($data);
if($res){
return json(['code'=>0,'msg'=>'审核成功','icon'=>6]);
}else {
return json(['code'=>-1,'msg'=>'失败啦','icon'=>6]);
}
}

View File

@ -87,7 +87,7 @@ class Forum extends AdminController
$where[] = ['title', 'like', '%'.$data['title'].'%'];
}
$list = $this->model->getList($where, input('limit'), input('page'));
$list = $this->model->getAllStatusList($where, input('limit'), input('page'));
$res = [];
if($list['total']){
foreach($list['data'] as $v) {
@ -277,6 +277,29 @@ class Forum extends AdminController
}
}
/**
* 多选批量审核
*
* @return Json
*/
public function checkSelect()
{
$param = Request::param('data');
$data = [];
foreach($param as $v) {
$data[] = ['id' => (int)$v['id'], 'status' => $v['check'] == '1' ? '-1' : '1'];
}
//获取状态
$res = $this->model->saveAll($data);
if($res){
return json(['code'=>0,'msg'=>'审核成功','icon'=>6]);
}else {
return json(['code'=>-1,'msg'=>'失败啦','icon'=>6]);
}
}
/**
* 上传接口
*

View File

@ -19,7 +19,6 @@ use app\common\lib\Uploads;
use app\common\validate\User as userValidate;
use think\exception\ValidateException;
class User extends AdminController
{
@ -39,40 +38,53 @@ class User extends AdminController
if(Request::isAjax()){
$datas = Request::only(['id','name','email','sex','status']);
$map = array_filter($datas,[$this,'filtrArr']);
if(!empty($map['id'])) {
$map['id'] = (int) $map['id'];
}
$user = Db::name('user')->where(['delete_time'=>0])->where($map)->order('id desc')->paginate([
'list_rows' => input('limit'),
'page' => input('page')
]);
$count = $user->total();
$res = [];
$data = [];
if($count){
$res = ['code'=>0,'msg'=>'ok','count'=>$count];
foreach($user as $k => $v){
$data = [
'id' => $v['id'],
'username' => $v['name'],
'nick' => $v['nickname'],
'avatar' => $v['user_img'],
'phone' => $v['phone'],
'email' => $v['email'],
'sex' => $v['sex'],
'ip' => $v['last_login_ip'],
'city' => $v['city'],
'logintime' => date("Y-m-d H:i",$v['last_login_time']),
'jointime' => date("Y-m-d",$v['create_time']),
'check' => $v['status'],
'auth' => $v['auth']
];
$res['data'][] = $data;
$vipList = [];
$vipRule = Db::name('user_viprule')->field('id,vip,nick')->select();
foreach($vipRule as $v) {
$vipList[] = ['id' => $v['id'], 'vip' => $v['vip'], 'title' => $v['nick']];
}
} else {
$res = ['code'=>-1,'msg'=>'没有查询结果!'];
foreach($user as $k => $v){
$data[] = [
'id' => $v['id'],
'username' => $v['name'],
'nick' => $v['nickname'],
'avatar' => $v['user_img'],
'phone' => $v['phone'],
'email' => $v['email'],
'sex' => $v['sex'],
'ip' => $v['last_login_ip'],
'city' => $v['city'],
'point' => $v['point'],
'logintime' => date("Y-m-d H:i:s",$v['last_login_time']),
'jointime' => date("Y-m-d H:i",$v['create_time']),
'check' => $v['status'],
'auth' => $v['auth'],
'vip' => $vipList[$v['vip']]['title']
];
}
return json(['code'=>0,'msg'=>'ok','count'=>$count, 'data' => $data, 'viplist' => $vipList]);
}
return json($res);
return json(['code'=>-1,'msg'=>'没有查询结果!']);
}
return View::fetch();
}
protected function getUserVipNick($vip) {
}
//添加用户
@ -204,5 +216,40 @@ class User extends AdminController
}
return true;
}
//登录用户中心
public function goUserHome() {
$id = (int)input('id');
$user_home_url = $this->getUserHome($id);
return redirect($user_home_url);
}
// 编辑用户积分
public function editPoint()
{
if(Request::isAjax()) {
$param = Request::param(['id','point']);
$res = Db::name('user')->where('id',(int)$param['id'])->update(['point' => (int)$param['point']]);
if($res > 0) {
return json(['code' => 0, 'msg' => '修改成功']);
}
return json(['code' => -1, 'msg' => '修改失败']);
}
}
// 编辑用户会员等级
public function editVipLevel()
{
if(Request::isAjax()) {
$param = Request::param(['id','vip']);
$vipRule = Db::name('user_viprule')->field('vip,nick')->where('nick', $param['vip'])->find();
$res = Db::name('user')->where('id',(int)$param['id'])->update(['vip' => (int)$vipRule['vip']]);
if($res > 0) {
return json(['code' => 0, 'msg' => '修改成功']);
}
return json(['code' => -1, 'msg' => '修改失败']);
}
}
}

View File

@ -29,22 +29,30 @@ class Vip extends AdminController
{
$keys = UserViprule::select();
$count = $keys->count();
$res = [];
$data = [];
if($count){
$res = ['code'=>0,'msg'=>'','count'=>$count];
foreach($keys as $k=>$v){
$res['data'][] = ['id'=>$v['id'],'score'=>$v['score'],'nick'=>$v['nick'],'vip'=>$v['vip'],'ctime'=>$v['create_time']];
}
} else {
$res = ['code'=>-1,'msg'=>'还没有任何vip等级设置'];
}
return json($res);
$data[] = [
'id'=>$v['id'],
'vip'=>$v['vip'],
'score'=>$v['score'],
'nick'=>$v['nick'],
'postnum'=>$v['postnum'],
'postpoint'=>$v['postpoint'],
'refreshnum'=>$v['refreshnum'],
'refreshpoint'=>$v['refreshpoint'],
'ctime'=>$v['create_time']
];
}
return json(['code'=>0,'msg'=>'ok','count'=>$count, 'data' => $data]);
}
return json(['code'=>-1,'msg'=>'还没有任何vip等级设置']);
}
//添加VIP积分规则
public function add()
{
$data = Request::only(['score','vip','nick']);
$data = Request::only(['score','vip','nick','postnum','refreshnum']);
$vip = UserViprule::where('vip',$data['vip'])->find();
if($vip){
$res = ['code'=>-1,'msg'=>'vip等级不能重复设置'];

View File

@ -4,5 +4,5 @@ return [
// 检测安装
\app\middleware\Install::class,
// 权限检测
app\middleware\Auth::class,
app\middleware\AdminAuth::class,
];

View File

@ -38,6 +38,9 @@
{{# } }}
{{# } }}
</script>
<script type="text/html" id="ver-tpl">
<div>{{d.version}} {{# if(d.have_newversion == 1) { }} <span class="layui-badge-dot"></span> {{# } }}</div>
</script>
<script type="text/html" id="buttonStatus">
<input type="checkbox" name="{{d.name}}" lay-skin="switch" lay-filter="addonsStatus" lay-text="启动|禁用" {{# if(d.status == 1){ }} checked {{# } }} data-url="{:url('addon.addons/check')}">
@ -51,7 +54,7 @@
{include file="public/user_login" /}
<script src="/static/component/layui/layui.js"></script>
<script src="/static/component/pear/pear.js"></script>
<script src="/static/component/pear/pear.js"></script>
<script>
var addonList = "{:url('addon.addons/getList')}";
@ -65,7 +68,7 @@
var toast = layui.toast;
let LIST_URL = "{:url('addon.addons/list')}";
let cols = [[
{type: 'checkbox'},
{title: '序号', type: 'numbers'},
@ -74,7 +77,7 @@
{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: 'version', title: '版本', templet: '#ver-tpl', width: 75},
{field: 'status', title: '在线', width: 70},
{title: '操作', width: 165, align: 'center', toolbar: '#addons-bar'}
]];

View File

@ -5,74 +5,77 @@
<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-inline layuiadmin-input-useradmin">
<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 class="layui-inline">
<label class="layui-form-label">内容</label>
<div class="layui-input-block">
<input type="text" name="content" placeholder="请输入" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">状态</label>
<div class="layui-input-block">
<select name="status" lay-filter="fourm-check">
<option value="">全部</option>
<option value="0">待审</option>
<option value="-1">禁止</option>
<option value="1">通过</option>
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="comment-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>
</div>
<div class="layui-card">
<div class="layui-card-body">
<table id="comment-table" lay-filter="comment-table"></table>
</div>
</div>
<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-inline layuiadmin-input-useradmin">
<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 class="layui-inline">
<label class="layui-form-label">内容</label>
<div class="layui-input-block">
<input type="text" name="content" placeholder="请输入" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">状态</label>
<div class="layui-input-block">
<select name="status" lay-filter="fourm-check">
<option value="">全部</option>
<option value="0">待审</option>
<option value="-1">禁止</option>
<option value="1">通过</option>
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<button class="pear-btn pear-btn-md pear-btn-primary" lay-submit lay-filter="comment-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>
</div>
<div class="layui-card">
<div class="layui-card-body">
<table id="comment-table" lay-filter="comment-table"></table>
</div>
</div>
<script type="text/html" id="comment-toolbar">
<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="comment-toolbar">
<button class="pear-btn pear-btn-danger pear-btn-md" lay-event="batchRemove">
<i class="layui-icon layui-icon-delete"></i>
删除
</button>
<button class="pear-btn layui-bg-orange pear-btn-md" lay-event="checkSelect">
批量审核
</button>
</script>
<script type="text/html" id="imgTpl">
<img style="width: 25px; height: 25px;" src= {{ d.avatar }}>
</script>
<script type="text/html" id="buttonCheck">
<input type="checkbox" name="check" lay-skin="switch" lay-filter="check" lay-text="通过|{{ d.check == 0 ? '待审' : '禁止' }}" {{ d.check == 1 ? 'checked' : '' }} id="{{d.id}}" >
<script type="text/html" id="imgTpl">
<img style="width: 25px; height: 25px;" src= {{ d.avatar }}>
</script>
<script type="text/html" id="buttonCheck">
<input type="checkbox" name="check" lay-skin="switch" lay-filter="check" lay-text="通过|{{ d.check == 0 ? '待审' : '禁止' }}" {{ d.check == 1 ? 'checked' : '' }} id="{{d.id}}" >
</script>
</script>
<script type="text/html" id="comment-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>
<script type="text/html" id="comment-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>
</div>
@ -125,7 +128,9 @@
window.refresh();
} else if (obj.event === 'batchRemove') {
window.batchRemove(obj);
}
} else if (obj.event === 'checkSelect') {
window.checkSelect(obj);
}
});
form.on('submit(comment-query)', function(data) {
@ -246,6 +251,53 @@
});
}
// 全选审核
window.checkSelect = function(obj) {
var id = obj.config.id;
var checkStatus = table.checkStatus(id);
var data = checkStatus.data;
if (data.length === 0) {
layer.msg("未选中数据", {
icon: 3,
time: 1000
});
return false;
}
layer.confirm('确定要审核?', {
icon: 3,
title: '提示'
}, function(index) {
layer.close(index);
let loading = layer.load();
console.log(data)
$.ajax({
type: "post",
url: "{:url('content.comment/checkSelect')}",
dataType: 'json',
data: {data},
success: function(result) {
layer.close(loading);
if (result.code === 0) {
layer.msg(result.msg, {
icon: 1,
time: 1000
}, function() {
table.reload('comment-table');
});
} else {
layer.msg(result.msg, {
icon: 2,
time: 1000
});
}
}
})
});
}
window.refresh = function(param) {
table.reload('comment-table');
}

View File

@ -113,7 +113,7 @@
show: true,
indent: 15,
strict: false,
expandedKeys: true
expandedKeys: false
},
tips: '请选择'
});
@ -203,6 +203,8 @@
});
</script>
{// 编辑器}
{:hook('ueditor')}
{:hook('taonyeditor')}
{// 百度标题词条}
{:hook('seoBaiduTitle')}

View File

@ -154,7 +154,7 @@
show: true,
indent: 15,
strict: false,
expandedKeys: true
expandedKeys: false
},
tips: '请选择'
});
@ -222,6 +222,8 @@
});
</script>
{// 编辑器}
{:hook('ueditor')}
{:hook('taonyeditor')}
{// 百度标题词条}
{:hook('seoBaiduTitle')}

View File

@ -5,358 +5,392 @@
<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-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 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 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 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 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>
</div>
<div class="layui-card">
<div class="layui-card-body">
<table id="forum-table" lay-filter="forum-table" ></table>
</div>
</div>
<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 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 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 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 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>
</div>
<div class="layui-card">
<div class="layui-card-body">
<table id="forum-table" lay-filter="forum-table" ></table>
</div>
</div>
<script type="text/html" id="forum-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="forum-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>
<button class="pear-btn layui-bg-orange pear-btn-md" lay-event="checkSelect">
批量审核
</button>
</script>
<script type="text/html" id="avatarTpl">
<div><img style="width: 25px; height: 25px;" src= "{{ d.avatar }}"></div>
</script>
<script type="text/html" id="forum-istop">
<input type="checkbox" name="is_top" value="{{d.id}}" lay-skin="switch" lay-text="是|否" lay-filter="isTop" {{ d.top == 1 ? 'checked' : '' }}>
</script>
<script type="text/html" id="buttonHot">
<input type="checkbox" name="is_hot" value="{{d.id}}" lay-skin="switch" lay-text="是|否" lay-filter="isHot" {{ d.hot == 1 ? 'checked' : '' }}>
</script>
<script type="text/html" id="buttonReply">
<input type="checkbox" name="is_reply" value="{{d.id}}" lay-skin="switch" lay-text="是|否" lay-filter="isReply" {{ d.reply == 0 ? 'checked' : '' }}>
</script>
<script type="text/html" id="buttonCheck">
<input type="checkbox" name="status" value="{{d.id}}" lay-skin="switch" lay-filter="artStatus" lay-text="通过|{{ d.check == 0 ? '待审' : '禁止' }}" {{ d.check == 1 ? 'checked' : '' }}>
</script>
<script type="text/html" id="avatarTpl">
<div><img style="width: 25px; height: 25px;" src= "{{ d.avatar }}"></div>
</script>
<script type="text/html" id="forum-istop">
<input type="checkbox" name="is_top" value="{{d.id}}" lay-skin="switch" lay-text="是|否" lay-filter="isTop" {{ d.top == 1 ? 'checked' : '' }}>
</script>
<script type="text/html" id="buttonHot">
<input type="checkbox" name="is_hot" value="{{d.id}}" lay-skin="switch" lay-text="是|否" lay-filter="isHot" {{ d.hot == 1 ? 'checked' : '' }}>
</script>
<script type="text/html" id="buttonReply">
<input type="checkbox" name="is_reply" value="{{d.id}}" lay-skin="switch" lay-text="是|否" lay-filter="isReply" {{ d.reply == 0 ? 'checked' : '' }}>
</script>
<script type="text/html" id="buttonCheck">
<input type="checkbox" name="status" value="{{d.id}}" lay-skin="switch" lay-filter="artStatus" lay-text="通过|{{ d.check == 0 ? '待审' : '禁止' }}" {{ d.check == 1 ? 'checked' : '' }}>
</script>
<script type="text/html" id="forum-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>
<script type="text/html" id="forum-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>
<script src="/static/component/layui/layui.js"></script>
<script src="/static/component/pear/pear.js"></script>
<script src="/static/component/layui/layui.js"></script>
<script src="/static/component/pear/pear.js"></script>
<script>
const FORUM_List = "{:url('content.forum/list')}";
<script>
const FORUM_List = "{:url('content.forum/list')}";
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;
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')}";
// 编辑器插件启用状态
var isShow = taonystatus ? false : true;
let cols = [
[
{type: 'checkbox'}
,{field: 'id', width: 60, title: 'ID', sort: true}
,{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'}
,{field: 'hot', title: '加精', templet: '#buttonHot', width: 80, align: 'center'}
,{field: 'reply', title: '禁评', templet: '#buttonReply', width: 80, align: 'center'}
,{field: 'check', title: '审帖', templet: '#buttonCheck', width: 95, align: 'center'}
,{title: '操作', width: 110, align: 'center', toolbar: '#forum-table-bar'}
]
];
table.render({
elem: '#forum-table',
url: FORUM_List,
page: true,
cols: cols,
skin: 'line',
toolbar: '#forum-toolbar',
defaultToolbar: [{
title: '刷新',
layEvent: 'refresh',
icon: 'layui-icon-refresh',
}, 'filter', 'print', 'exports']
});
let cols = [
[
{type: 'checkbox'}
,{field: 'id', width: 60, title: 'ID', sort: true}
,{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'}
,{field: 'hot', title: '加精', templet: '#buttonHot', width: 80, align: 'center'}
,{field: 'reply', title: '禁评', templet: '#buttonReply', width: 80, align: 'center'}
,{field: 'check', title: '审帖', templet: '#buttonCheck', width: 95, align: 'center'}
,{title: '操作', width: 110, align: 'center', toolbar: '#forum-table-bar'}
]
];
// 动态分类
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: '请选择'
});
});
}
table.render({
elem: '#forum-table',
url: FORUM_List,
page: true,
cols: cols,
skin: 'line',
toolbar: '#forum-toolbar',
defaultToolbar: [{
title: '刷新',
layEvent: 'refresh',
icon: 'layui-icon-refresh',
}, 'filter', 'print', 'exports']
});
getSelectCate();
// 动态分类
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);
} else if (obj.event === 'edit') {
window.edit(obj);
}
});
table.on('tool(forum-table)', function(obj) {
if (obj.event === 'remove') {
window.remove(obj);
} else if (obj.event === 'edit') {
window.edit(obj);
}
});
table.on('toolbar(forum-table)', function(obj) {
if (obj.event === 'add') {
window.add();
} else if (obj.event === 'refresh') {
window.refresh();
} else if (obj.event === 'batchRemove') {
window.batchRemove(obj);
} else if (obj.event === 'checkSelect') {
window.checkSelect(obj);
}
});
table.on('toolbar(forum-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(forum-query)', function(data) {
table.reload('forum-table', {
where: data.field,
page: {
curr: 1 //重新从第 1 页开始
}
})
return false;
});
form.on('submit(forum-query)', function(data) {
table.reload('forum-table', {
where: data.field,
page: {
curr: 1 //重新从第 1 页开始
}
})
return false;
});
// 监听置顶
form.on('switch(isTop)', function(obj){
$.post("{:url('content.forum/check')}",{id:obj.value, name:obj.elem.name,value:obj.elem.checked ? 1 : 0},function(res){
layer.tips(obj.value + ' ' + obj.elem.name + ''+ obj.elem.checked, obj.othis);
});
});
// 监听置顶
form.on('switch(isTop)', function(obj){
$.post("{:url('content.forum/check')}",{id:obj.value, name:obj.elem.name,value:obj.elem.checked ? 1 : 0},function(res){
layer.tips(obj.value + ' ' + obj.elem.name + ''+ obj.elem.checked, obj.othis);
});
});
// 监听加精
form.on('switch(isHot)', function(obj){
$.post("{:url('content.forum/check')}",{id:obj.value, name:obj.elem.name,value: obj.elem.checked ? 1 : 0},function(res){
layer.tips(obj.value + ' ' + obj.elem.name + ''+ obj.elem.checked, obj.othis);
});
});
// 监听加精
form.on('switch(isHot)', function(obj){
$.post("{:url('content.forum/check')}",{id:obj.value, name:obj.elem.name,value: obj.elem.checked ? 1 : 0},function(res){
layer.tips(obj.value + ' ' + obj.elem.name + ''+ obj.elem.checked, obj.othis);
});
});
// 监听回复
form.on('switch(isReply)', function(obj){
$.post("{:url('content.forum/check')}",{id:obj.value, name:obj.elem.name,value: obj.elem.checked ? 0 : 1},function(res){
layer.tips(obj.value + ' ' + obj.elem.name + ''+ obj.elem.checked, obj.othis);
});
});
// 监听回复
form.on('switch(isReply)', function(obj){
$.post("{:url('content.forum/check')}",{id:obj.value, name:obj.elem.name,value: obj.elem.checked ? 0 : 1},function(res){
layer.tips(obj.value + ' ' + obj.elem.name + ''+ obj.elem.checked, obj.othis);
});
});
// 监听审贴
form.on('switch(artStatus)', function(obj){
//layer.tips(obj.value + ' ' + obj.elem.name + ''+ obj.elem.checked, obj.othis);
$.post("{:url('content.forum/check')}",{id:obj.value, name:obj.elem.name,value: obj.elem.checked ? 1 : -1},function(res){
if(res.code === 0){
layer.msg(res.msg,{icon:res.icon,time:2000})
} else {
layer.open({title:'审核失败',content:res.msg,icon:5,adim:6})
}
});
});
// 监听审贴
form.on('switch(artStatus)', function(obj){
//layer.tips(obj.value + ' ' + obj.elem.name + ''+ obj.elem.checked, obj.othis);
$.post("{:url('content.forum/check')}",{id:obj.value, name:obj.elem.name,value: obj.elem.checked ? 1 : -1},function(res){
if(res.code === 0){
layer.msg(res.msg,{icon:res.icon,time:2000})
} else {
layer.open({title:'审核失败',content:res.msg,icon:5,adim:6})
}
});
});
// 添加
window.add = function() {
layer.open({
type: 2,
title: '新增',
shade: 0.1,
area: [common.isModile()?'100%':'100%', common.isModile()?'100%':'100%'],
content: 'add.html'
});
}
window.add = function() {
if(isShow) {
toast.info({title: '信息',message: '编辑器插件未开启或未安装',position: 'topRight'});
return false;
}
layer.open({
type: 2,
title: '新增',
shade: 0.1,
area: [common.isModile()?'100%':'100%', common.isModile()?'100%':'100%'],
content: 'add.html'
});
}
window.edit = function(obj) {
layer.open({
type: 2,
title: '修改',
shade: 0.1,
area: ['100%', '100%'],
content: 'edit.html?id=' + obj.data.id
});
}
window.edit = function(obj) {
if(isShow) {
toast.info({title: '信息',message: '编辑器插件未开启或未安装',position: 'topRight'});
return false;
}
layer.open({
type: 2,
title: '修改',
shade: 0.1,
area: ['100%', '100%'],
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.forum/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
});
}
}
})
});
}
// $(document).on('focusin', function(e) {
// if ($(e.target).closest(".tox-tinymce, .tox-tinymce-aux, .moxman-window, .tam-assetmanager-root").length) {
// e.stopImmediatePropagation();
// }
// });
// 批量删除
window.batchRemove = function(obj) {
var checkIds = common.checkField(obj,'id');
if (checkIds === "") {
layer.msg("未选中数据", {
icon: 3,
time: 1000
});
return false;
}
window.remove = function(obj) {
layer.confirm('确定要删除?', {
icon: 3,
title: '提示'
}, function(index) {
layer.close(index);
let loading = layer.load();
$.ajax({
url: "{:url('content.forum/delete')}?id=" + checkIds,
dataType: 'json',
type: 'delete',
data:{"id":checkIds},
success: function(result) {
layer.close(loading);
if (result.code === 0) {
layer.msg(result.msg, {
icon: 1,
time: 1000
}, function() {
table.reload('forum-table');
});
} else {
layer.msg(result.msg, {
icon: 2,
time: 1000
});
}
}
})
});
}
layer.confirm('确定要删除?', {
icon: 3,
title: '提示'
}, function(index) {
layer.close(index);
let loading = layer.load();
$.ajax({
url: "{:url('content.forum/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.checkSelect = function(obj) {
var id = obj.config.id;
var checkStatus = table.checkStatus(id);
var data = checkStatus.data;
window.batchRemove = function(obj) {
var checkIds = common.checkField(obj,'id');
if (checkIds === "") {
layer.msg("未选中数据", {
icon: 3,
time: 1000
});
return false;
}
if (data.length === 0) {
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.forum/delete')}?id=" + checkIds,
dataType: 'json',
type: 'delete',
data:{"id":checkIds},
success: function(result) {
layer.close(loading);
if (result.code === 0) {
layer.msg(result.msg, {
icon: 1,
time: 1000
}, function() {
table.reload('forum-table');
});
} else {
layer.msg(result.msg, {
icon: 2,
time: 1000
});
}
}
})
});
}
layer.confirm('确定要审核?', {
icon: 3,
title: '提示'
}, function(index) {
layer.close(index);
let loading = layer.load();
console.log(data)
$.ajax({
type: "post",
url: "{:url('content.forum/checkSelect')}",
dataType: 'json',
data: {data},
success: function(result) {
layer.close(loading);
if (result.code === 0) {
layer.msg(result.msg, {
icon: 1,
time: 1000
}, function() {
table.reload('forum-table');
});
} else {
layer.msg(result.msg, {
icon: 2,
time: 1000
});
}
}
})
});
}
window.refresh = function(param) {
table.reload('forum-table');
}
// 刷新
window.refresh = function(param) {
table.reload('forum-table');
}
});
</script>
</body>
});
</script>
</body>
</html>

View File

@ -327,7 +327,7 @@
const v = layui.v;
layui.use(['form','layer', 'echarts', 'element', 'count','toast'], function() {
layui.use(['form','layer', 'echarts', 'carousel', 'element', 'count','toast'], function() {
let $ = layui.jquery, form = layui.form,
layer = layui.layer,
element = layui.element,
@ -335,37 +335,37 @@
echarts = layui.echarts;
let toast = layui.toast;
let table = layui.table;
let carousel = layui.carousel;
$('.UI').append(v);
count.up("value1", {
time: 4000,
num: {:hook('seoBaiduTongji',['name'=>'tpv']) ?: 0},
bit: 0,
regulator: 50
})
bit: 0,
regulator: 50
})
count.up("value2", {
time: 4000,
num: {:hook('seoBaiduTongji',['name'=>'tuv']) ?: 0},
bit: 0,
regulator: 50
})
bit: 0,
regulator: 50
})
count.up("value3", {
time: 4000,
num: {:hook('seoBaiduTongji',['name'=>'tip']) ?: 0},
bit: 0,
regulator: 50
})
bit: 0,
regulator: 50
})
count.up("value4", {
time: 4000,
bit: 2,
num: {:hook('seoBaiduTongji',['name'=>'tvt']) ?: 0},
regulator: 50
})
regulator: 50
})
var echartsRecords = echarts.init(document.getElementById('echarts-records'), 'walden');
@ -610,20 +610,20 @@
$.get("{:url('system.upgrade/check')}",function (data){
if (data.code === 1) {
//可升级
layer.confirm('发现新版本V' + data.data.version + ',确定升级?',{icon: 3, title:'系统检测'}, function(index){
layer.confirm('发现新版本V' + data.data.version + ',确定升级?', {icon: 3, title:'系统检测'}, function(index){
var loadIndex = layer.load(0);
//更新
$.get("{:url('system.upgrade/upload')}",function (res){
layer.close(loadIndex)
if (res.code === 0) {
layer.close(index);
toast.info({title:"通知消息", message: res.msg ,position: 'topRight'})
} else {
layer.close(index);
toast.error({title:"服务器错误", message:res.msg})
}
return false;
});
//关闭load加载层
layer.close(index);
});
}
});
});

View File

@ -129,14 +129,14 @@
</div>
</div>
</div>
<div class="layui-card">
<!-- <div class="layui-card">
<div class="layui-card-header">
使用记录
</div>
<div class="layui-card-body">
<table id="role-table" lay-filter="role-table"></table>
</div>
</div>
</div> -->
</div>
</div>
</div>
@ -145,81 +145,13 @@
<div class="layui-card-header">留言板</div>
<div class="layui-card-body">
<ul class="pear-card-status">
{volist name="comments" id="vo"}
<li>
<p>要不要作为我的家人,搬来我家。</p>
<span>12月25日 19:92</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
<li>
<p>快乐的时候不敢尽兴,频繁警戒自己保持清醒。</p>
<span>4月30日 22:43</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
<li>
<p>夏天真的来了,尽管它还有些犹豫。</p>
<span>4月30日 22:43</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
<li>
<p>看似不可达到的高度,只要坚持不懈就可能到达。</p>
<span>4月30日 22:43</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
<li>
<p>当浑浊变成了一种常态,那么清白就成了一种罪过。</p>
<span>4月30日 22:43</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
<li>
<p>那是一种内在的东西,他们到达不了,也无法触及!</p>
<span>5月12日 01:25</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
</li>
<li>
<p>希望是一个好东西,也许是最好的,好东西是不会消亡的!</p>
<span>6月11日 15:33</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
<li>
<p>一切都在不可避免的走向庸俗。</p>
<span>2月09日 13:40</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
<li>
<p>路上没有灯火的时候,就点亮自己的头颅。</p>
<span>3月11日 12:30</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
<li>
<p>我们应该不虚度一生,应该能够说:"我已经做了我能做的事。"</p>
<span>4月30日 22:43</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
</li>
<li>
<p>接近,是我对一切的态度,是我对一切态度的距离</p>
<span>6月11日 15:33</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
<li>
<p>没有锚的船当然也可以航行,只是紧张充满你的一生。</p>
<span>2月09日 13:40</span>
<a href="javascript:;" data-id="1"
class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
<p>{$vo.content|raw}</p>
<span>{$vo.create_time}</span>
<a href="{$vo.url}" data-id="{$vo.id}" target="_blank" class="pear-btn pear-btn-primary pear-btn-xs pear-reply">回复</a>
</li>
{/volist}
</ul>
</div>
</div>

View File

@ -12,6 +12,7 @@
<meta charset="utf-8">
<title>{block name="title"}TaoLerCMS后台管理系统{/block}</title>
<link rel="stylesheet" href="/static/component/pear/css/pear.css" />
{block name="head"}内容{/block}
</head>
<body class="pear-container">
{block name="body"}内容{/block}

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>{block name="title"}TaoLerCMS后台管理系统{/block}</title>
<link rel="stylesheet" href="/static/component/pear/css/pear.css" />
{block name="link"}{/block}
</head>
<body>
{block name="body"}内容{/block}

View File

@ -29,21 +29,16 @@
归档
</div>
<div class="layui-card-body">
<ul class="list">
<!-- <ul class="list">
<li class="list-item"><span class="title">优化代码格式</span><span class="footer">2020-06-04 11:28</span></li>
<li class="list-item"><span class="title">新增消息组件</span><span class="footer">2020-06-01 04:23</span></li>
<li class="list-item"><span class="title">移动端兼容</span><span class="footer">2020-05-22 21:38</span></li>
<li class="list-item"><span class="title">系统布局优化</span><span class="footer">2020-05-15 14:26</span></li>
<li class="list-item"><span class="title">兼容多系统菜单模式</span><span class="footer">2020-05-13 16:32</span></li>
<li class="list-item"><span class="title">兼容多标签页切换</span><span class="footer">2019-12-9 14:58</span></li>
<li class="list-item"><span class="title">扩展下拉组件</span><span class="footer">2019-12-7 9:06</span></li>
<li class="list-item"><span class="title">扩展卡片样式</span><span class="footer">2019-12-1 10:26</span></li>
</ul>
</ul> -->
</div>
</div>
</div>
<div class="layui-col-md9">
<div class="layui-card">
<!-- <div class="layui-card">
<div class="layui-card-header">
我的文章
</div>
@ -51,6 +46,7 @@
<div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief">
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<div class="layui-row layui-col-space10" style="margin: 15px;">
<div class="layui-col-md1">
<img src="/static/admin/images/act.jpg" style="width: 100%;height: 100%;border-radius: 5px;" />
@ -63,83 +59,13 @@
<div class="comment">2020-06-12 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 评论 5 点赞 12 转发 4</div>
</div>
</div>
<div class="layui-row layui-col-space10" style="margin: 15px;">
<div class="layui-col-md1">
<img src="/static/admin/images/act.jpg" style="width: 100%;height: 100%;border-radius: 5px;" />
</div>
<div class="layui-col-md11" style="height: 80px;">
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习</div>
<div class="content">
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处在于理解了Git的精髓。”来一句我们程序员们接地气的话分享是一种快乐~
</div>
<div class="comment">2020-06-12 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 评论 5 点赞 12 转发 4</div>
</div>
</div>
<div class="layui-row layui-col-space10" style="margin: 15px;">
<div class="layui-col-md1">
<img src="/static/admin/images/act.jpg" style="width: 100%;height: 100%;border-radius: 5px;" />
</div>
<div class="layui-col-md11" style="height: 80px;">
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习</div>
<div class="content">
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处在于理解了Git的精髓。”来一句我们程序员们接地气的话分享是一种快乐~
</div>
<div class="comment">2020-06-12 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 评论 5 点赞 12 转发 4</div>
</div>
</div>
<div class="layui-row layui-col-space10" style="margin: 15px;">
<div class="layui-col-md1">
<img src="/static/admin/images/act.jpg" style="width: 100%;height: 100%;border-radius: 5px;" />
</div>
<div class="layui-col-md11" style="height: 80px;">
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习</div>
<div class="content">
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处在于理解了Git的精髓。”来一句我们程序员们接地气的话分享是一种快乐~
</div>
<div class="comment">2020-06-12 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 评论 5 点赞 12 转发 4</div>
</div>
</div>
<div class="layui-row layui-col-space10" style="margin: 15px;">
<div class="layui-col-md1">
<img src="/static/admin/images/act.jpg" style="width: 100%;height: 100%;border-radius: 5px;" />
</div>
<div class="layui-col-md11" style="height: 80px;">
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习</div>
<div class="content">
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处在于理解了Git的精髓。”来一句我们程序员们接地气的话分享是一种快乐~
</div>
<div class="comment">2020-06-12 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 评论 5 点赞 12 转发 4</div>
</div>
</div>
<div class="layui-row layui-col-space10" style="margin: 15px;">
<div class="layui-col-md1">
<img src="/static/admin/images/act.jpg" style="width: 100%;height: 100%;border-radius: 5px;" />
</div>
<div class="layui-col-md11" style="height: 80px;">
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习</div>
<div class="content">
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处在于理解了Git的精髓。”来一句我们程序员们接地气的话分享是一种快乐~
</div>
<div class="comment">2020-06-12 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 评论 5 点赞 12 转发 4</div>
</div>
</div>
<div class="layui-row layui-col-space10" style="margin: 15px;">
<div class="layui-col-md1">
<img src="/static/admin/images/act.jpg" style="width: 100%;height: 100%;border-radius: 5px;" />
</div>
<div class="layui-col-md11" style="height: 80px;">
<div class="title">为什么程序员们愿意在GitHub上开源自己的成果给别人免费使用和学习</div>
<div class="content">
“Git的精髓在于让所有人的贡献无缝合并。而GitHub的天才之处在于理解了Git的精髓。”来一句我们程序员们接地气的话分享是一种快乐~
</div>
<div class="comment">2020-06-12 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 评论 5 点赞 12 转发 4</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div> -->
</div>
</div>
<script src="/static/component/layui/layui.js"></script>

View File

@ -23,21 +23,21 @@
<label class="layui-form-label">邮箱</label>
<div class="layui-input-block">
<input type="text" name="email" value="{$user.email}" lay-verify="title"
autocomplete="off" placeholder="请输入标题" class="layui-input">
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="password" value="" lay-verify="title" autocomplete="off"
placeholder="请输入标题" class="layui-input">
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" value="{$user.phone}" lay-verify="title" autocomplete="off"
placeholder="请输入标题" class="layui-input">
placeholder="请输入电话" class="layui-input">
</div>
</div>
<div class="layui-form-item">

View File

@ -63,6 +63,7 @@
</form>
</div>
</div>
<div class="layui-card">
<div class="layui-card-body">
<table id="user-table" lay-filter="user-table"></table>
@ -80,7 +81,15 @@
</button>
</script>
<script type="text/html" id="imgTpl">
<img src= {{=d.avatar}} style="width: 30px; height: 30px;" />
<a href="{:url('user.user/goUserHome')}?id={{ d.id }}" target="_blank"><img src= {{=d.avatar}} style="width: 100px; height: 100px; border-radius: 6px; object-fit: cover;"/></a>
</script>
<script type="text/html" id="userInfoTpl">
<ul>
<li>ID: {{d.id}} 用户名:{{d.username }}</li>
<li>性别:{{#if (d.sex == 0) { }} <span></span> {{# }else if(d.sex == 1){ }} <span></span> {{# } }} 昵称:{{d.nickname}}</li>
<li>电话:{{d.phone}}</li>
<li>邮箱:{{d.email}}</li>
</ul>
</script>
<script type="text/html" id="user-bar">
<button class="pear-btn pear-btn-primary pear-btn-sm" lay-event="edit"><i class="layui-icon layui-icon-edit"></i></button>
@ -98,27 +107,25 @@
{if condition="checkRuleButton('user.user/auth')"}<input type="checkbox" name="auth" lay-skin="primary" lay-filter="auth" {{# if(d.auth ==1){ }}checked value="0"{{# } else { }}value="1"{{# } }} id="{{d.id}}" >{else}<button class="layui-btn layui-btn-xs layui-btn-disabled">无权限</button>{/if}
{{# } }}
</script>
<script type="text/html" id="user-sex">
{{#if (d.sex == 0) { }}
<span></span>
{{# }else if(d.sex == 1){ }}
<span></span>
{{# } }}
</script>
<script type="text/html" id="user-login">
{{#if (d.login == 0) { }}
<span>在线</span>
{{# }else if(d.sex == 1){ }}
<span>离线</span>
{{# } }}
<script type="text/html" id="userLoginTpl">
<url>
<li>ip{{d.ip}}</li>
<li>归属地:{{d.city}}</li>
<li>{{d.logintime}}</li>
</url>
</script>
<script type="text/html" id="user-createTime">
{{layui.util.toDateString(d.createTime, 'yyyy-MM-dd')}}
</script>
<script type="text/html" id="TPL-dropdpwn-vip">
<button class="layui-btn layui-btn-primary dropdpwn-demo">
<span>{{= d.vip}}</span>
<i class="layui-icon layui-icon-down layui-font-12"></i>
</button>
</script>
<script src="/static/component/layui/layui.js"></script>
<script src="/static/component/pear/pear.js"></script>
<script>
@ -127,68 +134,48 @@
let form = layui.form;
let $ = layui.jquery;
let common = layui.common;
var dropdown = layui.dropdown;
let MODULE_PATH = "operate/";
let MODULE_PATH = "operate/";
let cols = [
[{
[ {
type: 'checkbox'
},
{
title: 'id',
field: 'id',
align: 'center',
width: 60
},
{
title: '头像',
field: 'avatar',
align: 'center',
width: 80,
width: 150,
templet: '#imgTpl'
},
{
title: '用户',
field: 'username',
align: 'center',
width: 100
minWidth: 200,
templet: '#userInfoTpl'
},
{
title: '昵称',
field: 'nick',
align: 'center'
},
{
title: '性别',
field: 'sex',
align: 'center',
width: 80,
templet: '#user-sex'
},
{
title: '电话',
field: 'phone',
align: 'center'
},
{
title: '邮箱',
field: 'email',
align: 'center'
},
{
title: 'IP',
title: '登录',
field: 'ip',
align: 'center'
minWidth: 180,
templet: '#userLoginTpl'
},
{
title: '城市',
field: 'city',
align: 'center'
title: '积分/金币',
field: 'point',
align: 'center',
width: 120,
edit: 'text'
},
{
title: '登录时间',
field: 'logintime',
align: 'center'
title: '会员等级/L',
field: 'vip',
align: 'center',
width:180,
unresize: true,
align: 'center',
templet: '#TPL-dropdpwn-vip'
},
{
title: '状态',
@ -197,12 +184,6 @@
width: 95,
templet: '#user-enable'
},
{
title: '登录',
field: 'login',
align: 'center',
templet: '#user-login'
},
{
title: '超级管理',
field: 'auth',
@ -230,12 +211,54 @@
cols: cols,
skin: 'line',
toolbar: '#user-toolbar',
lineStyle: 'height: 160px;', // 定义表格的多行样式
defaultToolbar: [{
title: '刷新',
layEvent: 'refresh',
icon: 'layui-icon-refresh',
}, 'filter', 'print', 'exports'],
limit: 10
limit: 10,
done: function(res, curr, count){
var options = this;
// 获取当前行数据
table.getRowData = function(elem){
var index = $(elem).closest('tr').data('index');
return table.cache[options.id][index] || {};
};
// dropdown 方式的下拉选择
dropdown.render({
elem: '.dropdpwn-demo',
// trigger: 'hover',
// 此处的 data 值,可根据 done 返回的 res 遍历来赋值
data: res.viplist,
click: function(obj){
var data = table.getRowData(this.elem); // 获取当前行数据(如 id 等字段,以作为数据修改的索引)
this.elem.find('span').html(obj.title);
// 更新数据中对应的字段
data.vip = obj.title;
console.log(data)
$.ajax({
type: "post",
url: "{:url('user.user/editVipLevel')}",
data: data,
dataType: 'json',
success: (res) => {
if(res.code === 0) {
layer.msg(res.msg, {icon: 1});
} else {
layer.msg(res.msg, {icon: 2});
return false;
}
}
})
// 显示 - 仅用于演示
//layer.msg('选中值: '+ obj.title +'<br>当前行数据:'+ JSON.stringify(data));
}
});
}
});
table.on('tool(user-table)', function(obj) {
@ -256,6 +279,44 @@
}
});
// 单元格编辑后的事件
table.on('edit(user-table)', function(obj){
//var field = obj.field; // 得到修改的字段
var value = obj.value // 得到修改后的值
//var oldValue = obj.oldValue // 得到修改前的值 -- v2.8.0 新增
var data = obj.data // 得到所在行所有键值
//var col = obj.getCol(); // 得到当前列的表头配置属性 -- v2.8.0 新增
// 值的校验
if(value.replace(/\s/g, '') === ''){
layer.tips('值不能为空', this, {tips: 1});
return obj.reedit(); // 重新编辑 -- v2.8.0 新增
}
// 只能为数值型
if(isNaN(value)) {
layer.tips('只能为数值', this, {tips: 1});
return obj.reedit();
}
// 编辑后续操作,如提交更新请求,以完成真实的数据更新
$.ajax({
type: "post",
url: "{:url('user.user/editPoint')}",
data: data,
dataType: 'json',
success: (res) => {
if(res.code === 0) {
layer.msg(res.msg, {icon: 1});
} else {
layer.msg(res.msg, {icon: 2});
return false;
}
}
})
// …
});
form.on('submit(user-query)', function(data) {
table.reload('user-table', {
where: data.field

View File

@ -13,11 +13,11 @@
<input type="text" name="id" class="layui-input" value="{$vip.id}">
</div>
<div class="layui-form-item">
<label class="layui-form-label">Vip级别</label>
<label class="layui-form-label">会员等级</label>
<div class="layui-input-inline" >
<select name="vip">
{volist name="level" id="vo"}
<option {if condition="$vip.vip eq $vo"} selected {/if} value="{$vo}">{if condition="$vo eq 0"}普通{else /}VIP{$vo}{/if}</option>
<option {if condition="$vip.vip eq $vo"} selected {/if} value="{$vo}">{if condition="$vo eq 0"}普通{else /}L{$vo}{/if}</option>
{/volist}
</select>
</div>
@ -29,15 +29,33 @@
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">认证</label>
<label class="layui-form-label">认证昵称</label>
<div class="layui-input-inline">
<input type="text" name="nick" lay-verify="required" placeholder="等级昵称" autocomplete="off" class="layui-input" value="{$vip.nick}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">权限</label>
<label class="layui-form-label">免费发帖/日</label>
<div class="layui-input-inline">
<input type="text" name="rules" lay-verify="" placeholder="请选择" autocomplete="off" class="layui-input" value="{$vip.rules}">
<input type="text" name="postnum" lay-verify="number" placeholder="10" autocomplete="off" class="layui-input" value="{$vip.postnum}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">免费刷新/日</label>
<div class="layui-input-inline">
<input type="text" name="refreshnum" lay-verify="number" placeholder="10" autocomplete="off" class="layui-input" value="{$vip.refreshnum}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">发贴扣积分</label>
<div class="layui-input-inline">
<input type="text" name="postpoint" lay-verify="number" placeholder="10" autocomplete="off" class="layui-input" value="{$vip.postpoint}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">刷贴扣积分</label>
<div class="layui-input-inline">
<input type="text" name="refreshpoint" lay-verify="number" placeholder="10" autocomplete="off" class="layui-input" value="{$vip.refreshpoint}">
</div>
</div>
</div>
@ -77,9 +95,8 @@
icon: 1,
time: 1000
}, function() {
parent.layer.close(parent.layer.getFrameIndex(window
.name)); //关闭当前页
parent.layui.table.reload("vip-table");
parent.layer.close(parent.layer.getFrameIndex(window.name)); //关闭当前页
parent.layui.table.reload("vip-rule");
});
} else {
layer.msg(result.msg, {

View File

@ -8,20 +8,14 @@
</head>
<body class="pear-container">
<div class="layui-fluid" id="component-tabs">
<div class="layui-card">
<div class="layui-card-body">
<div class="layui-tab layui-tab-brief" lay-filter="server-tabs-brief">
<div class="layui-card">
<div class="layui-card-body">
<div class="layui-tab layui-tab-brief" lay-filter="server-tabs-brief" lay-allowclose="true">
<ul class="layui-tab-title">
{if hook('signstatushook') == 1}
<li class="layui-this" lay-id="score">签到规则</li>
{/if}
<li lay-id="vip" class="{if hook('signstatushook') == 0} layui-this {/if}">用户等级</li>
<li lay-id="vip" class="layui-this">用户等级</li>
</ul>
<div class="layui-tab-content">
{:hook('signadminhook')}
<div class="layui-tab-item {if hook('signstatushook') == 0}layui-show{/if}">
<div class="layui-tab-item layui-show">
<div class="layui-tab-content" style="padding: 20px 0;">
<div class="layui-form">
<div class="layui-form-item">
@ -29,24 +23,37 @@
<label class="layui-form-label">用户积分</label>
<div class="layui-input-inline" style="width: 120px;">
<select name="vip">
<option value="0">普通</option>
<option value="1">VIP1</option>
<option value="2">VIP2</option>
<option value="3">VIP3</option>
<option value="4">VIP4</option>
<option value="5">VIP5</option>
<option value="0">普通</option>
<option value="1">L1</option>
<option value="2">L2</option>
<option value="3">L3</option>
<option value="4">L4</option>
<option value="5">L5</option>
</select>
</div>
<div class="layui-input-inline">
<input type="tel" name="score" lay-verify="required" placeholder="积分区间:0-99" autocomplete="off" class="layui-input">
<input type="text" name="score" lay-verify="required" placeholder="积分区间:0-99" autocomplete="off" class="layui-input">
</div>
<div class="layui-input-inline">
<input type="tel" name="nick" lay-verify="required" placeholder="认证名称" autocomplete="off" class="layui-input">
<input type="text" name="nick" lay-verify="required" placeholder="认证名称" autocomplete="off" class="layui-input">
</div>
<div class="layui-input-inline">
<input type="text" name="postnum" lay-verify="required|number" placeholder="免费发帖日限额" autocomplete="off" class="layui-input">
</div>
<div class="layui-input-inline">
<input type="text" name="refreshnum" lay-verify="required|number" placeholder="免费刷新日限额" autocomplete="off" class="layui-input">
</div>
<div class="layui-input-inline">
<input type="text" name="postpoint" lay-verify="required|number" placeholder="发帖扣积分" autocomplete="off" class="layui-input">
</div>
<div class="layui-input-inline">
<input type="text" name="refreshpoint" lay-verify="required|number" placeholder="刷贴扣积分" autocomplete="off" class="layui-input">
</div>
<div class="layui-input-inline">
<input type="submit" class="pear-btn pear-btn-primary" lay-submit lay-filter="vip-rule-submit" id="vip-rule-submit" value="立即提交">
</div>
</div>
</div>
</div>
@ -59,6 +66,9 @@
</div>
</div>
</div>
{:hook('signadminhook')}
</div>
</div>
</div>
@ -75,6 +85,9 @@
let VIP_RULE = "{:url('user.vip/list')}";
// 渲染 tab 组件
element.render('tab', 'server-tabs-brief');
//Vip规则
table.render({
elem: '#vip-rule',
@ -84,7 +97,10 @@
{field: 'vip',title: '等级'},
{field: 'score',title: '积分'},
{field: 'nick',title: '认证'},
{field: 'rules',title: '权限'},
{field: 'postnum',title: '免费发帖/日'},
{field: 'refreshnum',title: '免费刷新/日'},
{field: 'postpoint',title: '发帖扣积分'},
{field: 'refreshpoint',title: '刷新扣积分'},
{field: 'ctime',title: '时间'},
{title: '操作', width: 150, align:'center', toolbar: '#vip-rule-bar'}
@ -111,23 +127,23 @@
url:"{:url('user.vip/add')}",
data:field,
daType:"json",
success:function (data){
if (data.code == 0) {
layer.msg(data.msg,{
icon:6,
time:2000
}, function(){
table.reload('vip-rule'); //数据刷新
});
} else {
layer.open({
title:'添加失败',
content:data.msg,
icon:5,
anim:6
});
}
success:function (res){
if (res.code == 0) {
layer.msg(res.msg,{
icon:6,
time:2000
}, function(){
table.reload('vip-rule'); //数据刷新
});
} else {
layer.open({
title:'添加失败',
content:res.msg,
icon:5,
anim:6
});
}
}
});
return false;
});
@ -139,7 +155,7 @@
type: 2,
title: '修改',
shade: 0.1,
area: ['450px', '400px'],
area: ['450px', '580px'],
content: 'edit.html?id=' + obj.data.id
});
}

View File

@ -18,6 +18,8 @@ use think\facade\Db;
use taoser\think\Auth;
use taoler\com\Files;
use think\facade\Lang;
use think\facade\Cookie;
use think\facade\Config;
/**
* 控制器基础类
@ -165,6 +167,31 @@ class AdminController extends \app\BaseController
$articleUrl = (string) url('article_detail', ['id' => (int) $aid, 'ename'=> $ename]);
}
return $this->appConver($appName, $articleUrl);
}
//后台管理用户的路由转换为前台用户中心的路由
//直接登录用户中心
protected function getUserHome($uid) {
$user = Db::name('user')->field('id,name')->find($uid);
$salt = Config::get('taoler.salt');
$auth = md5($user['name'].$salt).":".$user['id'];
Cookie::set('auth',$auth,604800);
$url = (string) url('user/index');
return $this->appConver('index', $url);
}
/**
* APP应用转换,在后台admin应用转换为在其它app应用的路径
* /admin/user/info转换为 /index/user/info
* @param string $appName 要转换为哪个应用
* @param string $url 路由地址
* @return string
*/
public function appConver(string $appName, string $url) :string
{
// 判断应用是否绑定域名
$app_bind = array_search($appName, config('app.domain_bind'));
// 判断应用是否域名映射
@ -179,43 +206,40 @@ class AdminController extends \app\BaseController
if($bind_admin) {
// 1.应用绑定了域名
if($app_bind) {
return $this->getDomain() . $articleUrl;
return $this->getDomain() . $url;
}
// 2.应用进行了映射
if($app_map){
return $this->getDomain() . '/' . $appName . $articleUrl;
return $this->getDomain() . '/' . $appName . $url;
}
// 3.应用未绑定域名也未进行映射
return $this->getDomain() . '/' . $appName . $articleUrl;
return $this->getDomain() . '/' . $appName . $url;
}
//2.admin进行了映射
if($map_admin) {
// 1.应用绑定了域名
if($app_bind) {
return $this->getDomain() . str_replace($map_admin, '', $articleUrl);;
return $this->getDomain() . str_replace($map_admin, '', $url);;
}
// 2.应用进行了映射
if($app_map){
return $this->getDomain() . str_replace($map_admin, $app_map, $articleUrl);
return $this->getDomain() . str_replace($map_admin, $app_map, $url);
}
// 3.应用未绑定域名也未进行映射
return $this->getDomain() . str_replace($map_admin, $appName, $articleUrl);
return $this->getDomain() . str_replace($map_admin, $appName, $url);
}
//3.admin未绑定域名也未映射
// 1.应用绑定了域名
if($app_bind) {
return $this->getDomain() . $articleUrl;
return $this->getDomain() . $url;
}
// 2.应用进行了映射
if($app_map){
return $this->getDomain() . str_replace('admin', $app_map, $articleUrl);
return $this->getDomain() . str_replace('admin', $app_map, $url);
}
return str_replace('admin', $appName, $articleUrl);
return str_replace('admin', $appName, $url);
}
}

View File

@ -16,7 +16,6 @@ use think\facade\Request;
use think\facade\View;
use think\facade\Db;
use think\facade\Session;
use think\facade\Cache;
use app\BaseController as BaseCtrl;
/**
@ -25,14 +24,26 @@ use app\BaseController as BaseCtrl;
class BaseController extends BaseCtrl
{
protected $uid = '';
/**
* 登录用户uid
*
* @var int|null
*/
protected $uid;
/**
* 登录用户信息
*
* @var array|object
*/
protected $user;
/**
* 初始化系统,导航,用户
*/
protected function initialize()
{
$this->uid = Session::get('user_id');
$this->setUid();
//系统配置
$this->showSystem();
@ -46,33 +57,32 @@ class BaseController extends BaseCtrl
}
//判断是否已登录?
protected function isLogged()
// 用户登录
private function setUid()
{
if(Session::has('user_id')){
$this->success('您已登录','/index/index/index');
if(Session::has('user_id')) {
$this->uid = Session::get('user_id') ?? -1;
}
}
//判断是否需要登录?
protected function isLogin()
{
if(!Session::has('user_id')){
$this->error('请登录','/index/user/login');
}
}
private function setUser()
{
if(Session::has('user_id')) {
$this->uid = Session::get('user_id') ?? -1;
}
}
// 显示子导航subnav
protected function showSubnav()
{
$subCateList = []; // 没有点击任何分类,点击首页获取全部分类信息
//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 = [];
} else { // 点击分类,获取子分类信息
if(!is_null($pCate)) { // 点击分类,获取子分类信息
$parentId = $pCate['id'];
$subCate = Db::name('cate')->field('id,ename,catename,is_hot,pid')->where(['pid'=>$parentId,'status'=>1,'delete_time'=>0])->select()->toArray();
if(!empty($subCate)) { // 有子分类
$subCateList = array2tree($subCate);
} else { //无子分类
@ -95,12 +105,13 @@ class BaseController extends BaseCtrl
//显示当前登录用户
protected function showUser($id)
{
$user = Cache::get('user'.$id);
if(!$user){
//1.查询用户
$user = Db::name('user')->field('id,name,nickname,user_img,sex,area_id,auth,city,email,active,sign,point,vip,create_time')->find($id);
Cache::tag('user')->set('user'.$id,$user,600);
}
if($id == -1) return [];
//1.查询用户
$user = Db::name('user')
->alias('u')
->join('user_viprule v','v.vip = u.vip')
->field('u.id as id,v.id as vid,name,nickname,user_img,sex,area_id,auth,city,phone,email,active,sign,point,u.vip as vip,nick,u.create_time as create_time')
->find((int)$id);
return $user;
}

View File

@ -10,6 +10,14 @@ use think\response\Json;
class Arts
{
/**
* 数据内容
*
* @var string
*/
protected $content = '';
//显示网站设置
protected function getSystem()
{
@ -19,11 +27,17 @@ class Arts
}
//域名协议转换 把数据库中的带HTTP或不带协议的域名转换为当前协议的域名前缀
protected function getHttpUrl($url)
{
//域名转换为无http协议
protected function getHttpUrl($url)
{
//域名转换为无http协议
$www = stripos($url,'://') ? substr(stristr($url,'://'),3) : $url;
return Request::scheme().'://'. $www;
$htpw = Request::scheme().'://'. $www;
return $htpw;
}
protected function getDomain()
{
return $this->getHttpUrl($this->getSystem()['domain']);
}
//得到当前系统安装前台域名
@ -305,10 +319,10 @@ class Arts
{
$filename = pathinfo($url, PATHINFO_BASENAME);
//$dirname = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_DIRNAME);
$dirname = date('Ymd',time());
$uid = session('user_id') ?: $userId;
//路径
$path = 'storage/' . $uid . '/article_pic/' . $dirname . '/';
$path = 'storage/' . $uid . '/article_pic/' . date('Ymd',time()) . '/';
//绝对文件夹
$fileDir = public_path() . $path;
//文件绝对路径
@ -338,8 +352,9 @@ class Arts
//下载网络图片到本地并替换
public function downUrlPicsReaplace($content, $userId = 1)
{
$this->content = $content;
// 批量下载网络图片并替换
$images = $this->getArticleAllpic($content);
$images = $this->getArticleAllpic($this->content);
if(count($images)) {
foreach($images as $image){
//1.带http地址的图片2.非本站的网络图片 3.非带有?号等参数的图片
@ -348,13 +363,13 @@ class Arts
//下载远程图片(可下载)
$newImageUrl = $this->downloadImage($image, $userId);
//替换图片链接
$content = str_replace($image,Request::domain().$newImageUrl,$content);
$this->content = str_replace($image,Request::domain().$newImageUrl,$this->content);
}
}
//不可下载的图片如加密或者带有参数的图片如type=jpeg,直接返回content
}
return $content;
return $this->content;
}
}

View File

@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
namespace app\common\lib;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class JwtAuth
{
// 访问密钥
const KEY = 'adsfhgkjl1324675809';
// 签发者
const ISS = 'www.aieok.com';
// 接收者
const AUD = 'www.aieok.com';
// 加密算法
const ALG = 'HS256';
/** 对数据进行编码
* @param array $data
*/
public static function encode(array $data)
{
$time = time();
$payload = [
"iss" => self::ISS,
"aud" => self::AUD,
"iat" => $time,
"nbf" => $time,
'exp' => $time + 86400 * 30,
'data' => $data,
];
$token = JWT::encode($payload, self::KEY, self::ALG);
return $token;
}
/**
*
* token 进行编码验证
* @param string $token
* @param integer $user_id
*/
public static function decode(string $token)
{
try {
// 对 token 进行编码
$decoded = JWT::decode($token, new Key(self::KEY, self::ALG));
// 检测 token 附加数据中是否存在用户id
if (!empty($decoded->data->uid)) {
$data = $decoded->data;
} else {
throw new \Exception('token 中没有用户信息');
}
} catch (\Exception $e) {
throw new \Exception($e->getMessage(), 201);
}
return $data; // 用户信息
}
public static function getHeaderToken(array $header)
{
return str_replace('Bearer ', '', $header['authorization']);
}
}

View File

@ -2,11 +2,11 @@
/*
* @Author: TaoLer <317927823@qq.com>
* @Date: 2021-12-06 16:04:50
* @LastEditTime: 2022-08-16 14:16:40
* @LastEditTime: 2024-04-12 19:32:40
* @LastEditors: TaoLer
* @Description: 优化版
* @FilePath: \TaoLer\app\common\lib\SqlFile.php
* Copyright (c) 2020~2022 https://www.aieok.com All rights reserved.
* Copyright (c) 2020~2024 https://www.aieok.com All rights reserved.
*/
declare (strict_types = 1);
@ -84,6 +84,9 @@ class SqlFile
if (file_exists($sqlFile)) {
$sqlArr = self::loadSqlFile($sqlFile);
if(!empty($sqlArr)) {
$orginal = 'tao_'; //sql默认表前缀
$prefix = config('database.connections.mysql.prefix'); // 现在表前缀
($orginal == $prefix) ? true : $sqlArr = str_replace(" `{$orginal}", " `{$prefix}", $sqlArr); //替换数组中表前缀
foreach($sqlArr as $v){
try {
Db::execute($v);

View File

@ -155,6 +155,7 @@ class Uploads
->check(['file'=>$file]);
} catch (ValidateException $e) {
halt($e->getMessage());
return json(['status'=>-1,'msg'=>$e->getMessage()]);
}
@ -200,4 +201,75 @@ class Uploads
return json(['status'=>0,'msg'=>'上传成功','url'=> $name_path, 'location'=>$name_path]);
}
/**
* 上传文件
* @param string $fileName 文件名
* @param string $dirName 目录名
* @param int $fileSize 文件大小
* @param string $fileType 文件类型
* @param string $rule 文件命名规则 默认md5,uniqid,date,sha1_self为上传文件名称作为文件名或者自定义如a.jpg文件名
* @return \think\response\Json
*/
public function put_api(string $fileName, string $dirName, int $fileSize, string $fileType, int $uid, string $rule = '' )
{
if(stripos($fileName,'http') !== false) {
$file = $fileName;
} else {
$file = request()->file($fileName);
}
$fileExt = $this->getFileInfo($fileType,'ext');
$fileMime = $this->getFileInfo($fileType,'mime');
try {
validate([$fileName=>['fileSize'=>$fileSize * 1024,'fileExt'=>$fileExt,'fileMime'=>$fileMime]])
->check(['file'=>$file]);
} catch (ValidateException $e) {
halt($e->getMessage());
return json(['status'=>-1,'msg'=>$e->getMessage()]);
}
// 解析存储位置 SYS_开头为系统位置
$isSys = stripos($dirName, 'SYS_');
if($isSys) {
$disk = 'sys';
$dirName = substr($dirName,4);
$uploadDir = Config::get('filesystem.disks.sys.url');
$path = DIRECTORY_SEPARATOR . $disk . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . date('Ymd');
} else {
$disk = 'public';
$dirName = $uid . DIRECTORY_SEPARATOR . $dirName;
$uploadDir = Config::get('filesystem.disks.public.url');
$path = DIRECTORY_SEPARATOR . 'storage' . DIRECTORY_SEPARATOR . $dirName . DIRECTORY_SEPARATOR . date('Ymd');
}
$realPath = app()->getRootPath() . 'public' . $path;
$rules = ['md5','date','sha1','uniqid'];
try{
// 解析是否自定义文件名
if(in_array($rule, $rules)) {
// rule命名
$info = $file->move($realPath, $file->hashName($rule));
} elseif(!empty($rule)) {
// 自定义文件名
if(stripos($rule, '_self')) {
$info = $file->move($realPath, $file->getOriginalName());
}
$info = $file->move($realPath, $rule);
} else {
// 默认
$info = $file->move($realPath, $file->hashName());
}
} catch (\Exception $e) {
return json(['code' => -1, 'msg' => $e->getMessage()]);
}
$name_path = str_replace('\\',"/", $path . '/' . $info->getBasename());
return json(['code' => 1,'msg'=>'上传成功', 'data' => ['url'=> $name_path]]);
}
}

View File

@ -7,6 +7,7 @@ use think\Model;
use think\model\concern\SoftDelete;
use think\facade\Cache;
use think\facade\Config;
use think\db\Query;
class Article extends Model
{
@ -109,20 +110,19 @@ class Article extends Model
*/
public function getArtTop(int $num)
{
return Cache::remember('topArticle', function() use($num){
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]])
$topIdArr = $this::where(['is_top' => 1, 'status' => 1])->limit($num)->column('id');
return $this::field('id,title,title_color,cate_id,user_id,create_time,is_top,pv,upzip,has_img,has_video,has_audio,read_type')
->where('id', 'in', $topIdArr)
->with([
'cate' => function ($query) {
$query->where('delete_time', 0)->field('id,catename,ename');
'cate' => function (Query $query) {
$query->field('id,catename,ename');
},
'user' => function ($query) {
'user' => function (Query $query) {
$query->field('id,name,nickname,user_img');
}
])->withCount(['comments'])
->order('create_time', 'desc')
->limit($num)
->order('id', 'desc')
->append(['url'])
->select()
->toArray();
@ -140,28 +140,30 @@ 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,content,create_time,is_hot,pv,jie,upzip,has_img,has_video,has_audio,read_type,art_pass')
$data = $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');
'cate' => function(Query $query){
$query->field('id,catename,ename,detpl');
},
'user' => function($query){
'user' => function(Query $query){
$query->field('id,name,nickname,user_img');
} ])
->withCount(['comments'])
->where('status', '=', 1)
->order('create_time','desc')
->order('id','desc')
->limit($num)
->hidden(['art_pass'])
->append(['url'])
->select()
->toArray();
->select();
return $data->hidden(['art_pass'])->toArray();
},30);
}
/**
* 热点文章
* @param int $num 热点列表数量
* @param int $num 热点列表数量 评论或者pv排序
* @return \think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
@ -169,20 +171,47 @@ class Article extends Model
*/
public function getArtHot(int $num)
{
$artHot = $this::field('id,cate_id,title,create_time')
->with(['cate' => function($query){
$query->where('delete_time',0)->field('id,ename');
}])
->withCount('comments')
->where(['status'=>1,'delete_time'=>0])
->whereTime('create_time', 'year')
->order('comments_count','desc')
return Cache::remember('article_hot', function() use($num){
$comments = Comment::field('article_id,count(*) as count')
->hasWhere('article',['status' => 1])
->group('article_id')
->order('count','desc')
->limit($num)
->withCache(120)
->append(['url'])
->select();
$idArr = [];
foreach($comments as $v) {
$idArr[] = $v->article_id;
}
$where = [];
if(count($idArr)) {
// 评论数
$where = [
['id', 'in', $idArr]
];
return $artHot;
$artHot = $this::field('id,cate_id,title,create_time')
->withCount('comments')
->where($where)
//->whereYear('create_time')
// ->order('comments_count','desc')
->append(['url'])
->select();
} else {
// pv数
$where = [
['status', '=', 1]
];
$artHot = $this::field('id,cate_id,title,create_time')
->withCount('comments')
->where($where)
->whereMonth('create_time')
->order('pv','desc')
->limit($num)
->append(['url'])
->select();
}
return $artHot;
}, 3600);
}
/**
@ -198,14 +227,15 @@ class Article extends Model
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){
$query->where('delete_time',0)->field('id,catename,ename');
'cate' => function(Query $query){
$query->field('id,catename,ename');
},
'user' => function($query){
'user' => function(Query $query){
$query->field('id,name,nickname,user_img,area_id,vip,city')->withCount(['article','comments']);
}
])
->withCount(['comments'])
->hidden(['art_pass'])
->append(['url'])
->find($id);
@ -223,12 +253,6 @@ class Article extends Model
*/
public function getCateList(string $ename, string $type, int $page = 1)
{
$where = [];
$cateId = Cate::where('ename',$ename)->value('id');
if($cateId){
$where[] = ['cate_id' ,'=', $cateId];
}
switch ($type) {
//查询文章,15个分1页
case 'jie':
@ -244,10 +268,28 @@ class Article extends Model
$where[] = ['jie','=', 0];
break;
}
$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,read_type,art_pass')
return Cache::remember('cate_list_'.$ename.$type.$page, function() use($where,$ename,$page){
$cateId = Cate::where('ename',$ename)->value('id');
if($cateId){
$where[] = ['cate_id' ,'=', $cateId];
}
$list = $this::field('id')->where($where)->order(['id'=>'desc'])->paginate([
'list_rows' => 15,
'page' => $page
])->toArray();
$idArr = [];
if($list['total'] > 0) {
foreach($list['data'] as $v) {
$idArr[] = $v['id'];
}
}
$data = $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');
@ -256,13 +298,19 @@ class Article extends Model
$query->field('id,name,nickname,user_img,vip');
}
])->withCount(['comments'])
->where($where)
->limit(15)
->order(['create_time'=>'desc'])
->paginate([
'list_rows' => 15,
'page' => $page
])->append(['url'])->toArray();
->where('id','in',$idArr)
->order(['id'=>'desc'])
->append(['url'])
->hidden(['art_pass'])
->select()
->toArray();
return [
'total' => $list['total'],
'per_page' => $list['per_page'],
'current_page' => $list['current_page'],
'last_page' => $list['last_page'],
'data' => $data
];
}, 600);
}
@ -270,11 +318,12 @@ class Article extends Model
public function getUserArtList(int $id) {
$userArtList = $this::field('id,cate_id,title,create_time,pv,is_hot')
->with(['cate' => function($query){
$query->where(['delete_time'=>0,'status'=>1])->field('id,ename');
$query->where(['status'=>1])->field('id,ename');
}])
->where(['user_id' => $id,'status' => 1])
->order(['create_time'=>'desc'])
->order('id','desc')
->append(['url'])
->limit(25)
->cache(3600)
->select()
->toArray();
@ -295,10 +344,11 @@ class Article extends Model
$map[] = ['title','like','%'.$keywords.'%'];
$res = Article::where($map)
->withCount('comments')
->order('create_time','desc')
->order('id','desc')
->append(['url'])
->paginate(10);
return $res;
return $res;
}
}
@ -311,14 +361,17 @@ class Article extends Model
*/
public function getAllTags($tagId)
{
$allTags = $this::hasWhere('taglist',['tag_id'=>$tagId])
$arrId = Taglist::where('tag_id', $tagId)->column('article_id');
$allTags = $this::field('id,user_id,cate_id,title,create_time,is_hot')->where('id','in', $arrId)
->with(['user' => function($query){
$query->field('id,name,nickname,user_img,area_id,vip');
},'cate' => function($query){
$query->where('delete_time',0)->field('id,catename,ename');
$query->field('id,catename,ename');
}])
->where(['status'=>1])
->order('pv desc')
->order('id desc')
->limit(20)
->append(['url'])
->select()
->toArray();
@ -335,14 +388,13 @@ class Article extends Model
*/
public function getRelationTags($tagId,$id,$limit)
{
$allTags = $this::hasWhere('taglist',['tag_id'=>$tagId])
->with(['user' => function($query){
$query->field('id,name,nickname,user_img,area_id,vip');
},'cate' => function($query){
$query->where('delete_time',0)->field('id,catename,ename');
}])
$arrId = Taglist::where([
['tag_id', '=', $tagId],
['article_id','<>',$id]
])->column('article_id');
$allTags = $this::field('id,cate_id,title')->where('id', 'in', $arrId)
->where(['status'=>1])
// ->where('article.id', '<>', $id)
->order('pv desc')
->limit($limit)
->append(['url'])
@ -359,23 +411,33 @@ class Article extends Model
* @param [type] $cid 当前分类ID
* @return void|array
*/
public function getPrevNextArticle($id,$cid)
public function getPrevNextArticle($id, $cid)
{
//上一篇
$previous = $this::field('id,title,cate_id')
->where([
['id', '<', $id],
$pIds = $this::where([
['id', '>=', $id], // >= <= 条件可以使用索引
['cate_id', '=', $cid],
['status', '=',1]
])->order('id desc')->limit(1)->append(['url'])->select()->toArray();
])->order('id asc')->limit(2)->column('id');
if(count($pIds) === 2) {
$previous = $this::field('id,title,cate_id')->append(['url'])->find($pIds[1])->toArray();
} else {
$previous = [];
}
//下一篇
$next = $this::field('id,title,cate_id')
->where([
['id', '>', $id],
$nids = $this::where([
['id', '<=', $id],
['cate_id', '=', $cid],
['status', '=',1]
])->limit(1)->append(['url'])->select()->toArray();
])->order('id desc')->limit(2)->column('id');
if(count($nids) === 2) {
$next = $this::field('id,title,cate_id')->append(['url'])->find($nids[1])->toArray();
} else {
$next = [];
}
return ['previous' => $previous, 'next' => $next];
}
@ -394,13 +456,33 @@ class Article extends Model
])
->where(['status' => 1])
->where($where)
->order('create_time', 'desc')
->order('id', 'desc')
->paginate([
'list_rows' => $limit,
'page' => $page
])->toArray();
}
// 获取admin应用所有帖子状态内容
public function getAllStatusList(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,read_type,art_pass')
->with([
'user' => function($query){
$query->field('id,name,user_img');
},
'cate' => function($query){
$query->field('id,ename,catename');
}
])
->where($where)
->order('id', 'desc')
->paginate([
'list_rows' => $limit,
'page' => $page
])->toArray();
}
// 获取url
public function getUrlAttr($value,$data)
{

View File

@ -63,12 +63,12 @@ class Cate extends Model
public function del($id)
{
$cates = $this->field('id,pid')->with('article')->find($id);
$sonCate = $this->field('id,pid')->where('pid',$cates['id'])->find();
if(empty($sonCate)) {
$res = $cates->together(['article'])->delete();
return $res ? 1 : '删除失败';
$sonCate = $this::where('pid',$cates['id'])->count();
if($sonCate > 0) {
return '存在子分类,无法删除';
}
return '存在子分类,无法删除';
$res = $cates->together(['article'])->delete();
return $res ? 1 : '删除失败';
}
// 分类表
@ -89,7 +89,7 @@ class Cate extends Model
{
try {
return $this->where(['status' => 1])
->cache('catename', 3600)
->cache(3600)
->append(['url'])
->select()
->toArray();
@ -104,7 +104,7 @@ class Cate extends Model
{
try {
$cateList = $this->where(['status' => 1])
->cache('catename', 3600)
->cache(3600)
->append(['url'])
->select()
->toArray();
@ -121,11 +121,11 @@ class Cate extends Model
public function getUrlAttr($value,$data)
{
// 栏目下存在帖子则返回正常url,否则为死链
$articleArr = Article::field('id')->where('cate_id', $data['id'])->find();
if(empty($articleArr)) {
return 'javascript:void(0);';
$articleCount = Article::where('cate_id', $data['id'])->count();
if($articleCount > 0) {
return (string) url('cate',['ename' => $data['ename']]);
}
return (string) url('cate',['ename' => $data['ename']]);;
return 'javascript:void(0);';
}

View File

@ -97,7 +97,7 @@ class Comment extends Model
$res['data'][] = $u;
}
} else {
$res = ['status' => 0, 'msg' =>'no reply'];
$res = ['status' => -1, 'msg' =>'no reply'];
}
return json($res);
}

View File

@ -33,12 +33,11 @@ class MessageTo extends Model
//得到消息数
public function getMsgNum($id)
{
$msg = $this::where(['receve_id'=>$id,'is_read'=>0])->column('id');
if($num = count($msg)) {
return $num;
} else {
return 0;
$msgNum = $this::where(['receve_id'=>$id,'is_read'=>0])->count('id');
if($msgNum) {
return $msgNum;
}
return 0;
}

View File

@ -127,6 +127,7 @@ class User extends Model
$salt = substr(md5($data['create_time']),-6);
$data['password'] = substr_replace(md5($data['password']),$salt,0,6);
$data['status'] = Config::get('taoler.config.regist_check');
$data['nickname'] = $data['name'];
$msg = $data['status'] ? '注册成功请登录' : '注册成功,请等待审核';
$result = $this->save($data);
if ($result) {

View File

@ -24,7 +24,7 @@ class UserViprule extends Model
//获取等级名
public function getVipAttr($value)
{
$vip = [0=>'普通',1=>'VIP1',2=>'VIP2',3=>'VIP3',4=>'VIP4',5=>'VIP5'];
$vip = [0=>'普通',1=>'L1',2=>'L2',3=>'L3',4=>'L4',5=>'L5'];
return $vip[$value];
}

View File

@ -30,6 +30,7 @@ class Article extends TagLib
'description' => ['attr' => '', 'close' => 0],
'link' => ['attr' => '', 'close' => 0],
'time' => ['attr' => '', 'close' => 0],
'uptime' => ['attr' => '', 'close' => 0],
'cate' => ['attr' => 'name', 'close' => 0],
'user' => ['attr' => 'name', 'close' => 0],
@ -102,6 +103,11 @@ class Article extends TagLib
return '{$article.create_time}';
}
public function tagUptime(): string
{
return '{$article.update_time}';
}
// 详情分类
public function tagCate($tag): string
{

View File

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

View File

@ -50,18 +50,19 @@ class Article extends BaseController
//分类列表
$artList = $this->model->getCateList($ename,$type,$page);
// halt($artList);
// 热议文章
$artHot = $this->model->getArtHot(10);
$assignArr = [
'ename'=>$ename,
'cateinfo'=> $cateInfo,
'type'=>$type,
'artList'=>$artList,
'artHot'=>$artHot,
'path'=>$path,
'jspage'=>'jie'
'ename' => $ename,
'cateinfo' => $cateInfo,
'type' => $type,
'artList' => $artList,
'artHot' => $artHot,
'path' => $path,
'jspage' => 'jie'
];
View::assign($assignArr);
@ -96,8 +97,8 @@ class Article extends BaseController
// 标签
$tags = [];
$relationArticle = [];
$artTags = Db::name('taglist')->where('article_id',$id)->select();
$relationArticle = []; //相关帖子
$artTags = Db::name('taglist')->where('article_id', $id)->select();
if(count($artTags)) {
foreach($artTags as $v) {
$tag = Db::name('tag')->find($v['tag_id']);
@ -118,15 +119,15 @@ class Article extends BaseController
//上一篇下一篇
$upDownArt = $this->model->getPrevNextArticle($id,$artDetail['cate_id']);
if(empty($upDownArt['previous'][0])) {
if(empty($upDownArt['previous'])) {
$previous = '前面已经没有了!';
} else {
$previous = '<a href="' . $upDownArt['previous'][0]['url'] . '" rel="prev">' . $upDownArt['previous'][0]['title'] . '</a>';
$previous = '<a href="' . $upDownArt['previous']['url'] . '" rel="prev">' . $upDownArt['previous']['title'] . '</a>';
}
if(empty($upDownArt['next'][0])) {
if(empty($upDownArt['next'])) {
$next = '已经是最新的内容了!';
} else {
$next = '<a href="' . $upDownArt['next'][0]['url'] . '" rel="prev">' . $upDownArt['next'][0]['title'] . '</a>';
$next = '<a href="' . $upDownArt['next']['url'] . '" rel="prev">' . $upDownArt['next']['title'] . '</a>';
}
//评论
@ -139,22 +140,22 @@ class Article extends BaseController
$push_js = Db::name('push_jscode')->where(['delete_time'=>0,'type'=>1])->cache(true)->select();
View::assign([
'article' => $artDetail,
'pv' => $pv,
'artHot' => $artHot,
'tags' => $tags,
'article' => $artDetail,
'pv' => $pv,
'artHot' => $artHot,
'tags' => $tags,
'relationArticle' => $relationArticle,
'previous' => $previous,
'next' => $next,
'page' => $page,
'comments' => $comments,
'push_js' => $push_js,
'cid' => $id,
'lrDate_time' => $lrDate_time,
'userZanList' => $userZanList,
'zanCount' => $zanCount,
'jspage' => 'jie',
'passJieMi' => session('art_pass_'.$id),
'previous' => $previous,
'next' => $next,
'page' => $page,
'comments' => $comments,
'push_js' => $push_js,
'cid' => $id,
'lrDate_time' => $lrDate_time,
'userZanList' => $userZanList,
'zanCount' => $zanCount,
'jspage' => 'jie',
'passJieMi' => session('art_pass_'.$id),
$download,
]);
@ -179,7 +180,7 @@ class Article extends BaseController
$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){
@ -229,6 +230,7 @@ class Article extends BaseController
if (Request::isAjax()) {
// 检验发帖是否开放
if(config('taoler.config.is_post') == 0 ) return json(['code'=>-1,'msg'=>'抱歉,系统维护中,暂时禁止发帖!']);
// 数据
$data = Request::only(['cate_id', 'title', 'title_color','read_type','art_pass', 'content', 'upzip', 'keywords', 'description', 'captcha']);
$data['user_id'] = $this->uid;
@ -252,7 +254,7 @@ class Article extends BaseController
$iva= $this->hasIva($data['content']);
$data = array_merge($data,$iva);
// 处理内容
// 处理图片内容
$data['content'] = $this->downUrlPicsReaplace($data['content']);
// 把中文,转换为英文,并去空格->转为数组->去掉空数组->再转化为带,号的字符串
$data['keywords'] = implode(',',array_filter(explode(',',trim(str_replace('',',',$data['keywords'])))));
@ -260,30 +262,61 @@ class Article extends BaseController
// 获取分类ename,appname
$cateName = Db::name('cate')->field('ename,appname')->find($data['cate_id']);
// vip每天可免费发帖数
$user = Db::name('user')->field('id,vip,point,auth')->find($this->uid);
$postRule = Db::name('user_viprule')->field('postnum,postpoint')->where('vip', $user['vip'])->find();
// 检测可发帖子剩余量
$postLog = Db::name('user_article_log')->field('id,user_postnum')->where(['user_id' => $this->uid])->whereDay('create_time')->find();
if(is_null($postLog)) {
//没有记录创建
Db::name('user_article_log')->save(['user_id' => $this->uid, 'create_time' => time()]);
$postLog = Db::name('user_article_log')->field('id,user_postnum')->where(['user_id' => $this->uid])->whereDay('create_time')->find();
}
// 超级管理员排外
if($user['auth'] === '0') {
$cannum = $postRule['postnum'] - $postLog['user_postnum']; // 可用免费额
if($cannum <= 0) {
//额度已用完需要扣积分
$canpoint = 1 * $postRule['postpoint'];
$point = $user['point'] - $canpoint;
if($point < 0) { // 1.积分不足
return json(['code' => -1, 'msg' => "免额已使用,本次需{$canpoint}积分,请充值!"]);
}
// 2.扣除积分
Db::name('user')->where('id', $this->uid)->update(['point' => $point]);
}
}
$result = $this->model->add($data);
if ($result['code'] == 1) {
// 记录每天发帖量
Db::name('user_article_log')->where('id', $postLog['id'])->inc('user_postnum')->update();
// 获取到的最新ID
$aid = $result['data']['id'];
//写入taglist表
$tagArr = [];
if(isset($tagId)) {
$tagIdArr = explode(',',$tagId);
if(!empty($tagId)) {
$tagArr = [];
$tagIdArr = explode(',', $tagId);
foreach($tagIdArr as $tid) {
$tagArr[] = ['article_id'=>$aid,'tag_id'=>$tid,'create_time'=>time()];
$tagArr[] = [ 'article_id' => $aid, 'tag_id' => $tid, 'create_time'=>time()];
}
}
Db::name('taglist')->insertAll($tagArr);
Db::name('taglist')->insertAll($tagArr);
}
// 清除文章tag缓存
Cache::tag('tagArtDetail')->clear();
// 发提醒邮件
if(Config::get('taoler.config.email_notice')) hook('mailtohook',[$this->showUser(1)['email'],'发帖审核通知','Hi亲爱的管理员:</br>用户'.$this->showUser($this->uid)['name'].'刚刚发表了 <b>'.$data['title'].'</b> 新的帖子,请尽快处理。']);
hook('mailtohook',[$this->showUser(1)['email'],'发帖审核通知','Hi亲爱的管理员:</br>用户'.$this->showUser($this->uid)['name'].'刚刚发表了 <b>'.$data['title'].'</b> 新的帖子,请尽快处理。']);
$link = $this->getRouteUrl((int)$aid, $cateName['ename']);
$link = $this->getRouteUrl((int) $aid, $cateName['ename']);
$url = $result['data']['status'] ? $link : (string)url('index/');
hook('SeoBaiduPush', ['link'=>$link]); // 推送给百度收录接口
$url = $result['data']['status'] ? $link : (string)url('index/');
hook('callme_add', ['article_id' => (int) $aid]); // 添加文章的联系方式
return Msgres::success($result['msg'], $url);
}
return Msgres::error('add_error');
@ -354,11 +387,11 @@ class Article extends BaseController
$result = $article->edit($data);
if($result == 1) {
//处理标签
$artTags = Db::name('taglist')->where('article_id',$id)->column('tag_id','id');
if(isset($tagId)) {
if(!empty($tagId)) {
$tagIdArr = explode(',',$tagId);
$artTags = Db::name('taglist')->where('article_id',$id)->column('tag_id','id');
foreach($artTags as $aid => $tid) {
if(!in_array($tid,$tagIdArr)){
if(!in_array($tid, $tagIdArr)){
//删除被取消的tag
Db::name('taglist')->delete($aid);
}
@ -408,7 +441,7 @@ class Article extends BaseController
*/
public function delete()
{
$article = $this->model->find(input('id'));
$article = $this->model->find((int)input('id'));
$result = $article->together(['comments'])->delete();
if($result) {
return Msgres::success('delete_success');
@ -436,11 +469,14 @@ class Article extends BaseController
public function download($id)
{
$zipdir = Db::name('article')->where('id',$id)->value('upzip');
$zip = substr($zipdir,1);
Db::name('article')->cache(true)->where('id',$id)->inc('downloads')->update();
//删除缓存显示下载后数据
Cache::delete('article_'.$id);
return download($zip,'my');
if(!empty($zipdir)) {
$zip = substr($zipdir,1);
Db::name('article')->cache(true)->where('id',$id)->inc('downloads')->update();
//删除缓存显示下载后数据
Cache::delete('article_'.$id);
return download($zip,'my');
}
}
// 文章置顶、加精、评论状态

View File

@ -11,13 +11,15 @@
namespace app\index\controller;
use app\common\controller\BaseController;
use app\common\lib\facade\HttpHelper;
use think\facade\View;
use think\facade\Request;
use think\facade\Db;
use app\facade\Article;
use app\common\lib\Msgres;
use addons\pay\controller\AlipayFactory;
use addons\pay\controller\WeixinFactory;
class Index extends BaseController
{
/**
@ -29,18 +31,31 @@ class Index extends BaseController
*/
public function index()
{
// $res = get_addons_info('callme1');
// halt($res);
// $htmlString = "<p>这是一个<a href='http://example.com'>链接</a>和其他文本。</p>";
// $cleanString = preg_replace("/<a\b[^>]*>(.*?)<\/a>/is", "", $htmlString);
// //$cleanString = preg_replace("(<a [^>]*>|</a>)","",$htmlString);
// echo $cleanString;
// $ip = file_get_contents('https://myip.ipip.net');
// echo "My public IP address is: " . $ip;
// $alipay = AlipayFactory::createPayMethod();
// $weixin = WeixinFactory::createPayMethod();
// $a = $alipay->index();
// $b= $weixin->index();
// var_dump($a,$b);
$types = input('type');
//置顶文章
$artTop = Article::getArtTop(5);
//首页文章列表,显示10个
$artList = Article::getArtList(15);
//热议文章
$artHot = Article::getArtHot(10);
$artList = Article::getArtList(10);
$vs = [
'artTop' => $artTop,
'artList' => $artList,
'artHot' => $artHot,
'type' => $types,
'jspage' => '',
];
@ -48,13 +63,6 @@ class Index extends BaseController
return View::fetch();
}
//回帖榜
public function reply()
{
$comment = new \app\common\model\Comment();
return $comment->reply(20);
}
public function jump()
{

View File

@ -42,9 +42,8 @@ class Login extends BaseController
// 检验登录是否开放
if(config('taoler.config.is_login') == 0 ) return json(['code'=>-1,'msg'=>'抱歉,网站维护中,暂时不能登录哦!']);
//登陆前数据校验
$data = Request::param();
if(Config::get('taoler.config.login_captcha') == 1)
{
$data = Request::only(['name','email','phone','password','captcha','remember']);
if(Config::get('taoler.config.login_captcha') == 1) {
//先校验验证码
if(!captcha_check($data['captcha'])){
// 验证失败
@ -55,8 +54,7 @@ class Login extends BaseController
//邮箱正则表达式
$pattern = "/^([0-9A-Za-z\\-_\\.]+)@([0-9a-z]+\\.[a-z]{2,3}(\\.[a-z]{2})?)$/i";
if(preg_match("/^1[34578]\d{9}$/",$data['name']))
{
if(preg_match("/^1[34578]\d{9}$/",$data['name'])) {
//手机验证登录
$data['phone'] = $data['name'];
unset($data['name']);

View File

@ -11,7 +11,6 @@
namespace app\index\controller;
use app\common\controller\BaseController;
use think\facade\Session;
use think\facade\Request;
use think\facade\Db;
use app\common\model\Message as MessageModel;
@ -25,12 +24,8 @@ class Message extends BaseController
{
$messgeto = new MessageTo();
$num = $messgeto->getMsgNum($this->uid);
if($num){
$res = ['status' =>0,'count' => $num, 'msg' => 'ok'];
} else {
$res = ['status' =>0,'count' => 0, 'msg' => 'no message'];
}
return json($res);
if($num) return json(['status' =>0,'count' => $num, 'msg' => 'ok']);
return json(['status' =>0,'count' => 0, 'msg' => 'no message']);
}
//消息查询
@ -82,18 +77,20 @@ class Message extends BaseController
$uid = $this->uid;
$id = Request::only(['id']);
if($id['id'] == 'true'){
//删除所有此用户消息
$msg = Db::name('message_to')->where(['receve_id'=>$uid,'delete_time'=>0])->useSoftDelete('delete_time',time())->delete();
// id为'true' 删除所有此用户消息
$msg = Db::name('message_to')->where(['receve_id' => $uid])->delete();
} else {
//删除单条消息
$msg = Db::name('message_to')->where('id',$id['id'])->useSoftDelete('delete_time',time())->delete();
$msg = Db::name('message_to')->where('id', $id['id'])->delete();
}
if($msg){
$res = ['status'=>0];
return $res;
}
return $res;
}

View File

@ -15,7 +15,6 @@ use app\facade\Article;
use think\facade\View;
use think\facade\Request;
use think\facade\Db;
use app\common\model\Slider;
use app\common\model\Tag as TagModel;
class Tag extends BaseController
@ -31,22 +30,20 @@ class Tag extends BaseController
{
//
$tagEname = Request::param('ename');
$tag = Db::name('tag')->where('ename',$tagEname)->find();
$tag = Db::name('tag')->where('ename', $tagEname)->find();
$artList = Article::getAllTags($tag['id']);
$slider = new Slider();
//首页右栏
$ad_comm = $slider->getSliderList(2);
// 查询热议
$artHot = Article::getArtHot(10);
$assign = [
'tag'=>$tag,
'artList'=>$artList,
'ad_comm'=>$ad_comm,
'artHot'=>$artHot,
'jspage'=>''
'tag' => $tag,
'artList' => $artList,
'artHot' => $artHot,
'jspage' => ''
];
View::assign($assign);
return View::fetch('index');
}

View File

@ -3,7 +3,6 @@ namespace app\index\controller;
use app\common\controller\BaseController;
use app\common\validate\User as userValidate;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\Request;
use think\facade\Session;
@ -13,7 +12,6 @@ use think\facade\View;
use app\common\model\Article;
use app\common\model\Collection;
use app\common\model\User as userModel;
use app\common\model\Comment;
use taoler\com\Message;
class User extends BaseController
@ -33,13 +31,13 @@ class User extends BaseController
public function artList()
{
$param = Request::only(['page','limit']);
$myArticle = Article::field('id,cate_id,title,status,pv,create_time')
$myArticle = Article::field('id,cate_id,title,status,pv,create_time,update_time')
->withCount(['comments'])
->where(['user_id'=>$this->uid])
->order('update_time','desc')
->paginate([
'list_rows' => $param['limit'],
'page' => $param['page']
'page' => $param['page']
]);
$count = $myArticle->total();
$res = [];
@ -50,16 +48,34 @@ class User extends BaseController
$res['data'][] = ['id'=>$v['id'],
'title' => htmlspecialchars($v['title']),
'url' => $this->getRouteUrl($v['id'], $v->cate->ename, $v->cate->appname),
'status' => $v['status'] ? '正常':'待审',
'status' => $this->artStatus($v['status']),
'ctime' => $v['create_time'],
'datas' => $v['pv'].'阅/'.$v['comments_count'].'答'
'utime' => $v['update_time'],
'pv' => $v['pv'],
'datas' => $v['comments_count'].'答'
];
}
} else {
return json(['code'=>-1,'msg'=>'无数据']);
return json($res);
}
return json($res);
return json(['code'=>-1,'msg'=>'无数据']);
}
// 文章状态
private function artStatus($status)
{
switch ($status) {
case 1:
$res = '正常';
break;
case -1:
$res = '禁止';
break;
default:
$res = '待审';
break;
}
return $res;
}
// 收藏list
@ -99,6 +115,82 @@ class User extends BaseController
{
return View::fetch();
}
// 编辑pv
public function edtiPv()
{
if(Request::isAjax()){
$param = Request::param(['id','pv']);
$res = Db::name('article')->save(['id' => $param['id'], 'pv' => $param['pv']]);
if($res) {
return json(['code' => 0, 'msg' => '修改成功!']);
}
}
return json(['code' => -1, 'msg' => '修改失败!']);
}
// 刷新
public function updateTime()
{
if(Request::isAjax()){
$param = Request::param(['data']);
if(count($param) == 0) return json(['code' => -1, 'msg' => '未选中任何数据!']);
$idArr = [];
foreach($param['data'] as $v) {
$idArr[] = $v['id'];
}
$count = count($idArr);
// vip每天可刷新数
$user = Db::name('user')->field('id,vip,point,auth')->find($this->uid);
$refreshRule = Db::name('user_viprule')->field('refreshnum,refreshpoint')->where('vip', $user['vip'])->find();
// 检测刷新帖子剩余量
$refreshLog = Db::name('user_article_log')->field('id,user_refreshnum')->where(['user_id' => $this->uid])->whereDay('create_time')->find();
if(is_null($refreshLog)) {// 新增
Db::name('user_article_log')->save(['user_id' => $this->uid, 'create_time' => time()]);
$refreshLog = Db::name('user_article_log')->field('id,user_refreshnum')->where(['user_id' => $this->uid])->whereDay('create_time')->find();
}
// 超级管理员排外
if($user['auth'] === '0') {
$cannum = $refreshRule['refreshnum'] - $refreshLog['user_refreshnum']; // 可用免费数
// 刷帖先扣积分
if($cannum <= 0) { // a.免费额已用完 后面需要积分
$canpoint = $count * $refreshRule['refreshpoint'];
$point = $user['point'] - $canpoint;
if($point < 0) {
// 1.积分不足
return json(['code' => -1, 'msg' => "免额已使用,本次需{$canpoint}积分,请充值!"]);
} else {
// 2.扣除积分
Db::name('user')->where('id', $this->uid)->update(['point' => $point]);
}
} else { // b.未超限 有剩余条数
if($count > $cannum) { // 本次刷新数量大于剩余免费数量,需要支付积分
$canpoint = ($count - $cannum) * $refreshRule['refreshpoint'];
$point = $user['point'] - $canpoint;
if($point < 0) {
// 1.积分不足
return json(['code' => -1, 'msg' => "免额已使用,本次需{$canpoint}积分,额度不足请充值!"]);
} else {
// 2.扣除积分
Db::name('user')->where('id', $this->uid)->update(['point' => $point]);
}
}
}
}
// 刷新数据
$res = Db::name('article')->where('id', 'in', $idArr)->update(['update_time' => time()]);
if($res > 0) {
// 记录刷帖日志
Db::name('user_article_log')->where('id', $refreshLog['id'])->inc('user_refreshnum', $count)->update();
return json(['code' => 0, 'msg' => '刷新成功!']);
}
}
return json(['code' => -1, 'msg' => '刷新失败!']);
}
//取消文章收藏
public function colltDel()
@ -119,7 +211,7 @@ class User extends BaseController
public function set()
{
if(Request::isAjax()){
$data = Request::only(['email','nickname','sex','city','area_id','sign']);
$data = Request::only(['email','phone','nickname','sex','city','area_id','sign']);
$data['user_id'] = $this->uid;
// 过滤
$sign = strtolower($data['sign']);
@ -209,11 +301,8 @@ class User extends BaseController
public function home($id)
{
//用户
$u = Cache::get('user'.$id);
if(!$u){
$u = Db::name('user')->field('name,nickname,city,sex,sign,user_img,point,vip,create_time')->cache(3600)->find($id);
}
$u = Db::name('user')->field('name,nickname,city,sex,sign,user_img,point,vip,create_time')->find($id);
$article = new Article();
$arts = $article->getUserArtList((int) $id);
@ -228,7 +317,8 @@ class User extends BaseController
->field('a.id,a.title,t.ename,c.content,c.create_time,c.delete_time,c.status')
->where(['a.delete_time'=>0,'c.delete_time'=>0,'c.status'=>1])
->where('c.user_id',$id)
->order(['c.create_time'=>'desc'])
->order(['c.id'=>'desc'])
->limit(10)
->cache(3600)->select();
View::assign(['u'=>$u,'arts'=>$arts,'reys'=>$reys,'jspage'=>'']);
@ -278,15 +368,15 @@ class User extends BaseController
return json(['code'=>-1,'msg' =>$validate->getError()]);
}
$user = new userModel;
$result = $user->setpass($data);
$user = new userModel;
$result = $user->setpass($data);
if($result == 1) {
Session::clear();
Cookie::delete('auth');
return $this->success('密码修改成功 请登录', (string) url('login/index'));
} else {
return json(['code'=>-1,'msg' =>$result]);
return json(['code' => 1, 'msg' => '密码修改成功', 'data' => ['url' => (string) url('login/index')]]);
}
return json(['code' => -1,'msg' =>$result]);
}
}

View File

@ -31,6 +31,8 @@ Route::group(function () {
Route::get('user/message$', 'user/message');
Route::get('user/post', 'user/post');
Route::get('user/article','user/artList');
Route::post('user/editpv','user/editPv');
Route::post('user/updatetime','user/updateTime');
Route::get('user/coll','user/collList');
Route::get('user/colldel','user/collDel');
Route::get('user/setpass','user/setPass');

View File

@ -74,7 +74,8 @@ CREATE TABLE `tao_article` (
`delete_time` int NOT NULL DEFAULT 0 COMMENT '删除时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `user_id`(`user_id`) USING BTREE COMMENT '文章的用户索引',
INDEX `cate_id`(`cate_id`) USING BTREE COMMENT '文章分类索引'
INDEX `cate_id`(`cate_id`) USING BTREE COMMENT '文章分类索引',
INDEX `idx_article_create_time`(`create_time` DESC) USING BTREE COMMENT '创建时间'
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '文章表' ROW_FORMAT = Dynamic;
-- ----------------------------
@ -213,7 +214,7 @@ INSERT INTO `tao_auth_rule` VALUES (64, 'user.user/edit', 'Edit user', 1, 1, 60,
INSERT INTO `tao_auth_rule` VALUES (65, 'user.user/delete', 'Delete user', 1, 1, 60, 2, '', 2, 54, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (66, 'user.user/check', 'Check user', 1, 1, 60, 2, '', 2, 55, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (67, 'user.user/auth', 'Superuser', 1, 1, 60, 2, '', 2, 56, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (68, 'user.vip/index', '用户vip', 1, 1, 2, 1, '', 1, 2, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (68, 'user.vip/index', '会员等级', 1, 1, 2, 1, '', 1, 2, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (69, 'user.vip/list', 'vip列表', 1, 1, 68, 2, '', 2, 50, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (70, 'user.vip/add', '添加vip', 1, 1, 68, 2, '', 2, 51, '', 0, 0, 0);
INSERT INTO `tao_auth_rule` VALUES (71, 'user.vip/edit', '编辑vip', 1, 1, 68, 2, '', 2, 52, '', 0, 0, 0);
@ -429,7 +430,8 @@ CREATE TABLE `tao_message_to` (
`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
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_mesto_receveid`(`receve_id`) USING BTREE COMMENT '收件人ID'
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '消息详细表' ROW_FORMAT = Dynamic;
-- ----------------------------
@ -606,6 +608,20 @@ INSERT INTO `tao_user_area` VALUES (2, '上海', '沪', 0, 0, 0);
INSERT INTO `tao_user_area` VALUES (3, '广州', '广', 0, 0, 0);
INSERT INTO `tao_user_area` VALUES (4, '深圳', '', 0, 0, 0);
-- ----------------------------
-- Table structure for tao_user_article_log
-- ----------------------------
DROP TABLE IF EXISTS `tao_user_article_log`;
CREATE TABLE `tao_user_article_log` (
`id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` int NOT NULL COMMENT '用户ID',
`user_postnum` int NOT NULL DEFAULT 0 COMMENT '用户发帖数量',
`user_refreshnum` int NOT NULL DEFAULT 0 COMMENT '用户刷新数量',
`create_time` int NOT NULL DEFAULT 0 COMMENT '记录时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `uid`(`user_id` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户发文刷新日志记录' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for tao_user_sign
-- ----------------------------
@ -649,10 +665,14 @@ INSERT INTO `tao_user_signrule` VALUES (4, 7, 10, 1677824262, 1677824262, 0);
DROP TABLE IF EXISTS `tao_user_viprule`;
CREATE TABLE `tao_user_viprule` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '用户等级ID',
`score` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '积分区间',
`vip` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'vip等级',
`score` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '积分区间',
`nick` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '认证昵称',
`rules` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '权限',
`postnum` int NOT NULL DEFAULT 10 COMMENT '日发帖数量',
`postpoint` int NOT NULL DEFAULT 0 COMMENT '发文扣积分',
`refreshnum` int NOT NULL DEFAULT 10 COMMENT '日刷贴数量',
`refreshpoint` int NOT NULL DEFAULT 0 COMMENT '刷帖扣积分',
`create_time` int NOT NULL DEFAULT 0 COMMENT '创建时间',
`update_time` int NOT NULL DEFAULT 0 COMMENT '升级时间',
`delete_time` int NOT NULL DEFAULT 0 COMMENT '删除时间',
@ -662,12 +682,12 @@ CREATE TABLE `tao_user_viprule` (
-- ----------------------------
-- Records of tao_user_viprule
-- ----------------------------
INSERT INTO `tao_user_viprule` VALUES (1, '0-99', 0, '游民', '0', 1585476523, 1585544577, 0);
INSERT INTO `tao_user_viprule` VALUES (2, '100-299', 1, '富农', '1', 1585476551, 1677823895, 0);
INSERT INTO `tao_user_viprule` VALUES (3, '300-500', 2, '地主', '0', 1585545450, 1585546241, 0);
INSERT INTO `tao_user_viprule` VALUES (4, '501-699', 3, '土豪', '0', 1585545542, 1585569657, 0);
INSERT INTO `tao_user_viprule` VALUES (5, '700-899', 4, '霸主', '0', 1677824242, 1677824242, 0);
INSERT INTO `tao_user_viprule` VALUES (6, '900-1000', 5, '王爷', '0', 1677824859, 1677824859, 0);
INSERT INTO `tao_user_viprule` VALUES (1, 0, '0-99', '游民', '0', 2, 2, 10, 1, 1585476523, 1698763623, 0);
INSERT INTO `tao_user_viprule` VALUES (2, 1, '100-299', '富农', '1', 50, 0, 10, 0, 1585476551, 1698740135, 0);
INSERT INTO `tao_user_viprule` VALUES (3, 2, '300-500', '地主', '0', 100, 0, 0, 0, 1585545450, 1698733320, 0);
INSERT INTO `tao_user_viprule` VALUES (4, 3, '501-699', '土豪', '0', 10, 0, 100, 0, 1585545542, 1698746583, 0);
INSERT INTO `tao_user_viprule` VALUES (5, 4, '700-899', '霸主', '0', 10, 0, 0, 0, 1677824242, 1677824242, 0);
INSERT INTO `tao_user_viprule` VALUES (6, 5, '900-1000', '王爷', '0', 10, 0, 0, 0, 1677824859, 1677824859, 0);
-- ----------------------------
-- Table structure for tao_user_zan

View File

@ -33,52 +33,36 @@ class UserLogin
$url = 'http://ip-api.com/json/' . $ip . '?lang=zh-CN&fields=57361';
$city = 'earth';
// 登录日志
Log::channel('login')->info('login:{user} {ip}',['user'=>$u->name,'ip'=>$ip]);
//日志
if($type == 'log'){
//$name = $user->user['name'];
try{
$ipInfo = HttpHelper::get($url)->toJson();
if($ipInfo->status == 'success')
{
if($ipInfo->status == 'success') {
$city = $ipInfo->city;
}
$data = [
'city' => $city,
'last_login_ip' => $ip,
'last_login_time' => time(),
'login_error_num' => 0
];
} catch (\Exception $e) {
// echo $e->getMessage();
}
//国内查询,接口已失效
// $url = 'http://freeapi.ipip.net/' . $ip;
// $ipJson = Api::urlGetRespond($url);
// $respond = $ipJson->getData();
// if($respond['code'] == 0){
// //字符串数组["中国","北京","北京"]
// $data = $respond['data'];
// //正则去掉[''],保留字符串
// $str = preg_replace('/(\"|\[|\])/','',$data);
// //地址数组
// $arr = explode(',', $str);
// $city = 'earth';
// if($arr[0] !== '本机地址') {
// $city = $arr[2];
// }
// }
}
if($type == 'logError'){
$u->allowField(['login_error_num','login_error_time'])->save(['login_error_num'=>$u->login_error_num + 1,'login_error_time'=>time()]);
// 登录失败 失败次数加1
if($type == 'logError') {
$data = [
'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]);
$u->allowField(['city','last_login_ip','last_login_time','login_error_num'])->save($data);
}
}

View File

@ -0,0 +1,117 @@
<?php
/*
* @Author: TaoLer <alipey_tao@qq.com>
* @Date: 2021-12-06 16:04:50
* @LastEditTime: 2022-04-22 06:24:03
* @LastEditors: TaoLer
* @Description: 搜索引擎SEO优化设置
* @FilePath: \TaoLer\app\middleware\Auth.php
* Copyright (c) 2020~2022 http://www.aieok.com All rights reserved.
*/
declare(strict_types=1);
namespace app\middleware;
use taoser\think\Auth as UserAuth;
use think\facade\Session;
use think\facade\Cookie;
use think\facade\Db;
use think\facade\Config;
use think\facade\Request;
class AdminAuth
{
/**
* 处理请求
*
* @param Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
// var_dump(Request::url(),Request::pathinfo(),$request->baseUrl(),$request->controller());
//访问路径
// $path = app('http')->getName().'/'.stristr($request->pathinfo(),".html",true);
$path = stristr($request->pathinfo(),".html",true) ?: Request::pathinfo();
// var_dump($path);
//登陆前获取加密的Cookie
$cooAuth = Cookie::get('adminAuth');
if(!empty($cooAuth)){
$resArr = explode(':',$cooAuth);
$userId = end($resArr);
//检验用户
$user = Db::name('admin')->where('id',$userId)->find();
if(!empty($user)){
//验证cookie
$salt = Config::get('taoler.salt');
$auth = md5($user['username'].$salt).":".$userId;
if($auth == $cooAuth){
Session::set('admin_name',$user['username']);
Session::set('admin_id',$userId);
}
}
}
// //没有登录及当前非登录页重定向登录页
// if(!Session::has('admin_id') && $path !== 'admin/login/index' && !(stristr($request->pathinfo(),"captcha.html") || stristr($request->pathinfo(),"addons")) )
// {
// return redirect((string) url('login/index'));
// }
// //登陆后无法访问登录页
// if(Session::has('admin_id') && $path == 'admin/login/index'){
// return redirect((string) url('index/index'));
// }
// // 排除公共权限
// $not_check = ['admin/','index/index', 'admin/menu/getMenuNavbar','admin/login/index','admin/index/index','admin/index/home','admin/Admin/info','admin/Admin/repass','admin/Admin/logout','admin/Index/news','admin/Index/cunsult','admin/Index/replys','admin/Index/reply','admin/captcha','addons/socail/','admin/addons/social/oauth/login','admin/addons/bacimg/index/getImages'];
//没有登录及当前非登录页重定向登录页
if(!Session::has('admin_id') && $path !== 'login/index' && !(stristr($request->pathinfo(),"captcha.html") || stristr($request->pathinfo(),"addons")) )
{
return redirect((string) url('login/index'));
}
//登陆后无法访问登录页
if(Session::has('admin_id') && $path == 'login/index' || $path == ''){
return redirect((string) url('index/index'));
}
// 排除公共权限
$not_check = [
'captcha',
'login/index',
'admin/index',
'system.menu/getnav',
'index/index',
'index/console1',
'index/console2',
'index/news',
'menu/getMenuNavbar',
'index/home',
'Admin/info',
'system.admin/repass',
'system.admin/logout',
'Index/cunsult',
'Index/replys',
'Index/reply',
'admin/captcha',
'addons/socail/',
'addons/social/oauth/login',
'addons/bacimg/index/getImages'
];
if (!in_array($path, $not_check)) {
$auth = new UserAuth();
$admin_id = Session::get('admin_id'); //登录用户的id
if (!$auth->check($path, $admin_id) && $admin_id != 1) {
//return view('public/auth');
//return response("<script>alert('没有操作权限')</script>");
return json(['code'=>-1,'msg'=>'无权限']);
}
}
return $next($request);
}
}

View File

@ -1,117 +1,31 @@
<?php
/*
* @Author: TaoLer <alipey_tao@qq.com>
* @Date: 2021-12-06 16:04:50
* @LastEditTime: 2022-04-22 06:24:03
* @LastEditors: TaoLer
* @Description: 搜索引擎SEO优化设置
* @FilePath: \TaoLer\app\middleware\Auth.php
* Copyright (c) 2020~2022 http://www.aieok.com All rights reserved.
*/
declare(strict_types=1);
namespace app\middleware;
use taoser\think\Auth as UserAuth;
use think\facade\Session;
use think\facade\Cookie;
use think\facade\Db;
use think\facade\Config;
use think\facade\Request;
use app\common\lib\JwtAuth;
class Auth
{
/**
* 处理请求
*
* @param Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
// var_dump(Request::url(),Request::pathinfo(),$request->baseUrl(),$request->controller());
//访问路径
// $path = app('http')->getName().'/'.stristr($request->pathinfo(),".html",true);
$path = stristr($request->pathinfo(),".html",true) ?: Request::pathinfo();
// var_dump($path);
//登陆前获取加密的Cookie
$cooAuth = Cookie::get('adminAuth');
$header = $request->header();
if(!empty($cooAuth)){
$resArr = explode(':',$cooAuth);
$userId = end($resArr);
//检验用户
$user = Db::name('admin')->where('id',$userId)->find();
if(!empty($user)){
//验证cookie
$salt = Config::get('taoler.salt');
$auth = md5($user['username'].$salt).":".$userId;
if($auth == $cooAuth){
Session::set('admin_name',$user['username']);
Session::set('admin_id',$userId);
}
if(isset($header['authorization'])) {
$token = trim(ltrim($request->header('authorization'), 'Bearer'));
try{
$data = JwtAuth::decode($token);
$request->uid = $data->uid;
} catch(\Exception $e) {
return json(['code' => -1, 'msg' => $e->getMessage()]);
}
} else {
return json(['code' => -1, 'msg' => 'no auth']);
}
// //没有登录及当前非登录页重定向登录页
// if(!Session::has('admin_id') && $path !== 'admin/login/index' && !(stristr($request->pathinfo(),"captcha.html") || stristr($request->pathinfo(),"addons")) )
// {
// return redirect((string) url('login/index'));
// }
// //登陆后无法访问登录页
// if(Session::has('admin_id') && $path == 'admin/login/index'){
// return redirect((string) url('index/index'));
// }
// // 排除公共权限
// $not_check = ['admin/','index/index', 'admin/menu/getMenuNavbar','admin/login/index','admin/index/index','admin/index/home','admin/Admin/info','admin/Admin/repass','admin/Admin/logout','admin/Index/news','admin/Index/cunsult','admin/Index/replys','admin/Index/reply','admin/captcha','addons/socail/','admin/addons/social/oauth/login','admin/addons/bacimg/index/getImages'];
//没有登录及当前非登录页重定向登录页
if(!Session::has('admin_id') && $path !== 'login/index' && !(stristr($request->pathinfo(),"captcha.html") || stristr($request->pathinfo(),"addons")) )
{
return redirect((string) url('login/index'));
}
//登陆后无法访问登录页
if(Session::has('admin_id') && $path == 'login/index' || $path == ''){
return redirect((string) url('index/index'));
}
// 排除公共权限
$not_check = [
'captcha',
'login/index',
'admin/index',
'system.menu/getnav',
'index/index',
'index/console1',
'index/console2',
'index/news',
'menu/getMenuNavbar',
'index/home',
'Admin/info',
'system.admin/repass',
'system.admin/logout',
'Index/cunsult',
'Index/replys',
'Index/reply',
'admin/captcha',
'addons/socail/',
'addons/social/oauth/login',
'addons/bacimg/index/getImages'
];
if (!in_array($path, $not_check)) {
$auth = new UserAuth();
$admin_id = Session::get('admin_id'); //登录用户的id
if (!$auth->check($path, $admin_id) && $admin_id != 1) {
//return view('public/auth');
//return response("<script>alert('没有操作权限')</script>");
return json(['code'=>-1,'msg'=>'无权限']);
}
}
return $next($request);
return $next($request);
}
}

33
app/middleware/Auths.php Normal file
View File

@ -0,0 +1,33 @@
<?php
namespace app\middleware;
use app\common\lib\JwtAuth;
class Auths
{
public function handle($request, \Closure $next)
{
$header = $request->header();
if(isset($header['authorization'])) {
$token = trim(ltrim($request->header('authorization'), 'Bearer'));
try{
$data = JwtAuth::decode($token);
$request->uid = $data->uid;
} catch(\Exception $e) {
return $e->getMessage();
}
} else {
return json(['code' => -1, 'msg' => 'no auth']);
}
//登陆前获取加密的Cookie
return $next($request);
}
}

View File

@ -1,17 +1,20 @@
<?php
namespace app\middleware;
use think\facade\Request;
use think\facade\Log;
/**
* 浏览记录日志中间件
*/
class Browse
{
public function handle($request, \Closure $next)
{
$agent = $_SERVER['HTTP_USER_AGENT'];
$ip = $_SERVER['REMOTE_ADDR'];
$url = Request::url(true);
$agent = $request->header('user-agent');
$ip = $request->ip();
$url = $request->url(true);
Log::channel('browse')->info('browse:{agent} {ip} {url}',['agent'=>$agent,'url'=>$url,'ip'=>$ip]);
return $next($request);
return $next($request);
}
}

View File

@ -24,8 +24,6 @@
"topthink/think-view": "^1.0",
"topthink/think-captcha": "^3.0",
"phpmailer/phpmailer": "^6.1",
"lotofbadcode/phpspirit_databackup": "^1.1",
"wamkj/thinkphp6.0-databackup": "^1.0",
"taoser/think-addons": "^1.0",
"liliuwei/thinkphp-social": "^1.3",
"taoser/think-setarr": "^0.0.3",
@ -38,7 +36,9 @@
"workerman/phpsocket.io": "^1.1",
"jaeger/querylist": "^4.2",
"symfony/var-exporter": "^5.4",
"yzh52521/easyhttp": "^1.0"
"yzh52521/easyhttp": "^1.0",
"firebase/php-jwt": "^6.8",
"overtrue/easy-sms": "^2.5"
},
"require-dev": {
"symfony/var-dumper": "^4.2",

438
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "20dad4ba0451f20b1191711c63ad21c7",
"content-hash": "6be3b456c215d7ae6d3ba8a28f6697b4",
"packages": [
{
"name": "bacon/bacon-qr-code",
@ -257,16 +257,16 @@
},
{
"name": "dasprid/enum",
"version": "1.0.4",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/DASPRiD/Enum.git",
"reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f"
"reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
"reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/6faf451159fb8ba4126b925ed2d78acfce0dc016",
"reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016",
"shasum": ""
},
"require": {
@ -301,9 +301,9 @@
],
"support": {
"issues": "https://github.com/DASPRiD/Enum/issues",
"source": "https://github.com/DASPRiD/Enum/tree/1.0.4"
"source": "https://github.com/DASPRiD/Enum/tree/1.0.5"
},
"time": "2023-03-01T18:44:03+00:00"
"time": "2023-08-25T16:18:39+00:00"
},
{
"name": "endroid/qr-code",
@ -377,6 +377,69 @@
],
"time": "2022-10-26T08:48:17+00:00"
},
{
"name": "firebase/php-jwt",
"version": "v6.10.0",
"source": {
"type": "git",
"url": "https://github.com/firebase/php-jwt.git",
"reference": "a49db6f0a5033aef5143295342f1c95521b075ff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/a49db6f0a5033aef5143295342f1c95521b075ff",
"reference": "a49db6f0a5033aef5143295342f1c95521b075ff",
"shasum": ""
},
"require": {
"php": "^7.4||^8.0"
},
"require-dev": {
"guzzlehttp/guzzle": "^6.5||^7.4",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5",
"psr/cache": "^1.0||^2.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0"
},
"suggest": {
"ext-sodium": "Support EdDSA (Ed25519) signatures",
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
},
"type": "library",
"autoload": {
"psr-4": {
"Firebase\\JWT\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Neuman Vong",
"email": "neuman+pear@twilio.com",
"role": "Developer"
},
{
"name": "Anant Narayanan",
"email": "anant@php.net",
"role": "Developer"
}
],
"description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
"homepage": "https://github.com/firebase/php-jwt",
"keywords": [
"jwt",
"php"
],
"support": {
"issues": "https://github.com/firebase/php-jwt/issues",
"source": "https://github.com/firebase/php-jwt/tree/v6.10.0"
},
"time": "2023-12-01T16:26:39+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "7.0.0",
@ -648,21 +711,21 @@
},
{
"name": "jaeger/g-http",
"version": "V1.7.2",
"version": "V1.7.3",
"source": {
"type": "git",
"url": "https://github.com/jae-jae/GHttp.git",
"reference": "82585ddd5e2c6651e37ab1d8166efcdbb6b293d4"
"reference": "035fe0ff6e3e0390769647ce14694875bf02cf22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jae-jae/GHttp/zipball/82585ddd5e2c6651e37ab1d8166efcdbb6b293d4",
"reference": "82585ddd5e2c6651e37ab1d8166efcdbb6b293d4",
"url": "https://api.github.com/repos/jae-jae/GHttp/zipball/035fe0ff6e3e0390769647ce14694875bf02cf22",
"reference": "035fe0ff6e3e0390769647ce14694875bf02cf22",
"shasum": ""
},
"require": {
"cache/filesystem-adapter": "^1",
"guzzlehttp/guzzle": "^6.0 | ^7.0"
"guzzlehttp/guzzle": "^6.0 || ^7.0"
},
"type": "library",
"autoload": {
@ -683,9 +746,9 @@
"description": "Simple Http client base on GuzzleHttp",
"support": {
"issues": "https://github.com/jae-jae/GHttp/issues",
"source": "https://github.com/jae-jae/GHttp/tree/V1.7.2"
"source": "https://github.com/jae-jae/GHttp/tree/V1.7.3"
},
"time": "2021-08-08T04:59:44+00:00"
"time": "2024-03-24T14:55:49+00:00"
},
{
"name": "jaeger/phpquery-single",
@ -736,16 +799,16 @@
},
{
"name": "jaeger/querylist",
"version": "V4.2.8",
"version": "V4.2.9",
"source": {
"type": "git",
"url": "https://github.com/jae-jae/QueryList.git",
"reference": "39dc0ca9c668bec7a793e20472ccd7d26ef89ea4"
"reference": "7aae3aed38214d3d7096174faf49f6c41b2dd550"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jae-jae/QueryList/zipball/39dc0ca9c668bec7a793e20472ccd7d26ef89ea4",
"reference": "39dc0ca9c668bec7a793e20472ccd7d26ef89ea4",
"url": "https://api.github.com/repos/jae-jae/QueryList/zipball/7aae3aed38214d3d7096174faf49f6c41b2dd550",
"reference": "7aae3aed38214d3d7096174faf49f6c41b2dd550",
"shasum": ""
},
"require": {
@ -753,11 +816,10 @@
"jaeger/g-http": "^1.1",
"jaeger/phpquery-single": "^1",
"php": ">=7.1",
"tightenco/collect": ">5.0"
"symfony/var-dumper": ">3.4"
},
"require-dev": {
"phpunit/phpunit": "^8.5",
"symfony/var-dumper": "^3.3"
"phpunit/phpunit": "^8.5"
},
"type": "library",
"autoload": {
@ -784,7 +846,7 @@
],
"support": {
"issues": "https://github.com/jae-jae/QueryList/issues",
"source": "https://github.com/jae-jae/QueryList/tree/V4.2.8"
"source": "https://github.com/jae-jae/QueryList/tree/V4.2.9"
},
"funding": [
{
@ -792,20 +854,20 @@
"type": "open_collective"
}
],
"time": "2021-07-05T06:07:58+00:00"
"time": "2024-04-12T06:29:50+00:00"
},
{
"name": "laravel/serializable-closure",
"version": "v1.3.1",
"version": "v1.3.3",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
"reference": "e5a3057a5591e1cfe8183034b0203921abe2c902"
"reference": "3dbf8a8e914634c48d389c1234552666b3d43754"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/e5a3057a5591e1cfe8183034b0203921abe2c902",
"reference": "e5a3057a5591e1cfe8183034b0203921abe2c902",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3dbf8a8e914634c48d389c1234552666b3d43754",
"reference": "3dbf8a8e914634c48d389c1234552666b3d43754",
"shasum": ""
},
"require": {
@ -852,7 +914,7 @@
"issues": "https://github.com/laravel/serializable-closure/issues",
"source": "https://github.com/laravel/serializable-closure"
},
"time": "2023-07-14T13:56:28+00:00"
"time": "2023-11-08T14:08:06+00:00"
},
{
"name": "league/flysystem",
@ -950,26 +1012,26 @@
},
{
"name": "league/mime-type-detection",
"version": "1.11.0",
"version": "1.15.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/mime-type-detection.git",
"reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd"
"reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
"reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301",
"reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"php": "^7.2 || ^8.0"
"php": "^7.4 || ^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.2",
"phpstan/phpstan": "^0.12.68",
"phpunit/phpunit": "^8.5.8 || ^9.3"
"phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0"
},
"type": "library",
"autoload": {
@ -990,7 +1052,7 @@
"description": "Mime-type detection for Flysystem",
"support": {
"issues": "https://github.com/thephpleague/mime-type-detection/issues",
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0"
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.15.0"
},
"funding": [
{
@ -1002,7 +1064,7 @@
"type": "tidelift"
}
],
"time": "2022-04-17T13:12:02+00:00"
"time": "2024-01-28T23:22:08+00:00"
},
{
"name": "liliuwei/thinkphp-social",
@ -1080,61 +1142,83 @@
"time": "2021-01-13T05:11:12+00:00"
},
{
"name": "lotofbadcode/phpspirit_databackup",
"version": "v1.2",
"name": "overtrue/easy-sms",
"version": "2.6.0",
"source": {
"type": "git",
"url": "https://github.com/lotofbadcode/phpspirit_databackup.git",
"reference": "77c2421f8461392c044cf8c29918f495c22a5612"
"url": "https://github.com/overtrue/easy-sms.git",
"reference": "bb88b244f0de8d1f74bc50c4c08414f4c5f30281"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lotofbadcode/phpspirit_databackup/zipball/77c2421f8461392c044cf8c29918f495c22a5612",
"reference": "77c2421f8461392c044cf8c29918f495c22a5612",
"url": "https://api.github.com/repos/overtrue/easy-sms/zipball/bb88b244f0de8d1f74bc50c4c08414f4c5f30281",
"reference": "bb88b244f0de8d1f74bc50c4c08414f4c5f30281",
"shasum": ""
},
"require": {
"php": ">=7.0"
"ext-json": "*",
"guzzlehttp/guzzle": "^6.2 || ^7.0",
"php": ">=5.6"
},
"require-dev": {
"brainmaestro/composer-git-hooks": "^2.8",
"jetbrains/phpstorm-attributes": "^1.0",
"mockery/mockery": "~1.3.3 || ^1.4.2",
"phpunit/phpunit": "^5.7 || ^7.5 || ^8.5.19 || ^9.5.8"
},
"type": "library",
"extra": {
"hooks": {
"pre-commit": [
"composer check-style",
"composer psalm",
"composer test"
],
"pre-push": [
"composer check-style"
]
}
},
"autoload": {
"psr-4": {
"phpspirit\\databackup\\": "src/"
"Overtrue\\EasySms\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
"MIT"
],
"authors": [
{
"name": "代码庸医",
"email": "3359964266@qq.com"
"name": "overtrue",
"email": "i@overtrue.me"
}
],
"description": "一个PHP数据库备份恢复的插件",
"keywords": [
"library",
"php"
],
"description": "The easiest way to send short message.",
"support": {
"issues": "https://github.com/lotofbadcode/phpspirit_databackup/issues",
"source": "https://github.com/lotofbadcode/phpspirit_databackup/tree/v1.2"
"issues": "https://github.com/overtrue/easy-sms/issues",
"source": "https://github.com/overtrue/easy-sms/tree/2.6.0"
},
"time": "2023-05-12T12:02:05+00:00"
"funding": [
{
"url": "https://github.com/overtrue",
"type": "github"
}
],
"time": "2024-03-08T06:36:45+00:00"
},
{
"name": "php-di/invoker",
"version": "2.3.3",
"version": "2.3.4",
"source": {
"type": "git",
"url": "https://github.com/PHP-DI/Invoker.git",
"reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786"
"reference": "33234b32dafa8eb69202f950a1fc92055ed76a86"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/cd6d9f267d1a3474bdddf1be1da079f01b942786",
"reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786",
"url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/33234b32dafa8eb69202f950a1fc92055ed76a86",
"reference": "33234b32dafa8eb69202f950a1fc92055ed76a86",
"shasum": ""
},
"require": {
@ -1168,7 +1252,7 @@
],
"support": {
"issues": "https://github.com/PHP-DI/Invoker/issues",
"source": "https://github.com/PHP-DI/Invoker/tree/2.3.3"
"source": "https://github.com/PHP-DI/Invoker/tree/2.3.4"
},
"funding": [
{
@ -1176,7 +1260,7 @@
"type": "github"
}
],
"time": "2021-12-13T09:22:56+00:00"
"time": "2023-09-08T09:24:21+00:00"
},
{
"name": "php-di/php-di",
@ -1298,16 +1382,16 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.8.0",
"version": "v6.9.1",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "df16b615e371d81fb79e506277faea67a1be18f1"
"reference": "039de174cd9c17a8389754d3b877a2ed22743e18"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/df16b615e371d81fb79e506277faea67a1be18f1",
"reference": "df16b615e371d81fb79e506277faea67a1be18f1",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/039de174cd9c17a8389754d3b877a2ed22743e18",
"reference": "039de174cd9c17a8389754d3b877a2ed22743e18",
"shasum": ""
},
"require": {
@ -1317,16 +1401,17 @@
"php": ">=5.5.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.2",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"doctrine/annotations": "^1.2.6 || ^1.13.3",
"php-parallel-lint/php-console-highlighter": "^1.0.0",
"php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.7.1",
"squizlabs/php_codesniffer": "^3.7.2",
"yoast/phpunit-polyfills": "^1.0.4"
},
"suggest": {
"decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication",
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"ext-openssl": "Needed for secure SMTP sending and DKIM signing",
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
@ -1366,7 +1451,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.8.0"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.1"
},
"funding": [
{
@ -1374,7 +1459,7 @@
"type": "github"
}
],
"time": "2023-03-06T14:43:22+00:00"
"time": "2023-11-25T22:23:28+00:00"
},
{
"name": "psr/cache",
@ -1525,16 +1610,16 @@
},
{
"name": "psr/http-client",
"version": "1.0.2",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31"
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
@ -1571,9 +1656,9 @@
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client/tree/1.0.2"
"source": "https://github.com/php-fig/http-client"
},
"time": "2023-04-10T20:12:12+00:00"
"time": "2023-09-23T14:17:50+00:00"
},
{
"name": "psr/http-message",
@ -1775,16 +1860,16 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"version": "v1.29.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"shasum": ""
},
"require": {
@ -1798,9 +1883,6 @@
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@ -1838,7 +1920,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0"
},
"funding": [
{
@ -1854,20 +1936,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2024-01-29T20:11:03+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.27.0",
"version": "v1.29.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
"reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25",
"reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25",
"shasum": ""
},
"require": {
@ -1875,9 +1957,6 @@
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@ -1914,7 +1993,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php72/tree/v1.29.0"
},
"funding": [
{
@ -1930,20 +2009,20 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2024-01-29T20:11:03+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.27.0",
"version": "v1.29.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
"reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
"reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
"shasum": ""
},
"require": {
@ -1951,9 +2030,6 @@
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@ -1997,7 +2073,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0"
},
"funding": [
{
@ -2013,7 +2089,7 @@
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
"time": "2024-01-29T20:11:03+00:00"
},
{
"name": "symfony/var-dumper",
@ -2106,16 +2182,16 @@
},
{
"name": "symfony/var-exporter",
"version": "v5.4.26",
"version": "v5.4.35",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-exporter.git",
"reference": "11401fe94f960249b3c63a488c63ba73091c1e4a"
"reference": "abb0a151b62d6b07e816487e20040464af96cae7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/11401fe94f960249b3c63a488c63ba73091c1e4a",
"reference": "11401fe94f960249b3c63a488c63ba73091c1e4a",
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/abb0a151b62d6b07e816487e20040464af96cae7",
"reference": "abb0a151b62d6b07e816487e20040464af96cae7",
"shasum": ""
},
"require": {
@ -2159,7 +2235,7 @@
"serialize"
],
"support": {
"source": "https://github.com/symfony/var-exporter/tree/v5.4.26"
"source": "https://github.com/symfony/var-exporter/tree/v5.4.35"
},
"funding": [
{
@ -2175,7 +2251,7 @@
"type": "tidelift"
}
],
"time": "2023-07-20T07:21:16+00:00"
"time": "2024-01-23T13:51:25+00:00"
},
{
"name": "taoser/think-addons",
@ -2327,60 +2403,6 @@
},
"time": "2022-04-16T23:08:43+00:00"
},
{
"name": "tightenco/collect",
"version": "v8.83.27",
"source": {
"type": "git",
"url": "https://github.com/tighten/collect.git",
"reference": "07eed6cf7441c7a69c379fdcb118eec1a1fdd0e6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tighten/collect/zipball/07eed6cf7441c7a69c379fdcb118eec1a1fdd0e6",
"reference": "07eed6cf7441c7a69c379fdcb118eec1a1fdd0e6",
"shasum": ""
},
"require": {
"php": "^7.3|^8.0",
"symfony/var-dumper": "^3.4 || ^4.0 || ^5.0 || ^6.0"
},
"require-dev": {
"mockery/mockery": "^1.0",
"nesbot/carbon": "^2.23.0",
"phpunit/phpunit": "^8.3"
},
"type": "library",
"autoload": {
"files": [
"src/Collect/Support/helpers.php",
"src/Collect/Support/alias.php"
],
"psr-4": {
"Tightenco\\Collect\\": "src/Collect"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
}
],
"description": "Collect - Illuminate Collections as a separate package.",
"keywords": [
"collection",
"laravel"
],
"support": {
"issues": "https://github.com/tighten/collect/issues",
"source": "https://github.com/tighten/collect/tree/v8.83.27"
},
"time": "2023-01-13T18:05:42+00:00"
},
{
"name": "topthink/framework",
"version": "v6.1.4",
@ -2592,24 +2614,27 @@
},
{
"name": "topthink/think-migration",
"version": "v3.0.6",
"version": "v3.1.1",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-migration.git",
"reference": "82c4226cb14f973b9377c7fc6e89c525cbb8b030"
"reference": "22c44058e1454f3af1d346e7f6524fbe654de7fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-migration/zipball/82c4226cb14f973b9377c7fc6e89c525cbb8b030",
"reference": "82c4226cb14f973b9377c7fc6e89c525cbb8b030",
"url": "https://api.github.com/repos/top-think/think-migration/zipball/22c44058e1454f3af1d346e7f6524fbe654de7fb",
"reference": "22c44058e1454f3af1d346e7f6524fbe654de7fb",
"shasum": ""
},
"require": {
"php": ">=7.2",
"topthink/framework": "^6.0 || ^8.0",
"topthink/think-helper": "^3.0.3"
},
"require-dev": {
"fzaninotto/faker": "^1.8"
"composer/composer": "^2.5.8",
"fzaninotto/faker": "^1.8",
"robmorgan/phinx": "^0.13.4"
},
"suggest": {
"fzaninotto/faker": "Required to use the factory builder (^1.8)."
@ -2624,7 +2649,7 @@
},
"autoload": {
"psr-4": {
"Phinx\\": "phinx/src/Phinx",
"Phinx\\": "phinx",
"think\\migration\\": "src"
}
},
@ -2640,9 +2665,9 @@
],
"support": {
"issues": "https://github.com/top-think/think-migration/issues",
"source": "https://github.com/top-think/think-migration/tree/v3.0.6"
"source": "https://github.com/top-think/think-migration/tree/v3.1.1"
},
"time": "2023-07-01T11:01:52+00:00"
"time": "2023-09-14T05:51:31+00:00"
},
{
"name": "topthink/think-multi-app",
@ -2829,51 +2854,6 @@
},
"time": "2019-11-06T11:40:13+00:00"
},
{
"name": "wamkj/thinkphp6.0-databackup",
"version": "v1.0",
"source": {
"type": "git",
"url": "https://github.com/wamkj/thinkphp6.0-databackup.git",
"reference": "28a0e406d827132942723a3c9f69bb20c98e652f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/wamkj/thinkphp6.0-databackup/zipball/28a0e406d827132942723a3c9f69bb20c98e652f",
"reference": "28a0e406d827132942723a3c9f69bb20c98e652f",
"shasum": ""
},
"require": {
"php": ">=7.1.0",
"topthink/framework": "^6.0"
},
"type": "library",
"autoload": {
"psr-4": {
"wamkj\\thinkphp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "wamkj",
"email": "1149183529@qq.com"
}
],
"description": "thinkphp6.0的数据库自动备份扩展",
"keywords": [
"think-databackup",
"thinkphp"
],
"support": {
"issues": "https://github.com/wamkj/thinkphp6.0-databackup/issues",
"source": "https://github.com/wamkj/thinkphp6.0-databackup/tree/v1.0"
},
"time": "2020-02-15T13:04:16+00:00"
},
{
"name": "workerman/channel",
"version": "v1.2.0",
@ -2958,16 +2938,16 @@
},
{
"name": "workerman/workerman",
"version": "v4.1.13",
"version": "v4.1.15",
"source": {
"type": "git",
"url": "https://github.com/walkor/workerman.git",
"reference": "807780ff672775fcd08f89e573a2824e939021ce"
"reference": "afc8242fc769ab7cf22eb4ac22b97cb59d465e4e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/workerman/zipball/807780ff672775fcd08f89e573a2824e939021ce",
"reference": "807780ff672775fcd08f89e573a2824e939021ce",
"url": "https://api.github.com/repos/walkor/workerman/zipball/afc8242fc769ab7cf22eb4ac22b97cb59d465e4e",
"reference": "afc8242fc769ab7cf22eb4ac22b97cb59d465e4e",
"shasum": ""
},
"require": {
@ -3017,7 +2997,7 @@
"type": "patreon"
}
],
"time": "2023-07-31T05:57:25+00:00"
"time": "2024-02-19T02:10:39+00:00"
},
{
"name": "yansongda/pay",
@ -3159,21 +3139,21 @@
},
{
"name": "yzh52521/easyhttp",
"version": "v1.0.7",
"version": "v1.1.3",
"source": {
"type": "git",
"url": "https://github.com/yzh52521/easyhttp.git",
"reference": "52cb9aba60a725bef77acd9c4c48ecc78931af9e"
"url": "https://github.com/yuanzhihai/easyhttp.git",
"reference": "02bcf47eaf723520fa3905d0e6f1852168fe646c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/52cb9aba60a725bef77acd9c4c48ecc78931af9e",
"reference": "52cb9aba60a725bef77acd9c4c48ecc78931af9e",
"url": "https://api.github.com/repos/yuanzhihai/easyhttp/zipball/02bcf47eaf723520fa3905d0e6f1852168fe646c",
"reference": "02bcf47eaf723520fa3905d0e6f1852168fe646c",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^6.0|^7.0",
"php": "^7.2.5|^8.0",
"php": ">=7.2.5",
"psr/log": "^1.0|^2.0|^3.0"
},
"type": "library",
@ -3204,10 +3184,10 @@
"phphttp"
],
"support": {
"issues": "https://github.com/yzh52521/easyhttp/issues",
"source": "https://github.com/yzh52521/easyhttp/tree/v1.0.7"
"issues": "https://github.com/yuanzhihai/easyhttp/issues",
"source": "https://github.com/yuanzhihai/easyhttp/tree/v1.1.3"
},
"time": "2023-02-16T03:04:02+00:00"
"time": "2023-11-14T05:49:02+00:00"
}
],
"packages-dev": [

View File

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

View File

@ -172,6 +172,15 @@ body,
display: none;
}
@media screen and (max-width: 768px) {
.pear-admin.banner-layout .layui-header .layui-logo {
display: none;
}
.pear-admin.banner-layout .layui-header .layui-layout-left {
left: 0px;
}
}
/** 收缩布局 */
.pear-mini .layui-side .layui-logo .title {
display: none;
@ -465,7 +474,13 @@ body,
-webkit-transition: all .3s;
opacity: 0;
}
@media screen and (max-width: 450px) {
.pearone-color .layui-form-item .layui-input-inline {
float: left !important;
width: 190px !important;
margin: 0 10px 0 0!important;
}
}
.select-color {
margin-bottom: 30px;
}

View File

@ -0,0 +1,327 @@
/** loader */
.pear-admin-dark .loader-wrapper,
.pear-admin-dark .loader-wrapper .loader {
background-color: #141414;
}
/** layout */
.pear-admin-dark .layui-layout {
background-color: #141414;
}
/** header */
.pear-admin-dark .layui-header,
.pear-admin-dark .layui-header .layui-logo {
background-color: #141414 !important;
box-shadow: none !important;
border: none !important;
}
.pear-admin-dark .layui-header.auto-theme,
.pear-admin-dark .layui-header.auto-theme .layui-logo {
background-color: var(--global-primary-color) !important;
}
.pear-admin-dark .layui-header.auto-theme .layui-logo .title {
color: #ffffff !important;
}
.pear-admin-dark .layui-header {
border: 1px solid rgba(0, 0, 0, .40) !important;
}
.pear-admin-dark .layui-header .layui-nav * {
color: #ffffff !important;
}
.pear-admin-dark .layui-header .layui-nav .layui-nav-child {
box-shadow: 0 3px 4px rgba(0, 0, 0, .6) !important;
background-color: #141414;
border-color: #141414;
}
.pear-admin-dark .layui-header .layui-nav .layui-nav-child dd > a:hover {
background-color: #141414 !important;
}
.pear-admin-dark .layui-header .pear-nav-control .layui-this a{
background-color: #0c0c0c !important;
}
.pear-admin-dark .auto-theme .layui-logo .title{
color: var(--global-primary-color) !important;
}
/** side */
.pear-admin-dark .layui-side {
box-shadow: 0 3px 4px rgba(0, 0, 0, .6) !important;
}
.pear-admin-dark .layui-logo {
border-color: rgba(0, 0, 0, .30) !important;
}
.pear-admin-dark .layui-side .layui-logo,
.pear-admin-dark .layui-side .layui-side-scroll,
.pear-admin-dark .layui-side .layui-side-scroll .layui-nav-tree{
background-color: #141414 !important;
}
.pear-admin-dark .layui-side .layui-side-scroll .layui-nav-tree .layui-nav-child {
background-color: rgba(0,0,0,.3)!important;
}
.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-item a,
.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-item a > .layui-nav-more {
color: rgba(255,255,255,.7) !important;
}
.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-child dd.layui-this a,
.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-itemed > a,
.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-itemed > a > .layui-nav-more,
.pear-admin-dark .layui-side .layui-side-scroll .layui-nav .layui-nav-item > a:hover {
color: #ffffff !important;
}
/** body */
.pear-admin-dark .layui-body,
.pear-admin-dark .layui-body .pear-tab-page-loading,
.pear-admin-dark .layui-body .pear-page-loading {
background-color: #0a0a0a !important;
}
.pear-admin-dark .layui-body .layui-tab .layui-tab-title,
.pear-admin-dark .layui-body .layui-tab .layui-tab-title li,
.pear-admin-dark .layui-body .layui-tab .layui-tab-control li {
background-color: #141414 !important;
border-color:rgba(0, 0, 0, .30) !important;
color: #ffffff;
}
.pear-admin-dark .layui-body .layui-tab .layui-tab-title li > span:first-child {
background-color: #434343;
}
.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim {
border-color: #141414;
background-color: #141414 !important;
}
.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim a {
color: #ffffff;
}
.pear-admin-dark .layui-body .layui-tab .layui-nav-child.layui-anim a:hover {
background-color: #0a0a0a;
}
.pear-admin-dark .layui-body .layui-tab .layui-tab-close:hover {
border-radius: 50%;
background-color: #0a0a0a !important;
}
.pear-admin-dark .pear-tab-page-menu ul li {
color: #ffffff !important;
}
.pear-admin-dark .layui-footer {
background-color: #141414;
border-top: 1px solid #141414;
}
/** theme */
.pear-admin-dark .set-text,
.pear-admin-dark .select-color-title,
.pear-admin-dark .color-title {
color: #ffffff;
}
/** search */
.pear-admin-dark .menu-search-no-data {
color: #ffffff;
}
.pear-admin-dark .menu-search-tips * {
color: #ffffff;
}
.pear-admin-dark .menu-search-tips kbd {
border-color: rgba(0, 0, 0, .30) !important;
}
/** message center */
.pear-admin-dark .pear-message-center .layui-tab-title,
.pear-admin-dark .pear-message-center .message-item {
border-color: rgba(0, 0, 0, .30) !important;
color: #ffffff;
}
/** button */
.pear-admin-dark .layui-btn {
color: #ffffff;
border-color: #4C4D4F;
}
/** layer */
.pear-admin-dark .layui-layer {
background-color: #141414;
}
.pear-admin-dark .layui-layer-msg {
border-color: #141414;
}
.pear-admin-dark .layui-layer-msg .layui-layer-content {
color: #E5EAF3;
}
.pear-admin-dark .layui-layer .layui-layer-setwin > span,
.pear-admin-dark .layui-layer .layui-layer-title {
color: #ffffff;
}
/** card */
.pear-admin-dark .layui-card {
background-color: #1d1e1f !important;
}
.pear-admin-dark .layui-card .layui-card-header {
border-bottom-color: #414243;
color: #ffffff;
}
.pear-admin-dark .layui-card .layui-card-body {
color: #ffffff;
}
/** input */
.pear-admin-dark .layui-input {
background-color: transparent;
color: #ffffff;
border-color: rgba(0, 0, 0, .30) !important;
}
/** switch */
.pear-admin-dark .layui-form-switch {
border-color: #484849;
background-color: rgba(255,255,255,.08);
}
/** table */
.pear-admin-dark .layui-table {
background-color: transparent;
}
.pear-admin-dark .layui-table tr:hover {
background-color: #141414 !important;
}
.pear-admin-dark .layui-table td,
.pear-admin-dark .layui-table th,
.pear-admin-dark .layui-table-view,
.pear-admin-dark .layui-table-page,
.pear-admin-dark .layui-table-tool,
.pear-admin-dark .layui-table-header {
border-color: rgba(0, 0, 0, .40) !important;
}
.pear-admin-dark .layui-laypage select,
.pear-admin-dark .layui-laypage button {
border-color: rgba(0, 0, 0, .40) !important;
color: #ffffff !important;
background-color: transparent;
}
.pear-admin-dark .layui-table-tool-self > div {
border-color: rgba(0, 0, 0, .40) !important;
color: #ffffff !important;
background-color: transparent;
}
/** panel */
.pear-admin-dark .layui-panel {
background-color: #1d1e1f !important;
border-color: #1d1e1f !important;
}
/** menu */
.pear-admin-dark .layui-menu {
background-color: #1d1e1f !important;
}
.pear-admin-dark .layui-menu .layui-menu-body-title,
.pear-admin-dark .layui-menu .layui-menu-body-title:hover {
color: #ffffff;
background-color: #1d1e1f !important;
}
/** timeline */
.pear-admin-dark .layui-timeline-axis {
background-color: rgb(29, 30, 31) !important;
}
.pear-admin-dark .layui-timeline-item:before {
background-color: #414243 !important;
}
/** toast */
.pear-admin-dark .iziToast {
background-color: #1f1f1f !important;
}
/** console */
.pear-admin-dark .deputy,
.pear-admin-dark .shortcut-menu {
background-color: #141414 !important;
}
.pear-admin-dark .deputy:hover,
.pear-admin-dark .shortcut-menu:hover {
box-shadow: 0 3px 4px rgba(0, 0, 0, .6) !important;
}
.pear-admin-dark .message-board li {
border-bottom: 1px solid rgba(0, 0, 0, .40) !important;
}
/** analysis */
.pear-admin-dark .top-panel-number {
color: #ffffff !important;
border-color: #414243;
}
.pear-admin-dark .dynamic-status dd {
border-color: #414243;
}
/** success failure */
.pear-admin-dark .pear-result .content {
background-color: rgba(153, 153, 153, 0.12);
color: #E5EAF3;
}
.pear-admin-dark .pear-result .title{
color: #ffffff;
}
.pear-admin-dark .pear-result .description{
color: #8D9095;
}
/** 403 404 500*/
.pear-admin-dark .pear-exception .title p{
color: #E5EAF3 !important;
}
/** scroll */
.pear-admin-dark *::-webkit-scrollbar-thumb {
background: #141414;
border-radius: 4px;
}
.pear-admin-dark *::-webkit-scrollbar-thumb:hover {
background: #0a0a0a;
}

View File

@ -0,0 +1,65 @@
.top-panel {
border-radius: 4px;
text-align: center;
}
.top-panel>.layui-card-body {
height: 60px;
}
.top-panel-number {
line-height: 60px;
font-size: 29px;
border-right: 1px solid #eceff9;
}
.top-panel-tips {
padding-left: 8px;
padding-top: 16px;
line-height: 30px;
font-size: 12px;
}
.top-panel-tips i {
font-size: 33px;
}
.top-panel-tips svg {
margin-top: -12px;
width: 50px;
height: 50px;
}
.dynamic-status {
padding: 0 10px 10px;
}
.dynamic-status dd {
padding: 15px 0;
border-bottom: 1px solid #EEE;
display: -webkit-flex;
display: flex;
}
.dynamic-status dd div.dynamic-status-img {
width: 32px;
height: 32px;
border-radius: 50%;
margin-right: 15px;
}
.dynamic-status dd div.dynamic-status-img a {
width: 100%;
height: 100%;
display: inline-block;
text-align: center;
line-height: 32px;
}
.dynamic-status dd div span {
color: #BBB;
}
.dynamic-status dd div a {
color: #01AAED;
}

View File

@ -0,0 +1,81 @@
.shortcut-menu {
width: 100%;
height: 66px;
background-color: #F8F8F8;
display: inline-block;
border-radius: 5px;
text-align: center;
margin-bottom: 3px;
}
.shortcut-menu i {
font-size: 30px;
height: 66px;
line-height: 66px;
}
.shortcut-menu:hover {
box-shadow: 2px 0 8px 0 lightgray !important;
}
.shortcut-menu-label {
width: 100%;
display: inline-block;
text-align: center;
}
.deputy {
width: 100%;
height: 90px;
background-color: #F8F8F8;
display: inline-block;
border-radius: 5px;
text-align: center;
margin-bottom: 3px;
}
.deputy:hover {
box-shadow: 2px 0 8px 0 lightgray !important;
}
.deputy .deputy-label {
color: gray;
margin-top: 14px;
font-size: 14px;
}
.deputy .deputy-count {
margin-top: 12px;
color: var(--global-primary-color);
font-size: 30px;
}
.message-board {
padding: 0 10px 10px;
}
.message-board li {
position: relative;
padding: 10px 0;
border-bottom: 1px solid #EEE;
}
.message-board li p {
padding-bottom: 10px;
padding-top: 3px;
}
.message-board li>span {
color: #999;
height: 24px;
line-height: 24px;
}
.message-board .message-board-reply {
position: absolute;
right: 20px;
bottom: 12px;
height: 24px;
line-height: 24px;
}

View File

@ -0,0 +1,28 @@
.pear-exception {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
text-align: center;
box-sizing: border-box;
padding: 70px 40px
}
.pear-exception .title {
margin-top: 20px;
}
.pear-exception .title p {
color: rgb(0, 0, 0);
font-size: 20px;
}
.pear-exception .description {
margin-top: 10px;
color: #8D9095;
font-size: 14px;
}
.pear-exception .extra {
margin: 30px;
}

View File

@ -0,0 +1,80 @@
.text-center {
text-align: center;
}
.user-info-head {
width: 110px;
height: 110px;
line-height: 110px;
position: relative;
display: inline-block;
border-radius: 50%;
overflow: hidden;
cursor: pointer;
margin: 0 auto;
}
.layui-line-dash {
border-bottom: 1px dashed #ccc;
margin: 15px 0;
}
.blog-title {
padding-left: 13.5px;
}
.blog-content {
padding-left: 13px;
font-size: 13px;
color: dimgray;
}
.layui-tab-title {
border-bottom: none;
}
.fl-item {
height: 30px;
font-size: 13.5;
}
.dot {
width: 10px;
height: 10px;
border-radius: 50px;
background-color: gray;
display: inline-block;
margin-right: 10px;
}
.message-board {
padding: 0 10px 10px;
}
.message-board li {
position: relative;
padding: 10px 0;
border-bottom: 1px solid #EEE;
}
.message-board li p {
padding-bottom: 10px;
padding-top: 3px;
}
.message-board li>span {
color: #999;
height: 24px;
line-height: 24px;
}
.message-board .message-board-reply {
position: absolute;
right: 20px;
bottom: 12px;
height: 24px;
line-height: 24px;
}

View File

@ -0,0 +1,44 @@
.layui-dropdown {
border-radius: var(--global-border-radius);
}
.layui-input {
border-radius: var(--global-border-radius);
}
.layui-form-onswitch {
background-color: var(--global-primary-color) !important;
}
.layui-form-onswitch {
border-color: var(--global-primary-color);
}
.layui-btn {
background-color: var(--global-primary-color);
}
.layui-btn.layui-btn-normal {
background-color: #1e9fff !important;
}
.layui-btn.layui-btn-danger {
background-color: #ff5722 !important;
}
.layui-btn.layui-btn-warm {
background-color: #ffb800 !important;
}
.layui-btn.layui-btn-primary {
background-color: transparent !important;
color: #5f5f5f !important;
}
.layui-card {
border-radius: var(--global-border-radius);
}
.layui-timeline-axis {
color: var(--global-primary-color);
}

View File

@ -0,0 +1,7 @@
:root {
--global-primary-color: #16baaa;
--global-border-radius: 4px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,977 @@
.pear-container {
padding: 10px;
margin: 0px;
box-sizing: border-box;
background-color: transparent;
width: 100%;
}
*::-webkit-scrollbar {
width: 0px;
height: 0px;
}
*::-webkit-scrollbar {
width: 6px;
height: 6px;
}
*::-webkit-scrollbar-track {
background: transparent;
}
*::-webkit-scrollbar-thumb {
background: #E6E6E6;
border-radius: 4px;
}
*::-webkit-scrollbar-thumb:hover {
background: #E6E6E6;
}
*::-webkit-scrollbar-corner {
background: #f6f6f6;
}
.pear-row::after,
.pear-row::before {
content: "";
display: table;
clear: both;
}
.pear-col {
float: left;
min-height: 1px;
}
.pear-row * {
box-sizing: border-box
}
.pear-col-md1 {
width: 4.16%;
}
.pear-col-md2 {
width: 8.33%;
}
.pear-col-md3 {
width: 12.5%;
}
.pear-col-md4 {
width: 16.66%;
}
.pear-col-md5 {
width: 20.83%;
}
.pear-col-md6 {
width: 25%;
}
.pear-col-md7 {
width: 29.16%;
}
.pear-col-md8 {
width: 33.33%;
}
.pear-col-md9 {
width: 37.5%;
}
.pear-col-md10 {
width: 41.66%;
}
.pear-col-md11 {
width: 45.83%;
}
.pear-col-md12 {
width: 50%;
}
.pear-col-md13 {
width: 54.16%;
}
.pear-col-md14 {
width: 58.33%;
}
.pear-col-md15 {
width: 62.5%;
}
.pear-col-md16 {
width: 66.66%;
}
.pear-col-md17 {
width: 70.83%;
}
.pear-col-md18 {
width: 75%;
}
.pear-col-md19 {
width: 79.16%;
}
.pear-col-md20 {
width: 83.33%;
}
.pear-col-md21 {
width: 87.5%;
}
.pear-col-md22 {
width: 91.66%;
}
.pear-col-md23 {
width: 95.83%;
}
.pear-col-md24 {
width: 100%;
}
.pear-col-md-offset1 {
margin-left: 4.16%;
}
.pear-col-md-offset2 {
margin-left: 8.33%;
}
.pear-col-md-offset3 {
margin-left: 12.5%;
}
.pear-col-md-offset4 {
margin-left: 16.66%;
}
.pear-col-md-offset5 {
margin-left: 20.83%;
}
.pear-col-md-offset6 {
margin-left: 25%;
}
.pear-col-md-offset7 {
margin-left: 29.16%;
}
.pear-col-md-offset8 {
margin-left: 33.33%;
}
.pear-col-md-offset9 {
margin-left: 37.5%;
}
.pear-col-md-offset10 {
margin-left: 41.66%;
}
.pear-col-md-offset11 {
margin-left: 45.83%;
}
.pear-col-md-offset12 {
margin-left: 50%;
}
.pear-col-md-offset13 {
margin-left: 54.16%;
}
.pear-col-md-offset14 {
margin-left: 58.33%;
}
.pear-col-md-offset15 {
margin-left: 62.5%;
}
.pear-col-md-offset16 {
margin-left: 66.66%;
}
.pear-col-md-offset17 {
margin-left: 70.83%;
}
.pear-col-md-offset18 {
margin-left: 75%;
}
.pear-col-md-offset19 {
margin-left: 79.16%;
}
.pear-col-md-offset20 {
margin-left: 83.33%;
}
.pear-col-md-offset21 {
margin-left: 87.5%;
}
.pear-col-md-offset22 {
margin-left: 91.66%;
}
.pear-col-md-offset23 {
margin-left: 95.83%;
}
.pear-col-md-offset24 {
margin-left: 100%;
}
@media all and (max-width:768px) {
.pear-col-xs1 {
width: 4.16%;
}
.pear-col-xs2 {
width: 8.33%;
}
.pear-col-xs3 {
width: 12.5%;
}
.pear-col-xs4 {
width: 16.66%;
}
.pear-col-xs5 {
width: 20.83%;
}
.pear-col-xs6 {
width: 25%;
}
.pear-col-xs7 {
width: 29.16%;
}
.pear-col-xs8 {
width: 33.33%;
}
.pear-col-xs9 {
width: 37.5%;
}
.pear-col-xs10 {
width: 41.66%;
}
.pear-col-xs11 {
width: 45.83%;
}
.pear-col-xs12 {
width: 50%;
}
.pear-col-xs13 {
width: 54.16%;
}
.pear-col-xs14 {
width: 58.33%;
}
.pear-col-xs15 {
width: 62.5%;
}
.pear-col-xs16 {
width: 66.66%;
}
.pear-col-xs17 {
width: 70.83%;
}
.pear-col-xs18 {
width: 75%;
}
.pear-col-xs19 {
width: 79.16%;
}
.pear-col-xs20 {
width: 83.33%;
}
.pear-col-xs21 {
width: 87.5%;
}
.pear-col-xs22 {
width: 91.66%;
}
.pear-col-xs23 {
width: 95.83%;
}
.pear-col-xs24 {
width: 100%;
}
.pear-col-xs-offset1 {
margin-left: 4.16%;
}
.pear-col-xs-offset2 {
margin-left: 8.33%;
}
.pear-col-xs-offset3 {
margin-left: 12.5%;
}
.pear-col-xs-offset4 {
margin-left: 16.66%;
}
.pear-col-xs-offset5 {
margin-left: 20.83%;
}
.pear-col-xs-offset6 {
margin-left: 25%;
}
.pear-col-xs-offset7 {
margin-left: 29.16%;
}
.pear-col-xs-offset8 {
margin-left: 33.33%;
}
.pear-col-xs-offset9 {
margin-left: 37.5%;
}
.pear-col-xs-offset10 {
margin-left: 41.66%;
}
.pear-col-xs-offset11 {
margin-left: 45.83%;
}
.pear-col-xs-offset12 {
margin-left: 50%;
}
.pear-col-xs-offset13 {
margin-left: 54.16%;
}
.pear-col-xs-offset14 {
margin-left: 58.33%;
}
.pear-col-xs-offset15 {
margin-left: 62.5%;
}
.pear-col-xs-offset16 {
margin-left: 66.66%;
}
.pear-col-xs-offset17 {
margin-left: 70.83%;
}
.pear-col-xs-offset18 {
margin-left: 75%;
}
.pear-col-xs-offset19 {
margin-left: 79.16%;
}
.pear-col-xs-offset20 {
margin-left: 83.33%;
}
.pear-col-xs-offset21 {
margin-left: 87.5%;
}
.pear-col-xs-offset22 {
margin-left: 91.66%;
}
.pear-col-xs-offset23 {
margin-left: 95.83%;
}
.pear-col-xs-offset24 {
margin-left: 100%;
}
}
@media all and (min-width:768px) and (max-width:992px) {
.pear-col-sm1 {
width: 4.16%;
}
.pear-col-sm2 {
width: 8.33%;
}
.pear-col-sm3 {
width: 12.5%;
}
.pear-col-sm4 {
width: 16.66%;
}
.pear-col-sm5 {
width: 20.83%;
}
.pear-col-sm6 {
width: 25%;
}
.pear-col-sm7 {
width: 29.16%;
}
.pear-col-sm8 {
width: 33.33%;
}
.pear-col-sm9 {
width: 37.5%;
}
.pear-col-sm10 {
width: 41.66%;
}
.pear-col-sm11 {
width: 45.83%;
}
.pear-col-sm12 {
width: 50%;
}
.pear-col-sm13 {
width: 54.16%;
}
.pear-col-sm14 {
width: 58.33%;
}
.pear-col-sm15 {
width: 62.5%;
}
.pear-col-sm16 {
width: 66.66%;
}
.pear-col-sm17 {
width: 70.83%;
}
.pear-col-sm18 {
width: 75%;
}
.pear-col-sm19 {
width: 79.16%;
}
.pear-col-sm20 {
width: 83.33%;
}
.pear-col-sm21 {
width: 87.5%;
}
.pear-col-sm22 {
width: 91.66%;
}
.pear-col-sm23 {
width: 95.83%;
}
.pear-col-sm24 {
width: 100%;
}
.pear-col-sm-offset1 {
margin-left: 4.16%;
}
.pear-col-sm-offset2 {
margin-left: 8.33%;
}
.pear-col-sm-offset3 {
margin-left: 12.5%;
}
.pear-col-sm-offset4 {
margin-left: 16.66%;
}
.pear-col-sm-offset5 {
margin-left: 20.83%;
}
.pear-col-sm-offset6 {
margin-left: 25%;
}
.pear-col-sm-offset7 {
margin-left: 29.16%;
}
.pear-col-sm-offset8 {
margin-left: 33.33%;
}
.pear-col-sm-offset9 {
margin-left: 37.5%;
}
.pear-col-sm-offset10 {
margin-left: 41.66%;
}
.pear-col-sm-offset11 {
margin-left: 45.83%;
}
.pear-col-sm-offset12 {
margin-left: 50%;
}
.pear-col-sm-offset13 {
margin-left: 54.16%;
}
.pear-col-sm-offset14 {
margin-left: 58.33%;
}
.pear-col-sm-offset15 {
margin-left: 62.5%;
}
.pear-col-sm-offset16 {
margin-left: 66.66%;
}
.pear-col-sm-offset17 {
margin-left: 70.83%;
}
.pear-col-sm-offset18 {
margin-left: 75%;
}
.pear-col-sm-offset19 {
margin-left: 79.16%;
}
.pear-col-sm-offset20 {
margin-left: 83.33%;
}
.pear-col-sm-offset21 {
margin-left: 87.5%;
}
.pear-col-sm-offset22 {
margin-left: 91.66%;
}
.pear-col-sm-offset23 {
margin-left: 95.83%;
}
.pear-col-sm-offset24 {
margin-left: 100%;
}
}
@media all and (min-width:1200px) {
.pear-col-lg1 {
width: 4.16%;
}
.pear-col-lg2 {
width: 8.33%;
}
.pear-col-lg3 {
width: 12.5%;
}
.pear-col-lg4 {
width: 16.66%;
}
.pear-col-lg5 {
width: 20.83%;
}
.pear-col-lg6 {
width: 25%;
}
.pear-col-lg7 {
width: 29.16%;
}
.pear-col-lg8 {
width: 33.33%;
}
.pear-col-lg9 {
width: 37.5%;
}
.pear-col-lg10 {
width: 41.66%;
}
.pear-col-lg11 {
width: 45.83%;
}
.pear-col-lg12 {
width: 50%;
}
.pear-col-lg13 {
width: 54.16%;
}
.pear-col-lg14 {
width: 58.33%;
}
.pear-col-lg15 {
width: 62.5%;
}
.pear-col-lg16 {
width: 66.66%;
}
.pear-col-lg17 {
width: 70.83%;
}
.pear-col-lg18 {
width: 75%;
}
.pear-col-lg19 {
width: 79.16%;
}
.pear-col-lg20 {
width: 83.33%;
}
.pear-col-lg21 {
width: 87.5%;
}
.pear-col-lg22 {
width: 91.66%;
}
.pear-col-lg23 {
width: 95.83%;
}
.pear-col-lg24 {
width: 100%;
}
.pear-col-lg-offset1 {
margin-left: 4.16%;
}
.pear-col-lg-offset2 {
margin-left: 8.33%;
}
.pear-col-lg-offset3 {
margin-left: 12.5%;
}
.pear-col-lg-offset4 {
margin-left: 16.66%;
}
.pear-col-lg-offset5 {
margin-left: 20.83%;
}
.pear-col-lg-offset6 {
margin-left: 25%;
}
.pear-col-lg-offset7 {
margin-left: 29.16%;
}
.pear-col-lg-offset8 {
margin-left: 33.33%;
}
.pear-col-lg-offset9 {
margin-left: 37.5%;
}
.pear-col-lg-offset10 {
margin-left: 41.66%;
}
.pear-col-lg-offset11 {
margin-left: 45.83%;
}
.pear-col-lg-offset12 {
margin-left: 50%;
}
.pear-col-lg-offset13 {
margin-left: 54.16%;
}
.pear-col-lg-offset14 {
margin-left: 58.33%;
}
.pear-col-lg-offset15 {
margin-left: 62.5%;
}
.pear-col-lg-offset16 {
margin-left: 66.66%;
}
.pear-col-lg-offset17 {
margin-left: 70.83%;
}
.pear-col-lg-offset18 {
margin-left: 75%;
}
.pear-col-lg-offset19 {
margin-left: 79.16%;
}
.pear-col-lg-offset20 {
margin-left: 83.33%;
}
.pear-col-lg-offset21 {
margin-left: 87.5%;
}
.pear-col-lg-offset22 {
margin-left: 91.66%;
}
.pear-col-lg-offset23 {
margin-left: 95.83%;
}
.pear-col-lg-offset24 {
margin-left: 100%;
}
}
.pear-col-space1 {
margin: -.5px
}
.pear-col-space1>* {
padding: .5px
}
.pear-col-space2 {
margin: -1px
}
.pear-col-space2>* {
padding: 1px
}
.pear-col-space4 {
margin: -2px
}
.pear-col-space4>* {
padding: 2px
}
.pear-col-space5 {
margin: -2.5px
}
.pear-col-space5>* {
padding: 2.5px
}
.pear-col-space6 {
margin: -3px
}
.pear-col-space6>* {
padding: 3px
}
.pear-col-space8 {
margin: -4px
}
.pear-col-space8>* {
padding: 4px
}
.pear-col-space10 {
margin: -5px
}
.pear-col-space10>* {
padding: 5px
}
.pear-col-space12 {
margin: -6px
}
.pear-col-space12>* {
padding: 6px
}
.pear-col-space14 {
margin: -7px
}
.pear-col-space14>* {
padding: 7px
}
.pear-col-space15 {
margin: -7.5px
}
.pear-col-space15>* {
padding: 7.5px
}
.pear-col-space16 {
margin: -8px
}
.pear-col-space16>* {
padding: 8px
}
.pear-col-space18 {
margin: -9px
}
.pear-col-space18>* {
padding: 9px
}
.pear-col-space20 {
margin: -10px
}
.pear-col-space20>* {
padding: 10px
}
.pear-col-space22 {
margin: -11px
}
.pear-col-space22>* {
padding: 11px
}
.pear-col-space24 {
margin: -12px
}
.pear-col-space24>* {
padding: 12px
}
.pear-col-space25 {
margin: -12.5px
}
.pear-col-space25>* {
padding: 12.5px
}
.pear-col-space26 {
margin: -13px
}
.pear-col-space26>* {
padding: 13px
}
.pear-col-space28 {
margin: -14px
}
.pear-col-space28>* {
padding: 14px
}
.pear-col-space30 {
margin: -15px
}
.pear-col-space30>* {
padding: 15px
}

View File

@ -0,0 +1,90 @@
/* 搜索面板 */
.menu-search-content .layui-input {
padding-left: 30px;
}
.menu-search-content .layui-input:focus {
border: 1px solid var(--global-primary-color)!important;
box-shadow: none;
}
.menu-search-content {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.menu-search-input-wrapper {
width: 100%;
padding: 15px 15px;
}
.menu-search-no-data {
display: flex;
justify-content: center;
width: 100%;
height: 122px;
align-items: center;
}
.menu-search-list {
width: 100%;
padding: 5px 15px;
}
.menu-search-list li {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
height: 50px;
margin-bottom: 8px;
padding: 0px 10px;
color: currentColor;
font-size: 14px;
border-radius: 4px;
box-shadow: 0 1px 3px #d4d9e1;
cursor: pointer;
background-color: #fff;
}
.menu-search-list li.this,
.menu-search-list li:hover {
background-color: var(--global-primary-color);
color: white;
}
.menu-search-tips {
margin-bottom: 15px;
padding: 0 15px;
width: 100%
}
.menu-search-tips>div {
display: flex;
align-items: center;
justify-content: flex-end;
font-size: 12px;
}
.menu-search-tips .mr-1 {
margin-right: 4px;
}
.menu-search-tips .mr-5 {
margin-right: 20px;
}
.menu-search-tips .w-5 {
width: 14px;
}
.menu-search-tips kbd {
line-height: 1.5;
border: 1px solid #e5e7eb;
font-size: 10px;
text-align: center;
padding: 2px 6px;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
border-radius: 5px;
}

View File

@ -0,0 +1,39 @@
.pear-message-center {
width: 360px;
height: 100%;
}
.pear-message-center .layui-tab .layui-tab-title{
display: flex;
}
.pear-message-center .layui-tab .layui-tab-title .layui-this::after {
display: none;
}
.pear-message-center .layui-tab .layui-tab-title li {
flex: 1;
}
.pear-message-center .message-item img {
margin-left: 8px;
width: 33px !important;
height: 33px !important;
border-radius: 50px;
margin-right: 15px;
}
.pear-message-center .message-item {
height: 64px !important;
line-height: 45px !important;
padding-right: 20px;
padding-left: 20px;
border-bottom: 1px solid whitesmoke;
padding-top: 10px;
padding-bottom: 15px;
}
.pear-message-center .message-item .extra {
float: right;
right: 10px;
}

View File

@ -0,0 +1,154 @@
.pear-page {
width: 100%;
position: relative;
overflow-y: auto;
height: 100%;
}
.pear-page .dot {
width: 5px;
height: 24px;
background-color: #5FB878;
margin-top: 8px;
margin-left: 15px;
border-radius: 2px;
display: inline-block;
}
.pear-page .pear-page-title {
height: 40px;
line-height: 40px;
background-color: white;
border: whitesmoke 1px solid;
}
.pear-page .pear-page-content,
.pear-page .pear-page-content iframe {
width: 100%;
height: calc(100% - 0px) !important;
}
.pear-page .pear-page-content iframe {
height: calc(100% - 4px) !important;
}
.pear-page-loading {
position: absolute;
display: none;
width: 100%;
height: calc(100% - 0px) !important;
background-color: #fff;
top: 0px;
z-index: 19;
}
.pear-page-loading.close {
animation: close 1s;
-webkit-animation: close 1s;
animation-fill-mode: forwards;
}
.ball-loader {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%)
}
.ball-loader>span,
.signal-loader>span {
background-color: #4aca85;
display: inline-block
}
.ball-loader>span:nth-child(1),
.ball-loader.sm>span:nth-child(1),
.signal-loader>span:nth-child(1),
.signal-loader.sm>span:nth-child(1) {
-webkit-animation-delay: 0s;
animation-delay: 0s
}
.ball-loader>span:nth-child(2),
.ball-loader.sm>span:nth-child(2),
.signal-loader>span:nth-child(2),
.signal-loader.sm>span:nth-child(2) {
-webkit-animation-delay: .1s;
animation-delay: .1s
}
.ball-loader>span:nth-child(3),
.ball-loader.sm>span:nth-child(3),
.signal-loader>span:nth-child(3),
.signal-loader.sm>span:nth-child(3) {
-webkit-animation-delay: .15s;
animation-delay: .15s
}
.ball-loader>span:nth-child(4),
.ball-loader.sm>span:nth-child(4),
.signal-loader>span:nth-child(4),
.signal-loader.sm>span:nth-child(4) {
-webkit-animation-delay: .2s;
animation-delay: .2s
}
.ball-loader>span {
width: 20px;
height: 20px;
margin: 0 3px;
border-radius: 50%;
transform: scale(0);
-ms-transform: scale(0);
-webkit-transform: scale(0);
animation: ball-load 1s ease-in-out infinite;
-webkit-animation: 1s ball-load ease-in-out infinite
}
@-webkit-keyframes ball-load {
0% {
transform: scale(0);
-webkit-transform: scale(0)
}
50% {
transform: scale(1);
-webkit-transform: scale(1)
}
100% {
transform: scale(0);
-webkit-transform: scale(0)
}
}
@keyframes ball-load {
0% {
transform: scale(0);
-webkit-transform: scale(0)
}
50% {
transform: scale(1);
-webkit-transform: scale(1)
}
100% {
transform: scale(0);
-webkit-transform: scale(0)
}
}
@-webkit-keyframes close {
0% {
opacity: 1;
/*display: block;*/
}
100% {
opacity: 0;
/*display: none;*/
}
}

View File

@ -0,0 +1,314 @@
.pear-tab-page {
margin: 0px;
overflow: hidden;
height: 100% !important;
}
.pear-tab-page .layui-tab-content {
height: calc(100% - 42px) !important;
}
.pear-tab-page .layui-tab-content .layui-tab-item {
overflow-y: auto;
height: 100%;
}
.pear-tab-page-menu{
box-shadow: none;
border-radius: 4px!important;
overflow: hidden;
box-shadow: 2px 0 6px rgba(0, 21, 41, .10);
}
.pear-tab-page-menu .item{
height: 20px;
padding-left: 18px;
padding-top: 7px;
padding-bottom: 7px;
color: #333;
font-size: 13.5px;
line-height: 20px;
cursor:pointer;
}
.pear-tab-page-menu .item:hover{
background: var(--global-primary-color);
color: white;
}
.pear-tab-page .layui-tab-content {
padding: 0px;
}
.pear-tab-page > .layui-tab-title {
border: none;
border: 1px solid whitesmoke;
background-color: white;
}
.pear-tab-page > .layui-tab-title li {
border-right: 1px solid whitesmoke;
color: dimgray;
font-size: 13.5px;
}
.pear-tab-page > .layui-tab-title .layui-tab-bar {
display: none;
}
.pear-tab-page .layui-nav-more {
display: none;
}
.pear-tab-page > .layui-tab-title .layui-this:after {
display: none;
}
.pear-tab-page > .layui-tab-title .pear-tab-page-active {
display: inline-block;
background-color: lightgray;
width: 8px;
height: 8px;
border-radius: 30px;
margin-right: 12px;
}
.pear-tab-page > .layui-tab-title .layui-this .pear-tab-page-active {
background-color: var(--global-primary-color) !important;
}
.pear-tab-page > .layui-tab-title .layui-tab-close:hover {
background-color: white;
line-height: 19px;
color: gray;
}
.pear-tab-page > .layui-tab-title .disable-close+.layui-tab-close {
display: none;
}
.pear-tab-page > .layui-tab-title .able-close+.layui-tab-close {
display: inline-block;
}
.pear-tab-page .layui-tab-close{
font-size: 13px;
}
.pear-tab-page .layui-tab-control>li {
position: absolute;
top: 0px;
height: 40px;
line-height: 40px;
width: 40px;
background-color: white;
border-top: whitesmoke 1px solid;
border-bottom: whitesmoke 1px solid;
text-align: center;
}
.pear-tab-page .layui-tab-prev {
left: 0px;
border-right: whitesmoke 1px solid;
}
.pear-tab-page .layui-tab-next {
right: 40px;
border-left: 1px solid whitesmoke;
}
.pear-tab-page .layui-tab-tool {
right: 0px;
border-left: 1px solid whitesmoke;
}
.pear-tab-page .layui-tab-control .layui-tab-tool,
.pear-tab-page .layui-tab-control .layui-tab-prev,
.pear-tab-page .layui-tab-control .layui-tab-next {
display: none;
}
.pear-tab-page.layui-tab-roll .layui-tab-control .layui-tab-prev,
.pear-tab-page.layui-tab-roll .layui-tab-control .layui-tab-next {
display: block;
}
.pear-tab-page.layui-tab-roll .layui-tab-control .layui-tab-next {
right: 0px;
border-right: 1px solid whitesmoke;
}
.pear-tab-page.layui-tab-roll .layui-tab-title {
padding-left: 40px;
padding-right: 40px;
}
.pear-tab-page.layui-tab-tool .layui-tab-control .layui-tab-tool {
display: block;
}
.pear-tab-page.layui-tab-tool .layui-tab-title {
padding-left: 0px;
padding-right: 40px;
}
.pear-tab-page.layui-tab-rollTool > .layui-tab-title {
padding-left: 40px;
padding-right: 80px;
}
.pear-tab-page.layui-tab-rollTool .layui-tab-control .layui-tab-prev,
.pear-tab-page.layui-tab-rollTool .layui-tab-control .layui-tab-next,
.pear-tab-page.layui-tab-rollTool .layui-tab-control .layui-tab-tool {
display: block;
}
.pear-tab-page .layui-tab-tool .layui-nav {
position: absolute;
height: 43px !important;
top: 0;
width: 100%;
height: 100%;
padding: 0;
background: 0 0;
}
.pear-tab-page .layui-tab-tool .layui-nav-item {
height: 40px;
}
.pear-tab-page .layui-tab-tool .layui-nav-bar {
display: none;
}
.pear-tab-page .layui-tab-tool .layui-nav-child {
left: auto;
top: 45px;
right: 3px;
width: 120px;
border: 1px solid whitesmoke;
}
.pear-tab-page .layui-tab-tool .layui-this a {
background-color: #009688;
}
.pear-tab-page-loading {
position: absolute;
display: none;
width: 100%;
height: calc(100% - 42px);
top: 42px;
z-index: 19;
background-color: #fff
}
.pear-tab-page-loading.close {
animation: close 1s;
-webkit-animation: close 1s;
animation-fill-mode: forwards;
}
.ball-loader {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%)
}
.ball-loader>span,
.signal-loader>span {
background-color: var(--global-primary-color) !important;
display: inline-block
}
.ball-loader>span:nth-child(1),
.ball-loader.sm>span:nth-child(1),
.signal-loader>span:nth-child(1),
.signal-loader.sm>span:nth-child(1) {
-webkit-animation-delay: 0s;
animation-delay: 0s
}
.ball-loader>span:nth-child(2),
.ball-loader.sm>span:nth-child(2),
.signal-loader>span:nth-child(2),
.signal-loader.sm>span:nth-child(2) {
-webkit-animation-delay: .1s;
animation-delay: .1s
}
.ball-loader>span:nth-child(3),
.ball-loader.sm>span:nth-child(3),
.signal-loader>span:nth-child(3),
.signal-loader.sm>span:nth-child(3) {
-webkit-animation-delay: .15s;
animation-delay: .15s
}
.ball-loader>span:nth-child(4),
.ball-loader.sm>span:nth-child(4),
.signal-loader>span:nth-child(4),
.signal-loader.sm>span:nth-child(4) {
-webkit-animation-delay: .2s;
animation-delay: .2s
}
.ball-loader>span {
width: 20px;
height: 20px;
margin: 0 3px;
border-radius: 50%;
transform: scale(0);
-ms-transform: scale(0);
-webkit-transform: scale(0);
animation: ball-load 1s ease-in-out infinite;
-webkit-animation: 1s ball-load ease-in-out infinite
}
@-webkit-keyframes ball-load {
0% {
transform: scale(0);
-webkit-transform: scale(0)
}
50% {
transform: scale(1);
-webkit-transform: scale(1)
}
100% {
transform: scale(0);
-webkit-transform: scale(0)
}
}
@keyframes ball-load {
0% {
transform: scale(0);
-webkit-transform: scale(0)
}
50% {
transform: scale(1);
-webkit-transform: scale(1)
}
100% {
transform: scale(0);
-webkit-transform: scale(0)
}
}
@-webkit-keyframes close {
0% {
opacity: 1;
/*display: block;*/
}
100% {
opacity: 0;
/*display: none;*/
}
}

View File

@ -2,7 +2,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
function(exports) {
"use strict";
var $ = layui.jquery,
const $ = layui.jquery,
form = layui.form,
element = layui.element,
yaml = layui.yaml,
@ -12,30 +12,31 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
pearFrame = layui.frame,
pearTheme = layui.theme,
message = layui.message,
fullscreen=layui.fullscreen;
fullscreen = layui.fullscreen;
var bodyFrame;
var sideMenu;
var bodyTab;
var config;
var logout = function() {};
var msgInstance;
var body = $('body');
let bodyFrame;
let sideMenu;
let bodyTab;
let config;
let logout = function () {
};
let msgInstance;
const body = $('body');
var pearAdmin = new function() {
const pearAdmin = new function () {
var configType = 'yml';
var configPath = 'pear.config.yml';
let configType = 'yml';
let configPath = 'pear.config.yml';
this.setConfigPath = function(path) {
this.setConfigPath = function (path) {
configPath = path;
}
this.setConfigType = function(type) {
this.setConfigType = function (type) {
configType = type;
}
this.render = function(initConfig) {
this.render = function (initConfig) {
if (initConfig !== undefined) {
applyConfig(initConfig);
} else {
@ -43,11 +44,11 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
}
this.readConfig = function() {
this.readConfig = function () {
if (configType === "yml") {
return yaml.load(configPath);
} else {
var data;
let data;
$.ajax({
url: configPath,
type: 'get',
@ -61,8 +62,8 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
}
this.messageRender = function(option) {
var option = {
this.messageRender = function (option) {
option = {
elem: '.message',
url: option.header.message,
height: '250px'
@ -70,12 +71,12 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
msgInstance = message.render(option);
}
this.logoRender = function(param) {
this.logoRender = function (param) {
$(".layui-logo .logo").attr("src", param.logo.image);
$(".layui-logo .title").html(param.logo.title);
}
this.menuRender = function(param) {
this.menuRender = function (param) {
sideMenu = pearMenu.render({
elem: 'sideMenu',
async: param.menu.async !== undefined ? param.menu.async : true,
@ -83,16 +84,15 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
height: '100%',
method: param.menu.method,
control: isControl(param) === 'true' || isControl(param) === true ? 'control' : false, // control
controlWidth: param.menu.controlWidth,
defaultMenu: 0,
accordion: param.menu.accordion,
url: param.menu.data,
data: param.menu.data,
parseData: false,
change: function() {
change: function () {
compatible();
},
done: function() {
done: function () {
sideMenu.isCollapse = param.menu.collapse;
sideMenu.selectItem(param.menu.select);
pearAdmin.collapse(param);
@ -100,9 +100,9 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
});
}
this.bodyRender = function(param) {
this.bodyRender = function (param) {
body.on("click", ".refresh", function() {
body.on("click", ".refresh", function () {
refresh();
})
@ -117,7 +117,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
index: 0,
tabMax: param.tab.max,
preload: param.tab.preload,
closeEvent: function(id) {
closeEvent: function (id) {
sideMenu.selectItem(id);
},
data: [{
@ -126,9 +126,9 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
title: param.tab.index.title,
close: false
}],
success: function(id) {
success: function (id) {
if (param.tab.session) {
setTimeout(function() {
setTimeout(function () {
sideMenu.selectItem(id);
bodyTab.positionTab();
}, 500)
@ -136,7 +136,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
});
bodyTab.click(function(id) {
bodyTab.click(function (id) {
if (!param.tab.keepState) {
bodyTab.refresh(false);
}
@ -144,7 +144,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
sideMenu.selectItem(id);
})
sideMenu.click(function(dom, data) {
sideMenu.click(function (dom, data) {
bodyTab.addTabOnly({
id: data.menuId,
title: data.menuTitle,
@ -163,32 +163,32 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
height: '100%'
});
sideMenu.click(function(dom, data) {
sideMenu.click(function (dom, data) {
bodyFrame.changePage(data.menuUrl, true);
compatible()
})
}
}
this.keepLoad = function(param) {
this.keepLoad = function (param) {
compatible()
setTimeout(function() {
setTimeout(function () {
$(".loader-main").fadeOut(200);
}, param.other.keepLoad)
}
this.themeRender = function(option) {
this.themeRender = function (option) {
if (option.theme.allowCustom === false) {
$(".setting").remove();
}
var colorId = localStorage.getItem("theme-color");
var currentColor = getColorById(colorId);
const colorId = localStorage.getItem("theme-color");
const currentColor = getColorById(colorId);
localStorage.setItem("theme-color", currentColor.id);
localStorage.setItem("theme-color-color", currentColor.color);
localStorage.setItem("theme-color-second", currentColor.second);
pearTheme.changeTheme(window, isAutoHead(config));
var menu = localStorage.getItem("theme-menu");
let menu = localStorage.getItem("theme-menu");
if (menu === null) {
menu = option.theme.defaultMenu;
} else {
@ -197,7 +197,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
}
var header = localStorage.getItem("theme-header");
let header = localStorage.getItem("theme-header");
if (header === null) {
header = option.theme.defaultHeader;
} else {
@ -206,7 +206,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
}
var banner = localStorage.getItem("theme-banner");
let banner = localStorage.getItem("theme-banner");
if (banner === null) {
banner = option.theme.banner;
} else {
@ -215,7 +215,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
}
var autoHead = localStorage.getItem("auto-head");
let autoHead = localStorage.getItem("auto-head");
if (autoHead === null) {
autoHead = option.other.autoHead;
} else {
@ -224,7 +224,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
}
var muiltTab = localStorage.getItem("muilt-tab");
let muiltTab = localStorage.getItem("muilt-tab");
if (muiltTab === null) {
muiltTab = option.tab.enable;
} else {
@ -233,7 +233,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
}
var control = localStorage.getItem("control");
let control = localStorage.getItem("control");
if (control === null) {
control = option.menu.control;
} else {
@ -242,10 +242,10 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
}
var footer = localStorage.getItem("footer");
if( footer === null) {
let footer = localStorage.getItem("footer");
if (footer === null) {
footer = option.other.footer;
}else{
} else {
if (option.theme.allowCustom === false) {
footer = option.other.footer;
}
@ -264,9 +264,9 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
this.footer(footer);
}
this.footer = function(footer){
var bodyDOM = $(".pear-admin .layui-body");
var footerDOM = $(".pear-admin .layui-footer");
this.footer = function (footer) {
const bodyDOM = $(".pear-admin .layui-body");
const footerDOM = $(".pear-admin .layui-footer");
if (footer === true || footer === "true") {
footerDOM.removeClass("close");
bodyDOM.css("bottom", footerDOM.outerHeight());
@ -276,15 +276,15 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
}
this.bannerSkin = function(theme) {
var pearAdmin = $(".pear-admin");
this.bannerSkin = function (theme) {
const pearAdmin = $(".pear-admin");
pearAdmin.removeClass("banner-layout");
if (theme === true || theme === "true") {
pearAdmin.addClass("banner-layout");
}
}
this.collapse = function(param) {
this.collapse = function (param) {
if (param.menu.collapse) {
if ($(window).width() >= 768) {
collapse()
@ -292,43 +292,44 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
}
this.menuSkin = function(theme) {
var pearAdmin = $(".pear-admin .layui-side");
this.menuSkin = function (theme) {
const pearAdmin = $(".pear-admin .layui-side");
pearAdmin.removeClass("light-theme");
pearAdmin.removeClass("dark-theme");
pearAdmin.addClass(theme);
}
this.headerSkin = function(theme) {
var pearAdmin = $(".pear-admin .layui-header");
this.headerSkin = function (theme) {
const pearAdmin = $(".pear-admin .layui-header");
pearAdmin.removeClass("light-theme");
pearAdmin.removeClass("dark-theme");
pearAdmin.addClass(theme);
}
this.logout = function(callback) {
this.logout = function (callback) {
logout = callback;
}
this.message = function(callback) {
this.message = function (callback) {
if (callback != null) {
msgInstance.click(callback);
}
}
this.collapseSide = function() {
this.collapseSide = function () {
collapse()
}
this.refreshThis = function() {
this.refreshThis = function () {
refresh()
}
this.refresh = function(id) {
$("iframe[id='"+ id +"']").attr('src', $("iframe[id='"+ id +"']").attr('src'));
this.refresh = function (id) {
const iframe = $("iframe[id='" + id + "']");
iframe.attr('src', iframe.attr('src'));
}
this.addTab = function(id, title, url) {
this.addTab = function (id, title, url) {
if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) {
bodyTab.addTabOnly({
id: id,
@ -337,79 +338,67 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
icon: null,
close: true
}, 400);
} else {
return;
}
}
this.closeTab = function(id) {
this.closeTab = function (id) {
if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) {
pearTab.delTabByElem('content', id, function(currentId){
pearTab.delTabByElem('content', id, function (currentId) {
sideMenu.selectItem(currentId);
});
} else {
return;
}
}
this.closeCurrentTab = function() {
this.closeCurrentTab = function () {
if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) {
pearTab.delCurrentTabByElem('content', function(id){
pearTab.delCurrentTabByElem('content', function (id) {
sideMenu.selectItem(id);
});
} else {
return;
}
}
this.closeOtherTab = function() {
if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) {
pearTab.delOtherTabByElem('content', function(id){
sideMenu.selectItem(id);
});
} else {
return;
}
}
this.closeAllTab = function() {
if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) {
pearTab.delAllTabByElem('content', function(id){
sideMenu.selectItem(id);
});
} else {
return;
}
}
this.changeTabTitle = function(id, title) {
pearTab.changeTabTitleById('content', id ,title);
}
this.changeIframe = function(id, title, url) {
this.closeOtherTab = function () {
if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) {
return;
} else {
pearTab.delOtherTabByElem('content', function (id) {
sideMenu.selectItem(id);
});
}
}
this.closeAllTab = function () {
if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) {
pearTab.delAllTabByElem('content', function (id) {
sideMenu.selectItem(id);
});
}
}
this.changeTabTitle = function (id, title) {
pearTab.changeTabTitleById('content', id, title);
}
this.changeIframe = function (id, title, url) {
if (isMuiltTab(config) !== "true" && isMuiltTab(config) !== true) {
sideMenu.selectItem(id);
bodyFrame.changePage(url, true);
}
}
this.jump = function(id, title, url) {
this.jump = function (id, title, url) {
if (isMuiltTab(config) === "true" || isMuiltTab(config) === true) {
pearAdmin.addTab(id, title, url)
} else {
pearAdmin.changeIframe(id, title, url)
}
}
this.fullScreen = function() {
this.fullScreen = function () {
if ($(".fullScreen").hasClass("layui-icon-screen-restore")) {
screenFun(2).then(function() {
screenFun(2).then(function () {
$(".fullScreen").eq(0).removeClass("layui-icon-screen-restore");
});
} else {
screenFun(1).then(function() {
screenFun(1).then(function () {
$(".fullScreen").eq(0).addClass("layui-icon-screen-restore");
});
}
@ -417,7 +406,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
};
function refresh() {
var refreshA = $(".refresh a");
const refreshA = $(".refresh a");
refreshA.removeClass("layui-icon-refresh-1");
refreshA.addClass("layui-anim");
refreshA.addClass("layui-anim-rotate");
@ -436,9 +425,9 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
function collapse() {
sideMenu.collapse();
var admin = $(".pear-admin");
var left = $(".layui-icon-spread-left")
var right = $(".layui-icon-shrink-right")
const admin = $(".pear-admin");
const left = $(".layui-icon-spread-left");
const right = $(".layui-icon-shrink-right");
if (admin.is(".pear-mini")) {
left.addClass("layui-icon-shrink-right")
left.removeClass("layui-icon-spread-left")
@ -464,14 +453,14 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
body.on("click", ".menuSearch", function () {
// 过滤菜单
var filterHandle = function (filterData, val) {
const filterHandle = function (filterData, val) {
if (!val) return [];
var filteredMenus = [];
const filteredMenus = [];
filterData = $.extend(true, {}, filterData);
$.each(filterData, function (index, item) {
if (item.children && item.children.length) {
var children = filterHandle(item.children, val)
var obj = $.extend({}, item, { children: children });
var obj = $.extend({}, item, {children: children});
if (children && children.length) {
filteredMenus.push(obj);
} else if (item.title.indexOf(val) >= 0) {
@ -483,25 +472,25 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
})
return filteredMenus;
}
};
// 树转路径
var tiledHandle = function (data) {
var tiledMenus = [];
var treeTiled = function (data, content) {
var path = "";
var separator = " / ";
const tiledHandle = function (data) {
const tiledMenus = [];
const treeTiled = function (data, content) {
let path = "";
const separator = " / ";
// 上级路径
if (!content) content = "";
$.each(data, function (index, item) {
if (item.children && item.children.length) {
path += content + item.title + separator;
var childPath = treeTiled(item.children, path);
const childPath = treeTiled(item.children, path);
path += childPath;
if (!childPath) path = ""; // 重置路径
} else {
path += content + item.title
tiledMenus.push({ path: path, info: item });
tiledMenus.push({path: path, info: item});
path = ""; //重置路径
}
})
@ -510,11 +499,11 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
treeTiled(data);
return tiledMenus;
}
};
// 创建搜索列表
var createList = function (data) {
var _listHtml = '';
const createList = function (data) {
let _listHtml = '';
$.each(data, function (index, item) {
_listHtml += '<li smenu-id="' + item.info.id + '" smenu-icon="' + item.info.icon + '" smenu-url="' + item.info.href + '" smenu-title="' + item.info.title + '" smenu-type="' + item.info.type + '">';
_listHtml += ' <span><i style="margin-right:10px" class=" ' + item.info.icon + '"></i>' + item.path + '</span>';
@ -522,9 +511,9 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
_listHtml += '</li>'
})
return _listHtml;
}
};
var _html = [
const _html = [
'<div class="menu-search-content">',
' <div class="layui-form menu-search-input-wrapper">',
' <div class=" layui-input-wrap layui-input-wrap-prefix">',
@ -551,43 +540,43 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
move: false,
content: _html,
success: function(layero,layeridx){
var $layer = layero;
var $content = $(layero).children('.layui-layer-content');
var $input = $(".menu-search-input-wrapper input");
var $noData = $(".menu-search-no-data");
var $list = $(".menu-search-list");
var menuData = sideMenu.option.data;
const $layer = layero;
const $content = $(layero).children('.layui-layer-content');
const $input = $(".menu-search-input-wrapper input");
const $noData = $(".menu-search-no-data");
const $list = $(".menu-search-list");
const menuData = sideMenu.option.data;
$layer.css("border-radius", "6px");
$input.off("focus").focus();
// 搜索菜单
$input.off("input").on("input", debounce(function(){
var keywords = $input.val().trim();
var filteredMenus = filterHandle(menuData, keywords);
const keywords = $input.val().trim();
const filteredMenus = filterHandle(menuData, keywords);
if(filteredMenus.length){
var tiledMenus = tiledHandle(filteredMenus);
var listHtml = createList(tiledMenus);
$noData.css("display", "none");
$list.html("").append(listHtml).children(":first").addClass("this")
if(filteredMenus.length){
const tiledMenus = tiledHandle(filteredMenus);
const listHtml = createList(tiledMenus);
$noData.css("display", "none");
$list.html("").append(listHtml).children(":first").addClass("this")
}else{
$list.html("");
$noData.css("display", "flex");
}
var currentHeight = $(".menu-search-content").outerHeight()
$layer.css("height", currentHeight);
$content.css("height", currentHeight);
}, 500)
const currentHeight = $(".menu-search-content").outerHeight();
$layer.css("height", currentHeight);
$content.css("height", currentHeight);
}, 500)
)
// 搜索列表点击事件
$list.off("click").on("click", "li", function () {
var menuId = $(this).attr("smenu-id");
var menuUrl = $(this).attr("smenu-url");
var menuIcon = $(this).attr("smenu-icon");
var menuTitle = $(this).attr("smenu-title");
var menuType = $(this).attr("smenu-type");
var openableWindow = menuType === "1" || menuType === 1;
const menuId = $(this).attr("smenu-id");
const menuUrl = $(this).attr("smenu-url");
const menuIcon = $(this).attr("smenu-icon");
const menuTitle = $(this).attr("smenu-title");
const menuType = $(this).attr("smenu-type");
const openableWindow = menuType === "1" || menuType === 1;
if(sideMenu.isCollapse){
collapse();
@ -611,13 +600,14 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
// 监听键盘事件
// Enter:13 Spacebar:32 UpArrow:38 DownArrow:40 Esc:27
$(document).off("keydown").keydown(function (e) {
const $menuSearchList = $(".menu-search-list li.this");
if (e.keyCode === 13 || e.keyCode === 32) {
e.preventDefault();
var menuId = $(".menu-search-list li.this").attr("smenu-id");
var menuUrl = $(".menu-search-list li.this").attr("smenu-url");
var menuTitle = $(".menu-search-list li.this").attr("smenu-title");
var menuType = $(".menu-search-list li.this").attr("smenu-type");
var openableWindow = menuType === "1" || menuType === 1;
const menuId = $menuSearchList.attr("smenu-id");
const menuUrl = $menuSearchList.attr("smenu-url");
const menuTitle = $menuSearchList.attr("smenu-title");
const menuType = $menuSearchList.attr("smenu-type");
const openableWindow = menuType === "1" || menuType === 1;
if (sideMenu.isCollapse) {
collapse();
}
@ -630,8 +620,8 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
layer.close(layeridx);
}else if(e.keyCode === 38){
e.preventDefault();
var prevEl = $(".menu-search-list li.this").prev();
$(".menu-search-list li.this").removeClass("this");
const prevEl = $menuSearchList.prev();
$menuSearchList.removeClass("this");
if(prevEl.length !== 0){
prevEl.addClass("this");
}else{
@ -639,8 +629,8 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
}else if(e.keyCode === 40){
e.preventDefault();
var nextEl = $(".menu-search-list li.this").next();
$(".menu-search-list li.this").removeClass("this");
const nextEl = $menuSearchList.next();
$menuSearchList.removeClass("this");
if(nextEl.length !== 0){
nextEl.addClass("this");
}else{
@ -684,7 +674,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
body.on("click", ".setting", function() {
var menuItem =
let menuItem =
'<li class="layui-this" data-select-bgcolor="dark-theme" >' +
'<a href="javascript:;" data-skin="skin-blue" style="" class="clearfix full-opacity-hover">' +
'<div><span style="display:block; width: 20%; float: left; height: 12px; background: #28333E;"></span><span style="display:block; width: 80%; float: left; height: 12px; background: white;"></span></div>' +
@ -700,7 +690,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
'</a>' +
'</li>';
var menuHtml =
const menuHtml =
'<div class="pearone-color">\n' +
'<div class="color-title">菜单风格</div>\n' +
'<div class="color-content">\n' +
@ -708,7 +698,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
'</div>\n' +
'</div>';
var headItem =
let headItem =
'<li class="layui-this" data-select-header="light-theme" >' +
'<a href="javascript:;" data-skin="skin-blue" style="" class="clearfix full-opacity-hover">' +
'<div><span style="display:block; width: 20%; float: left; height: 12px; background: #28333E;"></span><span style="display:block; width: 80%; float: left; height: 12px; background: white;"></span></div>' +
@ -724,7 +714,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
'</a>' +
'</li>';
var headHtml =
const headHtml =
'<div class="pearone-color">\n' +
'<div class="color-title">顶部风格</div>\n' +
'<div class="color-content">\n' +
@ -732,7 +722,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
'</div>\n' +
'</div>';
var moreItem =
let moreItem =
'<div class="layui-form-item"><div class="layui-input-inline"><input type="checkbox" name="control" lay-filter="control" lay-skin="switch" lay-text="开|关"></div><span class="set-text">菜单</span></div>';
moreItem +=
@ -747,7 +737,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
moreItem +=
'<div class="layui-form-item"><div class="layui-input-inline"><input type="checkbox" name="footer" lay-filter="footer" lay-skin="switch" lay-text="开|关"></div><span class="set-text">页脚</span></div>';
var moreHtml = '<br><div class="pearone-color">\n' +
const moreHtml = '<br><div class="pearone-color">\n' +
'<div class="color-title">更多设置</div>\n' +
'<div class="color-content">\n' +
'<form class="layui-form">\n' + moreItem + '</form>\n' +
@ -770,9 +760,9 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
form.render();
var color = localStorage.getItem("theme-color");
var menu = localStorage.getItem("theme-menu");
var header = localStorage.getItem("theme-header");
const color = localStorage.getItem("theme-color");
const menu = localStorage.getItem("theme-menu");
const header = localStorage.getItem("theme-header");
if (color !== "null") {
$(".select-color-item").removeClass("layui-icon").removeClass("layui-icon-ok");
@ -790,7 +780,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
$('#layui-layer-shade' + index).click(function() {
var $layero = $('#layui-layer' + index);
const $layero = $('#layui-layer' + index);
$layero.animate({
left: $layero.offset().left + $layero.width()
}, 200, function() {
@ -859,7 +849,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
});
body.on('click', '[data-select-bgcolor]', function() {
var theme = $(this).attr('data-select-bgcolor');
const theme = $(this).attr('data-select-bgcolor');
$('[data-select-bgcolor]').removeClass("layui-this");
$(this).addClass("layui-this");
localStorage.setItem("theme-menu", theme);
@ -867,7 +857,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
});
body.on('click', '[data-select-header]', function() {
var theme = $(this).attr('data-select-header');
const theme = $(this).attr('data-select-header');
$('[data-select-header]').removeClass("layui-this");
$(this).addClass("layui-this");
localStorage.setItem("theme-header", theme);
@ -877,8 +867,8 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
body.on('click', '.select-color-item', function() {
$(".select-color-item").removeClass("layui-icon").removeClass("layui-icon-ok");
$(this).addClass("layui-icon").addClass("layui-icon-ok");
var colorId = $(".select-color-item.layui-icon-ok").attr("color-id");
var currentColor = getColorById(colorId);
const colorId = $(".select-color-item.layui-icon-ok").attr("color-id");
const currentColor = getColorById(colorId);
localStorage.setItem("theme-color", currentColor.id);
localStorage.setItem("theme-color-color", currentColor.color);
localStorage.setItem("theme-color-second", currentColor.second);
@ -892,14 +882,14 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
pearAdmin.bodyRender(param);
pearAdmin.themeRender(param);
pearAdmin.keepLoad(param);
if (param.header.message != false) {
if (param.header.message !== false) {
pearAdmin.messageRender(param);
}
}
function getColorById(id) {
var color;
var flag = false;
let color;
let flag = false;
$.each(config.colors, function(i, value) {
if (value.id === id) {
color = value;
@ -917,7 +907,7 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
}
function buildColorHtml() {
var colors = "";
let colors = "";
$.each(config.colors, function(i, value) {
colors += "<span class='select-color-item' color-id='" + value.id + "' style='background-color:" + value.color +
";'></span>";
@ -981,9 +971,9 @@ layui.define(['message', 'table', 'jquery', 'element', 'yaml', 'form', 'tab', 'm
},50));
function debounce(fn, awaitTime) {
var timerID = null
let timerID = null;
return function () {
var arg = arguments[0]
const arg = arguments[0];
if (timerID) {
clearTimeout(timerID)
}

View File

@ -95,7 +95,11 @@ layui.define(['table', 'laypage','jquery', 'element'], function(exports) {
html += "<div id='cardpage'></div>";
}
else {
html = "<p>没有数据</p>";
if (data.code != option.response.statusCode) {
html = "<p>" + data.msg + "</p>";
} else {
html = "<p>没有数据</p>";
}
}
$(option.elem).html(html);
if (option.page) {
@ -187,6 +191,9 @@ layui.define(['table', 'laypage','jquery', 'element'], function(exports) {
data.msg = tempData[option.response.msgName];
data.count = tempData[option.response.countName];
var dataList = tempData[option.response.dataName];
if(!dataList){
return data;
}
data.data = [];
for (var i = 0; i < dataList.length; i++) {
var item = dataList[i];

View File

@ -0,0 +1,37 @@
layui.define(['jquery', 'element'], function(exports) {
"use strict";
var MOD_NAME = 'count',
$ = layui.jquery,
element = layui.element;
var count = new function() {
this.up = function(targetEle, options) {
options = options || {};
var $this = document.getElementById(targetEle),
time = options.time,
finalNum = options.num,
regulator = options.regulator,
step = finalNum / (time / regulator),
count = 0.00,
initial = 0;
var timer = setInterval(function() {
count = count + step;
if (count >= finalNum) {
clearInterval(timer);
count = finalNum;
}
var t = count.toFixed(options.bit?options.bit:0);;
if (t == initial) return;
initial = t;
$this.innerHTML = initial;
}, 30);
}
}
exports(MOD_NAME, count);
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,450 @@
layui.define(function (exports) {
exports('echartsTheme',
{
"color": [
"#3fb1e3",
"#6be6c1",
"#626c91",
"#a0a7e6",
"#c4ebad",
"#96dee8"
],
"backgroundColor": "rgba(252,252,252,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#666666"
},
"subtextStyle": {
"color": "#999999"
}
},
"line": {
"itemStyle": {
"borderWidth": "3"
},
"lineStyle": {
"width": "4"
},
"symbolSize": "10",
"symbol": "emptyCircle",
"smooth": true
},
"radar": {
"itemStyle": {
"borderWidth": "3"
},
"lineStyle": {
"width": "4"
},
"symbolSize": "10",
"symbol": "emptyCircle",
"smooth": true
},
"bar": {
"itemStyle": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
},
"emphasis": {
"itemStyle": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
}
}
},
"pie": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"scatter": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"boxplot": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"parallel": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"sankey": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"funnel": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"gauge": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"candlestick": {
"itemStyle": {
"color": "#e6a0d2",
"color0": "transparent",
"borderColor": "#e6a0d2",
"borderColor0": "#3fb1e3",
"borderWidth": "2"
}
},
"graph": {
"itemStyle": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"lineStyle": {
"width": "1",
"color": "#cccccc"
},
"symbolSize": "10",
"symbol": "emptyCircle",
"smooth": true,
"color": [
"#3fb1e3",
"#6be6c1",
"#626c91",
"#a0a7e6",
"#c4ebad",
"#96dee8"
],
"label": {
"color": "#ffffff"
}
},
"map": {
"itemStyle": {
"areaColor": "#eeeeee",
"borderColor": "#aaaaaa",
"borderWidth": 0.5
},
"label": {
"color": "#ffffff"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(63,177,227,0.25)",
"borderColor": "#3fb1e3",
"borderWidth": 1
},
"label": {
"color": "rgb(63,177,227)"
}
}
},
"geo": {
"itemStyle": {
"areaColor": "#eeeeee",
"borderColor": "#aaaaaa",
"borderWidth": 0.5
},
"label": {
"color": "#ffffff"
},
"emphasis": {
"itemStyle": {
"areaColor": "rgba(63,177,227,0.25)",
"borderColor": "#3fb1e3",
"borderWidth": 1
},
"label": {
"color": "rgb(63,177,227)"
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#999999"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#999999"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#999999"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"color": "#999999"
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"toolbox": {
"iconStyle": {
"borderColor": "#999999"
},
"emphasis": {
"iconStyle": {
"borderColor": "#666666"
}
}
},
"legend": {
"textStyle": {
"color": "#999999"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#cccccc",
"width": 1
},
"crossStyle": {
"color": "#cccccc",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#626c91",
"width": 1
},
"itemStyle": {
"color": "#626c91",
"borderWidth": 1
},
"controlStyle": {
"color": "#626c91",
"borderColor": "#626c91",
"borderWidth": 0.5
},
"checkpointStyle": {
"color": "#3fb1e3",
"borderColor": "rgba(63,177,227,0.15)"
},
"label": {
"color": "#626c91"
},
"emphasis": {
"itemStyle": {
"color": "#626c91"
},
"controlStyle": {
"color": "#626c91",
"borderColor": "#626c91",
"borderWidth": 0.5
},
"label": {
"color": "#626c91"
}
}
},
"visualMap": {
"color": [
"#2a99c9",
"#afe8ff"
]
},
"dataZoom": {
"backgroundColor": "rgba(255,255,255,0)",
"dataBackgroundColor": "rgba(222,222,222,1)",
"fillerColor": "rgba(114,230,212,0.25)",
"handleColor": "#cccccc",
"handleSize": "100%",
"textStyle": {
"color": "#999999"
}
},
"markPoint": {
"label": {
"color": "#ffffff"
},
"emphasis": {
"label": {
"color": "#ffffff"
}
}
}
});
});

View File

@ -0,0 +1,503 @@
/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
* @license MIT */
;(function(root, factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.NProgress = factory();
}
})(this, function() {
var NProgress = {};
NProgress.version = '0.2.0';
var Settings = NProgress.settings = {
minimum: 0.08,
easing: 'linear',
positionUsing: '',
speed: 200,
trickle: true,
trickleSpeed: 200,
showSpinner: true,
barSelector: '[role="bar"]',
spinnerSelector: '[role="spinner"]',
parent: 'body',
template: '<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'
};
/**
* Updates configuration.
*
* NProgress.configure({
* minimum: 0.1
* });
*/
NProgress.configure = function(options) {
var key, value;
for (key in options) {
value = options[key];
if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;
}
return this;
};
/**
* Last number.
*/
NProgress.status = null;
/**
* Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.
*
* NProgress.set(0.4);
* NProgress.set(1.0);
*/
NProgress.set = function(n) {
var started = NProgress.isStarted();
n = clamp(n, Settings.minimum, 1);
NProgress.status = (n === 1 ? null : n);
var progress = NProgress.render(!started),
bar = progress.querySelector(Settings.barSelector),
speed = Settings.speed,
ease = Settings.easing;
progress.offsetWidth; /* Repaint */
queue(function(next) {
// Set positionUsing if it hasn't already been set
if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();
// Add transition
css(bar, barPositionCSS(n, speed, ease));
if (n === 1) {
// Fade out
css(progress, {
transition: 'none',
opacity: 1
});
progress.offsetWidth; /* Repaint */
setTimeout(function() {
css(progress, {
transition: 'all ' + speed + 'ms linear',
opacity: 0
});
setTimeout(function() {
NProgress.remove();
next();
}, speed);
}, speed);
} else {
setTimeout(next, speed);
}
});
return this;
};
NProgress.isStarted = function() {
return typeof NProgress.status === 'number';
};
/**
* Shows the progress bar.
* This is the same as setting the status to 0%, except that it doesn't go backwards.
*
* NProgress.start();
*
*/
NProgress.start = function() {
if (!NProgress.status) NProgress.set(0);
var work = function() {
setTimeout(function() {
if (!NProgress.status) return;
NProgress.trickle();
work();
}, Settings.trickleSpeed);
};
if (Settings.trickle) work();
return this;
};
/**
* Hides the progress bar.
* This is the *sort of* the same as setting the status to 100%, with the
* difference being `done()` makes some placebo effect of some realistic motion.
*
* NProgress.done();
*
* If `true` is passed, it will show the progress bar even if its hidden.
*
* NProgress.done(true);
*/
NProgress.done = function(force) {
if (!force && !NProgress.status) return this;
return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);
};
/**
* Increments by a random amount.
*/
NProgress.inc = function(amount) {
var n = NProgress.status;
if (!n) {
return NProgress.start();
} else if(n > 1) {
return;
} else {
if (typeof amount !== 'number') {
if (n >= 0 && n < 0.2) { amount = 0.1; }
else if (n >= 0.2 && n < 0.5) { amount = 0.04; }
else if (n >= 0.5 && n < 0.8) { amount = 0.02; }
else if (n >= 0.8 && n < 0.99) { amount = 0.005; }
else { amount = 0; }
}
n = clamp(n + amount, 0, 0.994);
return NProgress.set(n);
}
};
NProgress.trickle = function() {
return NProgress.inc();
};
/**
* Waits for all supplied jQuery promises and
* increases the progress as the promises resolve.
*
* @param $promise jQUery Promise
*/
(function() {
var initial = 0, current = 0;
NProgress.promise = function($promise) {
if (!$promise || $promise.state() === "resolved") {
return this;
}
if (current === 0) {
NProgress.start();
}
initial++;
current++;
$promise.always(function() {
current--;
if (current === 0) {
initial = 0;
NProgress.done();
} else {
NProgress.set((initial - current) / initial);
}
});
return this;
};
})();
/**
* (Internal) renders the progress bar markup based on the `template`
* setting.
*/
NProgress.render = function(fromStart) {
if (NProgress.isRendered()) return document.getElementById('nprogress');
addClass(document.documentElement, 'nprogress-busy');
var progress = document.createElement('div');
progress.id = 'nprogress';
progress.innerHTML = Settings.template;
var bar = progress.querySelector(Settings.barSelector),
perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0),
parent = isDOM(Settings.parent)
? Settings.parent
: document.querySelector(Settings.parent),
spinner
css(bar, {
transition: 'all 0 linear',
transform: 'translate3d(' + perc + '%,0,0)'
});
if (!Settings.showSpinner) {
spinner = progress.querySelector(Settings.spinnerSelector);
spinner && removeElement(spinner);
}
if (parent != document.body) {
addClass(parent, 'nprogress-custom-parent');
}
parent.appendChild(progress);
return progress;
};
/**
* Removes the element. Opposite of render().
*/
NProgress.remove = function() {
removeClass(document.documentElement, 'nprogress-busy');
var parent = isDOM(Settings.parent)
? Settings.parent
: document.querySelector(Settings.parent)
removeClass(parent, 'nprogress-custom-parent')
var progress = document.getElementById('nprogress');
progress && removeElement(progress);
};
/**
* Checks if the progress bar is rendered.
*/
NProgress.isRendered = function() {
return !!document.getElementById('nprogress');
};
/**
* Determine which positioning CSS rule to use.
*/
NProgress.getPositioningCSS = function() {
// Sniff on document.body.style
var bodyStyle = document.body.style;
// Sniff prefixes
var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :
('MozTransform' in bodyStyle) ? 'Moz' :
('msTransform' in bodyStyle) ? 'ms' :
('OTransform' in bodyStyle) ? 'O' : '';
if (vendorPrefix + 'Perspective' in bodyStyle) {
// Modern browsers with 3D support, e.g. Webkit, IE10
return 'translate3d';
} else if (vendorPrefix + 'Transform' in bodyStyle) {
// Browsers without 3D support, e.g. IE9
return 'translate';
} else {
// Browsers without translate() support, e.g. IE7-8
return 'margin';
}
};
/**
* Helpers
*/
function isDOM (obj) {
if (typeof HTMLElement === 'object') {
return obj instanceof HTMLElement
}
return (
obj &&
typeof obj === 'object' &&
obj.nodeType === 1 &&
typeof obj.nodeName === 'string'
)
}
function clamp(n, min, max) {
if (n < min) return min;
if (n > max) return max;
return n;
}
/**
* (Internal) converts a percentage (`0..1`) to a bar translateX
* percentage (`-100%..0%`).
*/
function toBarPerc(n) {
return (-1 + n) * 100;
}
/**
* (Internal) returns the correct CSS for changing the bar's
* position given an n percentage, and speed and ease from Settings
*/
function barPositionCSS(n, speed, ease) {
var barCSS;
if (Settings.positionUsing === 'translate3d') {
barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };
} else if (Settings.positionUsing === 'translate') {
barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };
} else {
barCSS = { 'margin-left': toBarPerc(n)+'%' };
}
barCSS.transition = 'all '+speed+'ms '+ease;
return barCSS;
}
/**
* (Internal) Queues a function to be executed.
*/
var queue = (function() {
var pending = [];
function next() {
var fn = pending.shift();
if (fn) {
fn(next);
}
}
return function(fn) {
pending.push(fn);
if (pending.length == 1) next();
};
})();
/**
* (Internal) Applies css properties to an element, similar to the jQuery
* css method.
*
* While this helper does assist with vendor prefixed property names, it
* does not perform any manipulation of values prior to setting styles.
*/
var css = (function() {
var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],
cssProps = {};
function camelCase(string) {
return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function(match, letter) {
return letter.toUpperCase();
});
}
function getVendorProp(name) {
var style = document.body.style;
if (name in style) return name;
var i = cssPrefixes.length,
capName = name.charAt(0).toUpperCase() + name.slice(1),
vendorName;
while (i--) {
vendorName = cssPrefixes[i] + capName;
if (vendorName in style) return vendorName;
}
return name;
}
function getStyleProp(name) {
name = camelCase(name);
return cssProps[name] || (cssProps[name] = getVendorProp(name));
}
function applyCss(element, prop, value) {
prop = getStyleProp(prop);
element.style[prop] = value;
}
return function(element, properties) {
var args = arguments,
prop,
value;
if (args.length == 2) {
for (prop in properties) {
value = properties[prop];
if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);
}
} else {
applyCss(element, args[1], args[2]);
}
}
})();
/**
* (Internal) Determines if an element or space separated list of class names contains a class name.
*/
function hasClass(element, name) {
var list = typeof element == 'string' ? element : classList(element);
return list.indexOf(' ' + name + ' ') >= 0;
}
/**
* (Internal) Adds a class to an element.
*/
function addClass(element, name) {
var oldList = classList(element),
newList = oldList + name;
if (hasClass(oldList, name)) return;
// Trim the opening space.
element.className = newList.substring(1);
}
/**
* (Internal) Removes a class from an element.
*/
function removeClass(element, name) {
var oldList = classList(element),
newList;
if (!hasClass(element, name)) return;
// Replace the class name.
newList = oldList.replace(' ' + name + ' ', ' ');
// Trim the opening and closing spaces.
element.className = newList.substring(1, newList.length - 1);
}
/**
* (Internal) Gets a space separated list of the class names on the element.
* The list is wrapped with a single space on each end to facilitate finding
* matches within the list.
*/
function classList(element) {
return (' ' + (element && element.className || '') + ' ').replace(/\s+/gi, ' ');
}
/**
* (Internal) Removes an element from the DOM.
*/
function removeElement(element) {
element && element.parentNode && element.parentNode.removeChild(element);
}
return NProgress;
});
layui.define([], function(exports) {
exports('nprogress', NProgress);
});

View File

@ -0,0 +1,47 @@
layui.define(['layer'], function(exports) {
"use strict";
var MOD_NAME = 'popup',
layer = layui.layer;
var popup = new function() {
this.success = function(msg) {
layer.msg(msg, {
icon: 1,
time: 1000
})
},
this.failure = function(msg) {
layer.msg(msg, {
icon: 2,
time: 1000
})
},
this.warning = function(msg) {
layer.msg(msg, {
icon: 3,
time: 1000
})
},
this.success = function(msg, callback) {
layer.msg(msg, {
icon: 1,
time: 1000
}, callback);
},
this.failure = function(msg, callback) {
layer.msg(msg, {
icon: 2,
time: 1000
}, callback);
},
this.warming = function(msg, callback) {
layer.msg(msg, {
icon: 3,
time: 1000
}, callback);
}
};
exports(MOD_NAME, popup);
})

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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.6;
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

@ -20,7 +20,6 @@ layui.define(['table', 'jquery', 'element'], function (exports) {
defaultOpen: opt.defaultOpen,
defaultSelect: opt.defaultSelect,
control: opt.control,
controlWidth: opt.controlWidth ? opt.controlWidth : "auto",
defaultMenu: opt.defaultMenu,
accordion: opt.accordion,
height: opt.height,
@ -57,31 +56,6 @@ layui.define(['table', 'jquery', 'element'], function (exports) {
// 处理高度
$("#" + opt.elem).height(option.height)
setTimeout(function () {
$("#" + opt.control + " .control").on("mousewheel DOMMouseScroll", function (event) {
var delta = (event.originalEvent.wheelDelta && (event.originalEvent.wheelDelta > 0 ? 1 : -1)) || // chrome & ie
(event.originalEvent.detail && (event.originalEvent.detail > 0 ? -1 : 1)); // firefox
if (delta > 0) {
for (var num = 1; num < 20; num++) {
setTimeout(function () {
if ($("#" + opt.control + " .control ul").css('left').replace("px", "") < 0) {
$("#" + opt.control + " .control ul").css("left", "+=2px");
}
}, 10)
}
} else if (delta < 0) {
if (((Number)($("#" + opt.control + " .control ul").css("left").replace("px", "")) + ($("#" + opt.control + " .control ul").width() - $("#" + opt.control + " .control").width())) > 0) {
for (var num = 1; num < 20; num++) {
setTimeout(function () {
$("#" + opt.control + " .control ul").css("left", "-=2px");
}, 10)
}
}
}
});
}, 1000)
return new pearMenu(option);
}
@ -322,7 +296,8 @@ layui.define(['table', 'jquery', 'element'], function (exports) {
}
function createMenuAndControl(option) {
var control = '<div style="width: ' + option.controlWidth + 'px;white-space: nowrap;overflow-x: scroll;overflow: hidden;" class="control"><ul class="layui-nav pear-nav-control pc layui-hide-xs" style="width: fit-content;">';
var control = '<div class="control"><ul class="layui-nav pear-nav-control pc layui-hide-xs" style="width: fit-content;">';
control+= '<li class="layui-nav-item tabdrop layui-hide" style="float:right !important;"><a href="javascript:;"><i class="layui-icon layui-icon-more layui-font-20"></i></a><dl class="layui-nav-child"></dl></li>';
var controlPe = '<ul class="layui-nav pear-nav-control layui-hide-sm">';
// 声 明 头 部
var menu = '<div class="layui-side-scroll ' + option.theme + '">'
@ -479,7 +454,6 @@ layui.define(['table', 'jquery', 'element'], function (exports) {
});
});
} else {
$(this).parent().addClass("layui-nav-itemed");
ele.animate({
height: "0px"
}, 240, function () {
@ -551,10 +525,57 @@ layui.define(['table', 'jquery', 'element'], function (exports) {
rationalizeWidth = $headerControl.parent().innerWidth() - $headerControl.position().left;
}
if (option.controlWidth && rationalizeWidth >= option.controlWidth) {
rationalizeWidth = option.controlWidth;
}
$("#" + option.control + " .control").css({ "width": rationalizeWidth, "transition": "width .15s" });
$("#" + option.control + " .control").css({"width": rationalizeWidth});
var navobj = $("#" + option.control+' ul.pear-nav-control.pc');
var dropdown = $(".tabdrop", navobj);
var collection = 0;
var maxwidth = rationalizeWidth - 60;
var liwidth = 0;
//检查超过一行的标签页
$('.tabdrop').find('dd').each(function(){
var newLI = $('<li></li>').html($(this).html());
newLI.addClass('layui-nav-item');
newLI.attr('pear-href', $(this).attr('pear-href'));
newLI.attr('pear-title', $(this).attr('pear-title'));
newLI.attr('pear-id', $(this).attr('pear-id'));
navobj.append(newLI);
$(this).remove();
})
var litabs = navobj.find('>li').not('.tabdrop');
var totalwidth = 0;
litabs.each(function () {
totalwidth += $(this).outerWidth(true);
});
if (rationalizeWidth < totalwidth) {
litabs.each(function () {
liwidth += $(this).outerWidth(true);
if (liwidth > maxwidth) {
var newDD = $('<dd></dd>').html($(this).html());
newDD.attr('pear-href', $(this).attr('pear-href'));
newDD.attr('pear-title', $(this).attr('pear-title'));
newDD.attr('pear-id', $(this).attr('pear-id'));
dropdown.find('dl').append(newDD);
collection++;
$(this).remove();
}
});
if (collection > 0) {
dropdown.removeClass('layui-hide');
if (dropdown.find('.active').length === 1) {
dropdown.addClass('active');
} else {
dropdown.removeClass('active');
}
}
}else {
dropdown.addClass('layui-hide');
}
}
function rationalizeHeaderControlWidthAuto(option){

View File

@ -0,0 +1,233 @@
layui.define(['jquery', 'tools'], function (exports) {
"use strict";
/**
* @since Pear Admin 4.0
*
* Button component
* */
var MOD_NAME = 'menuSearch',
tools = layui.tools,
$ = layui.jquery;
var menuSearch = function (opt) {
this.option = opt;
};
/**
* @since Pear Admin 4.0
*
* Button start loading
* */
menuSearch.prototype.render = function (opt) {
var options = {
select: opt.select,
elem: opt.elem,
dataProvider: opt.dataProvider,
}
$('body').on("click", options.elem, function () {
var _html = [
`<div class="menu-search-content">
<div class="layui-form menu-search-input-wrapper">
<div class=" layui-input-wrap layui-input-wrap-prefix">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-search"></i>
</div>
<input type="text" name="menuSearch" value="" placeholder="搜索菜单" autocomplete="off" class="layui-input" lay-affix="clear">
</div>
</div>
<div class="menu-search-no-data"> </div>
<ul class="menu-search-list">
</ul>
<div class="menu-search-tips">
<div>
<span class="mr-1">选择</span><kbd class="mr-1 w-5"> </kbd><kbd class="mr-5 w-5"> </kbd>
<span class="mr-1">确定</span><kbd class="mr-5"> Enter </kbd><span class="mr-1"></span><kbd class="mr-1"> Esc </kbd>
</div>
</div>
</div>`
].join('');
layer.open({
type: 1,
offset: "10%",
area: ['600px'],
title: false,
closeBtn: 0,
shadeClose: true,
anim: 0,
move: false,
content: _html,
success: function (layero, layeridx) {
var $layer = layero;
var $content = $(layero).children('.layui-layer-content');
var $input = $(".menu-search-input-wrapper input");
var $noData = $(".menu-search-no-data");
var $list = $(".menu-search-list");
var menuData = options.dataProvider();
$layer.css("border-radius", "6px");
$input.off("focus").focus();
// 搜索输入事件
$input.off("input").on("input", tools.debounce(function () {
var keywords = $input.val().trim();
var filteredMenus = filterHandle(menuData, keywords);
if (filteredMenus.length) {
var tiledMenus = tiledHandle(filteredMenus);
var listHtml = createList(tiledMenus);
$noData.css("display", "none");
$list.html("").append(listHtml).children(":first").addClass("this")
} else {
$list.html("");
$noData.css("display", "flex");
}
var currentHeight = $(".menu-search-content").outerHeight()
$layer.css("height", currentHeight);
$content.css("height", currentHeight);
}, 500)
)
// 列表点击事件
$list.off("click").on("click", "li", function () {
var id = $(this).attr("smenu-id");
var title = $(this).attr("smenu-title");
var url = $(this).attr("smenu-url");
var type = $(this).attr("smenu-type");
var openType = $(this).attr("smenu-open-type");
options.select({ id, title, url, type, openType });
layer.close(layeridx);
})
$list.off('mouseenter').on("mouseenter", "li", function () {
$(".menu-search-list li.this").removeClass("this");
$(this).addClass("this");
}).off("mouseleave").on("mouseleave", "li", function () {
$(this).removeClass("this");
})
// 监听键盘事件
$('.menu-search-content').off("keydown").keydown(function (e) {
if (e.keyCode === 13 || e.keyCode === 32) {
e.preventDefault();
var that = $(".menu-search-list li.this");
var id = that.attr("smenu-id");
var title = that.attr("smenu-title");
var url = that.attr("smenu-url");
var type = that.attr("smenu-type");
var openType = that.attr("smenu-open-type");
options.select({ id, title, url, type, openType });
layer.close(layeridx);
} else if (e.keyCode === 38) {
e.preventDefault();
var prevEl = $(".menu-search-list li.this").prev();
$(".menu-search-list li.this").removeClass("this");
if (prevEl.length !== 0) {
prevEl.addClass("this");
} else {
$list.children().last().addClass("this");
}
} else if (e.keyCode === 40) {
e.preventDefault();
var nextEl = $(".menu-search-list li.this").next();
$(".menu-search-list li.this").removeClass("this");
if (nextEl.length !== 0) {
nextEl.addClass("this");
} else {
$list.children().first().addClass("this");
}
} else if (e.keyCode === 27) {
e.preventDefault();
layer.close(layeridx);
}
})
}
})
});
return new menuSearch(options);
}
/**
* @since Pear Admin 4.0
*
* 创建结果列表
*/
var createList = function (data) {
var listHtml = '';
$.each(data, function (index, item) {
listHtml += `<li smenu-open-type="${item.info.openType}" smenu-id="${item.info.id}" smenu-icon="'${item.info.icon}" smenu-url="${item.info.href}" smenu-title="${item.info.title}" smenu-type="${item.info.type}">
<span><i style="margin-right:10px" class="${item.info.icon}"></i>${item.path}</span>
<i class="layui-icon layui-icon-right"></i>
</li>`
})
return listHtml;
}
/**
* @since Pear Admin 4.0
*
* Tree path 列表
*/
var tiledHandle = function (data) {
var tiledMenus = [];
var treeTiled = function (data, content) {
var path = "";
var separator = " / ";
if (!content) content = "";
$.each(data, function (index, item) {
if (item.children && item.children.length) {
path += content + item.title + separator;
var childPath = treeTiled(item.children, path);
path += childPath;
if (!childPath) path = ""; // 重置路径
} else {
path += content + item.title
tiledMenus.push({ path: path, info: item });
path = ""; //重置路径
}
})
return path;
};
treeTiled(data);
return tiledMenus;
}
/**
* @since Pear Admin 4.0
*
* 查询匹配算法
*/
var filterHandle = function (filterData, val) {
if (!val) return [];
var filteredMenus = [];
filterData = $.extend(true, {}, filterData);
$.each(filterData, function (index, item) {
if (item.children && item.children.length) {
var children = filterHandle(item.children, val)
var obj = $.extend({}, item, { children: children });
if (children && children.length) {
filteredMenus.push(obj);
} else if (item.title.indexOf(val) >= 0) {
item.children = []; // 父级匹配但子级不匹配,就去除子级
filteredMenus.push($.extend({}, item));
}
} else if (item.title.indexOf(val) >= 0) {
filteredMenus.push(item);
}
})
return filteredMenus;
}
exports(MOD_NAME, new menuSearch());
});

View File

@ -0,0 +1,85 @@
layui.define(['table', 'jquery', 'element', 'dropdown'], function (exports) {
"use strict";
var MOD_NAME = 'messageCenter',
$ = layui.jquery,
dropdown = layui.dropdown;
var message = function (opt) {
this.option = opt;
};
message.prototype.render = function (opt) {
var option = {
elem: opt.elem,
url: opt.url ? opt.url : false,
height: opt.height,
data: opt.data
}
if (option.url != false) {
$.get(option.url, function (result) {
const { code, success, data } = result;
$(`${opt.elem}`).append(`<li class="layui-nav-item" lay-unselect="">
<a href="#" class="notice layui-icon layui-icon-notice"></a>
</li>`);
if (code == 200 || success) {
option.data = data;
dropdown.render({
elem: option.elem,
align: "center",
content: createHtml(option),
})
}
});
}
return new message(option);
}
message.prototype.click = function (callback) {
$("*[notice-id]").click(function (event) {
event.preventDefault();
var id = $(this).attr("notice-id");
var title = $(this).attr("notice-title");
var context = $(this).attr("notice-context");
var form = $(this).attr("notice-form");
callback(id, title, context, form);
})
}
function createHtml(option) {
var count = 0;
var notice = '<div class="pear-message-center"><div class="layui-tab layui-tab-brief">'
var noticeTitle = '<ul class="layui-tab-title">';
var noticeContent = '<div class="layui-tab-content" style="height:' + option.height + ';overflow-x: hidden;padding:0px;">';
$.each(option.data, function (i, item) {
noticeTitle += `<li class="${i === 0 ? 'layui-this' : ''}">${item.title}</li>`;
noticeContent += '<div class="layui-tab-item layui-show">';
$.each(item.children, function (i, note) {
count++;
noticeContent += '<div class="message-item" notice-form="' + note.form + '" notice-context="' + note.context +
'" notice-title="' + note.title + '" notice-id="' + note.id + '">';
noticeContent += '<img src="' + note.avatar + '"/><div style="display:inline-block;">' + note.title + '</div>' +
'<div class="extra">' + note.time + '</div>' +
'</div>';
})
noticeContent += '</div>';
})
noticeTitle += '</ul>';
noticeContent += '</div>';
notice += noticeTitle;
notice += noticeContent;
notice += "</div></div>"
return notice;
}
exports(MOD_NAME, new message());
})

View File

@ -0,0 +1,132 @@
layui.define(['jquery', 'element'], function (exports) {
"use strict";
var $ = layui.jquery;
var element = layui.element;
var page = function (opt) {
this.option = opt;
};
/**
* @since Pear Admin 4.0
*
* 创建 Page 页面
*/
page.prototype.render = function (opt) {
var option = {
elem: opt.elem,
url: opt.url,
width: opt.width || "100%",
height: opt.height || "100%",
title: opt.title
}
renderContent(option);
return new page(option);
}
/**
* @since Pear Admin 4.0
*
* 切换 Page 页面
*/
page.prototype.changePage = function (options) {
const $frame = $(`#${this.option.elem} .pear-page-content`);
if (options.type === "_iframe") {
$frame.html(`<iframe src='${options.href}' scrolling='auto' frameborder='0' allowfullscreen='true'></iframe>`);
} else {
$.ajax({
url: options.href,
type: 'get',
dataType: 'html',
success: function (data) {
$frame.html(data)
},
error: function (xhr) {
return layer.msg('Status:' + xhr.status + '' + xhr.statusText + ',请稍后再试!');
}
});
}
$frame.attr("type", options.type);
$frame.attr("href", options.href);
}
page.prototype.refresh = function (loading) {
var $frameLoad = $(`#${this.option.elem} .pear-page-loading`);
var $frame = $(`#${this.option.elem} .pear-page-content`);
if (loading) {
$frameLoad.css({
display: 'block'
});
}
if ($frame.attr("type") === "_iframe") {
$frame.html(`<iframe src='${$frame.attr("href")}' scrolling='auto' frameborder='0' allowfullscreen='true'></iframe>`);
const $contentFrame = $frame.find("iframe");
$contentFrame.on("load", () => {
$frameLoad.fadeOut(1000);
})
} else {
$.ajax({
type: 'get',
url: $frame.attr("href"),
dataType: 'html',
success: function (data) {
$frame.html(data)
$frameLoad.fadeOut(1000);
element.init();
},
error: function (xhr) {
return layer.msg('Status:' + xhr.status + '' + xhr.statusText + ',请稍后再试!');
}
});
}
}
function renderContent(option) {
$("#" + option.elem).html(`
<div class='pear-page'>
<div class='pear-page-content' type='${option.type}' href='${option.url}'></div>
<div class="pear-page-loading">
<div class="ball-loader">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
</div>`);
var $frame = $("#" + option.elem).find(".pear-page-content");
if (option.type === "_iframe") {
$frame.html(`<iframe src='${option.url}' scrolling='auto' frameborder='0' allowfullscreen='true'></iframe>`);
} else {
$.ajax({
url: option.url,
type: 'get',
dataType: 'html',
success: function (data) {
$frame.html(data);
},
error: function (xhr) {
return layer.msg('Status:' + xhr.status + '' + xhr.statusText + ',请稍后再试!');
}
});
}
}
exports('page', new page());
});

View File

@ -0,0 +1,626 @@
layui.define(['jquery', 'element', 'dropdown'], function (exports) {
"use strict";
var MOD_NAME = 'tabPage',
$ = layui.jquery,
dropdown = layui.dropdown,
element = layui.element;
var tabPage = function (opt) {
this.option = opt;
};
var tabData = new Array();
var tabDataCurrent = 0;
var contextTabDOM;
tabPage.prototype.render = function (opt) {
var option = {
elem: opt.elem,
data: opt.data,
index: opt.index,
tool: opt.tool || true,
roll: opt.roll || true,
success: opt.success ? opt.success : function (id) { },
session: opt.session ? opt.session : false,
preload: opt.preload ? opt.preload : false,
height: opt.height || "100%",
width: opt.width || "100%",
closeEvent: opt.closeEvent,
tabMax: opt.tabMax,
}
if (option.session) {
if (sessionStorage.getItem(option.elem + "-pear-tab-page-data") != null) {
tabData = JSON.parse(sessionStorage.getItem(option.elem + "-pear-tab-page-data"));
option.data = JSON.parse(sessionStorage.getItem(option.elem + "-pear-tab-page-data"));
tabDataCurrent = sessionStorage.getItem(option.elem + "-pear-tab-page-data-current");
tabData.forEach(function (item, index) {
if (item.id == tabDataCurrent) {
option.index = index;
}
})
} else {
tabData = opt.data;
}
}
var lastIndex;
var tab = createTab(option);
$("#" + option.elem).html(tab);
$(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-prev").click(function () {
rollPage("left", option);
})
$(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-next").click(function () {
rollPage("right", option);
})
element.init();
$("#" + option.elem).width(opt.width);
$("#" + option.elem).height(opt.height);
$("#" + option.elem).css({
position: "relative"
});
closeEvent(option);
option.success(sessionStorage.getItem(option.elem + "-pear-tab-page-data-current"));
dropdown.render({
elem: `#${option.elem} .layui-tab-control > .layui-icon-down`,
trigger: 'hover',
data: [{
title: '关 闭 当 前',
id: 1
}, {
title: '关 闭 其 他',
id: 2
}, {
title: '关 闭 全 部',
id: 3
}],
click: function (obj) {
const id = obj.id;
if (id === 1) {
var currentTab = $(".layui-tab[lay-filter='" + option.elem +
"'] .layui-tab-title .layui-this");
if (currentTab.find("span").is(".able-close")) {
var currentId = currentTab.attr("lay-id");
tabDelete(option.elem, currentId, option.closeEvent, option);
} else {
layer.msg("当前页面不允许关闭", {
icon: 3,
time: 1000
})
}
} else if (id === 2) {
var currentId = $(".layui-tab[lay-filter='" + option.elem +
"'] .layui-tab-title .layui-this").attr("lay-id");
var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li");
$.each(tabtitle, function (i) {
if ($(this).attr("lay-id") != currentId) {
if ($(this).find("span").is(".able-close")) {
tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent,
option);
}
}
})
} else {
var currentId = $(".layui-tab[lay-filter='" + option.elem +
"'] .layui-tab-title .layui-this").attr("lay-id");
var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li");
$.each(tabtitle, function (i) {
if ($(this).find("span").is(".able-close")) {
tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, option);
}
})
}
}
})
$("body .layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title").on("contextmenu", "li",
function (e) {
var top = e.clientY;
var left = e.clientX;
var menuWidth = 100;
var currentId = $(this).attr("lay-id");
var menu = `<ul>
<li class='item' id='${option.elem}closeThis'>关闭当前</li>
<li class='item' id='${option.elem}closeOther'>关闭其他</li>
<li class='item' id='${option.elem}closeAll'>关闭所有</li>
</ul>`;
contextTabDOM = $(this);
var isOutsideBounds = (left + menuWidth) > $(window).width();
if (isOutsideBounds) {
left = $(window).width() - menuWidth;
}
layer.open({
type: 1,
title: false,
shade: false,
skin: 'pear-tab-page-menu',
closeBtn: false,
area: [menuWidth + 'px', '108px'],
fixed: true,
anim: false,
isOutAnim: false,
offset: [top, left],
content: menu,
success: function (layero, index) {
layer.close(lastIndex);
lastIndex = index;
menuEvent(option, index);
var timer;
$(layero).on('mouseout', function () {
timer = setTimeout(function () {
layer.close(index);
}, 30)
});
$(layero).on('mouseover', function () {
clearTimeout(timer);
});
$(layero).on('contextmenu', function () {
return false;
})
}
});
return false;
})
mousewheelAndTouchmoveHandler(option)
return new tabPage(option);
}
tabPage.prototype.click = function (callback) {
var option = this.option;
var elem = this.option.elem;
element.on('tab(' + this.option.elem + ')', function (data) {
var id = $("#" + elem + " .layui-tab-title .layui-this").attr("lay-id");
sessionStorage.setItem(option.elem + "-pear-tab-page-data-current", id);
callback(id);
});
}
tabPage.prototype.positionTab = function () {
var $tabTitle = $('.layui-tab[lay-filter=' + this.option.elem + '] .layui-tab-title');
var autoLeft = 0;
$tabTitle.children("li").each(function () {
if ($(this).hasClass('layui-this')) {
return false;
} else {
autoLeft += $(this).outerWidth();
}
});
$tabTitle.animate({
scrollLeft: autoLeft - $tabTitle.width() / 3
}, 200);
}
tabPage.prototype.clear = function () {
sessionStorage.removeItem(this.option.elem + "-pear-tab-page-data");
sessionStorage.removeItem(this.option.elem + "-pear-tab-page-data-current");
}
var index = 0;
// 根据过滤 fliter 标识, 重置选项卡标题
tabPage.prototype.changeTabTitleById = function (elem, id, title) {
var currentTab = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title [lay-id='" + id +
"'] .title");
currentTab.html(title);
}
// 根据过滤 filter 标识, 删除指定选项卡
tabPage.prototype.delTabByElem = function (elem, id, callback) {
var currentTab = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title [lay-id='" + id + "']");
if (currentTab.find("span").is(".able-close")) {
tabDelete(elem, id, callback);
}
}
// 根据过滤 filter 标识, 删除其他选项卡
tabPage.prototype.delOtherTabByElem = function (elem, callback) {
var currentId = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title .layui-this").attr(
"lay-id");
var tabtitle = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title li");
$.each(tabtitle, function (i) {
if ($(this).attr("lay-id") != currentId) {
if ($(this).find("span").is(".able-close")) {
tabDelete(elem, $(this).attr("lay-id"), callback);
}
}
})
}
// 根据过滤 filter 标识, 删除全部选项卡
tabPage.prototype.delAllTabByElem = function (elem, callback) {
var currentId = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title .layui-this").attr(
"lay-id");
var tabtitle = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title li");
$.each(tabtitle, function (i) {
if ($(this).find("span").is(".able-close")) {
tabDelete(elem, $(this).attr("lay-id"), callback);
}
})
}
// 根据过滤 filter 标识, 删除当前选项卡
tabPage.prototype.delCurrentTabByElem = function (elem, callback) {
var currentTab = $(".layui-tab[lay-filter='" + elem + "'] .layui-tab-title .layui-this");
if (currentTab.find("span").is(".able-close")) {
var currentId = currentTab.attr("lay-id");
tabDelete(elem, currentId, callback);
}
}
/**
* @since Pear Admin 4.0
*/
tabPage.prototype.addTabOnly = function (opt, time) {
var title = `<span class="pear-tab-page-active"></span>
<span class="${opt.close ? 'able-close' : 'disable-close'} title">${opt.title}</span>
<i class="layui-icon layui-unselect layui-tab-close"></i>`;
if ($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]").length <=
0) {
var that = this;
if (opt.type === "_iframe") {
element.tabAdd(this.option.elem, {
id: opt.id,
title: title,
content: `<iframe id="${opt.id}" type="${opt.type}" data-frameid="${opt.id}" scrolling="auto" frameborder="0" src="${opt.url}" style="width:100%;height:100%;" allowfullscreen="true"></iframe>`
});
} else {
$.ajax({
url: opt.url,
type: 'get',
dataType: 'html',
async: false,
success: function (data) {
element.tabAdd(that.option.elem, {
id: opt.id,
title: title,
content: `<div id="${opt.id}" type="${opt.type}" data-frameid="${opt.id}" src="${opt.url}">${data}</div>`,
});
},
error: function (xhr, textstatus, thrown) {
return layer.msg('Status:' + xhr.status + '' + xhr.statusText + ',请稍后再试!');
}
});
}
tabData.push(opt);
sessionStorage.setItem(that.option.elem + "-pear-tab-page-data", JSON.stringify(tabData));
sessionStorage.setItem(that.option.elem + "-pear-tab-page-data-current", opt.id);
} else {
var isData = false;
$.each($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]"),
function () {
if ($(this).attr("lay-id") == opt.id) {
isData = true;
}
})
if (isData == false) {
if (this.option.tabMax != false) {
if ($(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-title li[lay-id]")
.length >= this.option.tabMax) {
layer.msg("最多打开" + this.option.tabMax + "个标签页", {
icon: 2,
time: 1000,
shift: 6
});
return false;
}
}
var that = this;
if (opt.type === "_iframe") {
element.tabAdd(this.option.elem, {
id: opt.id,
title: title,
content: `<iframe id="${opt.id}" type="${opt.type}" data-frameid="${opt.id}" scrolling="auto" frameborder="0" src="${opt.url}" style="width:100%;height:100%;" allowfullscreen="true"></iframe>`
});
} else {
$.ajax({
url: opt.url,
type: 'get',
dataType: 'html',
async: false,
success: function (data) {
element.tabAdd(that.option.elem, {
id: opt.id,
title: title,
content: `<div id="${opt.id}" type="${opt.type}" data-frameid="${opt.id}" src="${opt.url}">${data}</div>`,
});
},
error: function (xhr, textstatus, thrown) {
return layer.msg('Status:' + xhr.status + '' + xhr.statusText + ',请稍后再试!');
}
});
}
tabData.push(opt);
sessionStorage.setItem(that.option.elem + "-pear-tab-page-data", JSON.stringify(tabData));
sessionStorage.setItem(that.option.elem + "-pear-tab-page-data-current", opt.id);
}
}
element.tabChange(this.option.elem, opt.id);
sessionStorage.setItem(this.option.elem + "-pear-tab-page-data-current", opt.id);
}
// 刷 新 指 定 的 选 项 卡
tabPage.prototype.refresh = function (time) {
var $iframe = $(".layui-tab[lay-filter='" + this.option.elem + "'] .layui-tab-content .layui-show > *");
var $iframeLoad;
if (time != false && time != 0) {
$iframe.parent().append(`<div id="pear-tab-page-loading${index}" class="pear-tab-page-loading"><div class="ball-loader"><span></span><span></span><span></span><span></span></div></div>`);
$iframeLoad = $("#" + this.option.elem).find("#pear-tab-page-loading" + index++);
$iframeLoad.css({
display: "block"
});
}
if($iframe.attr("type") === "_iframe") {
$iframe.attr("src", $iframe.attr("src"));
$iframe.on("load", function() {
$iframeLoad.fadeOut(1000, function() {
$iframeLoad.remove();
});
})
} else {
$.ajax({
url: $iframe.attr("src"),
type: 'get',
dataType: 'html',
success: function (data) {
$iframe.html(data);
if ($iframeLoad != undefined) {
$iframeLoad.fadeOut(1000, function () {
$iframeLoad.remove();
});
}
},
error: function (xhr) {
return layer.msg('Status:' + xhr.status + '' + xhr.statusText + ',请稍后再试!');
}
});
}
}
function tabDelete(elem, id, callback, option) {
var tabTitle = $(".layui-tab[lay-filter='" + elem + "']").find(".layui-tab-title");
var removeTab = tabTitle.find("li[lay-id='" + id + "']");
var nextNode = removeTab.next("li");
if (!removeTab.hasClass("layui-this")) {
removeTab.remove();
var tabContent = $(".layui-tab[lay-filter='" + elem + "']").find("*[id='" + id + "']")
.parent();
tabContent.remove();
tabData = JSON.parse(sessionStorage.getItem(elem + "-pear-tab-page-data"));
tabDataCurrent = sessionStorage.getItem(elem + "-pear-tab-page-data-current");
tabData = tabData.filter(function (item) {
return item.id != id;
})
sessionStorage.setItem(elem + "-pear-tab-page-data", JSON.stringify(tabData));
return false;
}
var currId;
if (nextNode.length) {
nextNode.addClass("layui-this");
currId = nextNode.attr("lay-id");
$("#" + elem + " [id='" + currId + "']").parent().addClass("layui-show");
} else {
var prevNode = removeTab.prev("li");
prevNode.addClass("layui-this");
currId = prevNode.attr("lay-id");
$("#" + elem + " [id='" + currId + "']").parent().addClass("layui-show");
}
callback(currId);
tabData = JSON.parse(sessionStorage.getItem(elem + "-pear-tab-page-data"));
tabDataCurrent = sessionStorage.getItem(elem + "-pear-tab-page-data-current");
tabData = tabData.filter(function (item) {
return item.id != id;
})
sessionStorage.setItem(elem + "-pear-tab-page-data", JSON.stringify(tabData));
sessionStorage.setItem(elem + "-pear-tab-page-data-current", currId);
removeTab.remove();
// 删除 content
var tabContent = $(".layui-tab[lay-filter='" + elem + "']").find("*[id='" + id + "']").parent();
// 删除
tabContent.remove();
}
/**
* @since Pear Admin 4.0
*/
function createTab(option) {
var type = "";
if (option.roll == true) {
type = "layui-tab-roll";
}
if (option.tool != false) {
type = "layui-tab-tool";
}
if (option.roll == true && option.tool != false) {
type = "layui-tab-rollTool";
}
var tab = '<div class="pear-tab-page ' + type + ' layui-tab" lay-filter="' + option.elem +
'" lay-allowClose="true">';
var title = '<ul class="layui-tab-title">';
var content = '<div class="layui-tab-content">';
var control = `<div class="layui-tab-control">
<li class="layui-tab-prev layui-icon layui-icon-left"></li>
<li class="layui-tab-next layui-icon layui-icon-right"></li>
<li class="layui-tab-tool layui-icon layui-icon-down"></li>
</div>`;
// 处 理 选 项 卡 头 部
var index = 0;
$.each(option.data, function (i, item) {
var titleItem = `<li lay-id="${item.id}" class="${option.index == index ? 'layui-this' : ''}">
<span class="pear-tab-page-active"></span>
<span class="${item.close ? 'able-close' : 'disable-close'} title">
${item.title}
</span>
<i class="layui-icon layui-unselect layui-tab-close"></i></li>
</li>`;
title += titleItem;
if (item.type === "_iframe") {
content += `<div class="${option.index == index ? 'layui-show' : ''} layui-tab-item"><iframe id="${item.id}" type="${item.type}" data-frameid="${item.id}" scrolling="auto" frameborder="0" src="${item.url}" style="width:100%;height:100%;" allowfullscreen="true"></iframe></div>`
} else {
$.ajax({
url: item.url,
type: 'get',
dataType: 'html',
async: false,
success: function (data) {
content += `<div class="${option.index == index ? 'layui-show' : ''} layui-tab-item"><div id="${item.id}" type="${item.type}" data-frameid="${item.id}" src="${item.url}">${data}</div></div>`;
},
error: function (xhr) {
return layer.msg('Status:' + xhr.status + '' + xhr.statusText + ',请稍后再试!');
}
});
}
index++;
});
title += '</ul>';
content += '</div>';
tab += title;
tab += control;
tab += content;
tab += '</div>';
tab += ''
return tab;
}
function rollPage(d, option) {
var $tabTitle = $('#' + option.elem + ' .layui-tab-title');
var left = $tabTitle.scrollLeft();
if ('left' === d) {
$tabTitle.animate({
scrollLeft: left - 450
}, 200);
} else {
$tabTitle.animate({
scrollLeft: left + 450
}, 200);
}
}
function closeEvent(option) {
$(".layui-tab[lay-filter='" + option.elem + "']").on("click", ".layui-tab-close", function () {
var layid = $(this).parent().attr("lay-id");
tabDelete(option.elem, layid, option.closeEvent, option);
})
}
function menuEvent(option, index) {
$("#" + option.elem + "closeThis").click(function () {
var currentTab = contextTabDOM;
if (currentTab.find("span").is(".able-close")) {
var currentId = currentTab.attr("lay-id");
tabDelete(option.elem, currentId, option.closeEvent, option);
} else {
layer.msg("当前页面不允许关闭", {
icon: 3,
time: 800
})
}
layer.close(index);
})
$("#" + option.elem + "closeOther").click(function () {
var currentId = contextTabDOM.attr("lay-id");
var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li");
$.each(tabtitle, function (i) {
if ($(this).attr("lay-id") != currentId) {
if ($(this).find("span").is(".able-close")) {
tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent,
option);
}
}
})
layer.close(index);
})
$("#" + option.elem + "closeAll").click(function () {
var tabtitle = $(".layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title li");
$.each(tabtitle, function (i) {
if ($(this).find("span").is(".able-close")) {
tabDelete(option.elem, $(this).attr("lay-id"), option.closeEvent, option);
}
})
layer.close(index);
})
}
function mousewheelAndTouchmoveHandler(option) {
var $bodyTab = $("body .layui-tab[lay-filter='" + option.elem + "'] .layui-tab-title")
var $tabTitle = $('#' + option.elem + ' .layui-tab-title');
var mouseScrollStep = 100
// 鼠标滚轮
$bodyTab.on("mousewheel DOMMouseScroll", function (e) {
e.originalEvent.preventDefault()
var delta = (e.originalEvent.wheelDelta && (e.originalEvent.wheelDelta > 0 ? "top" :
"down")) || // chrome & ie
(e.originalEvent.detail && (e.originalEvent.detail > 0 ? "down" : "top")); // firefox
var scrollLeft = $tabTitle.scrollLeft();
if (delta === "top") {
scrollLeft -= mouseScrollStep
} else if (delta === "down") {
scrollLeft += mouseScrollStep
}
$tabTitle.scrollLeft(scrollLeft)
});
// 触摸移动
var touchX = 0;
$bodyTab.on("touchstart", function (e) {
var touch = e.originalEvent.targetTouches[0];
touchX = touch.pageX
})
$bodyTab.on("touchmove", function (e) {
var event = e.originalEvent;
if (event.targetTouches.length > 1) return;
event.preventDefault();
var touch = event.targetTouches[0];
var distanceX = touchX - touch.pageX
var scrollLeft = $tabTitle.scrollLeft();
touchX = touch.pageX
$tabTitle.scrollLeft(scrollLeft += distanceX)
});
}
exports(MOD_NAME, new tabPage());
})

View File

@ -0,0 +1,40 @@
layui.define(['jquery', 'element'],
function (exports) {
var $ = layui.jquery;
var tools = new function () {
/**
* @since 防抖算法
*
* @param fn 要执行的方法
* @param time 防抖时间参数
*/
this.debounce = function (fn, time) {
var timer = null
return function () {
var arguments = arguments[0]
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(function () {
fn(arguments)
}, time)
}
}
// image 转 base64
this.imageToBase64 = function (img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
var ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
var dataURL = canvas.toDataURL("image/" + ext);
return dataURL;
}
};
exports('tools', tools);
})

View File

@ -7,7 +7,7 @@ window.rootPath = (function (src) {
layui.config({
base: rootPath + "module/",
version: "3.30.0"
version: "3.40.0"
}).extend({
admin: "admin", // 框架布局组件
common: "common", // 公共方法封装

View File

@ -160,7 +160,7 @@ pre{overflow-y: auto;
/* 头像 */
.fly-avatar{position: absolute; left: 15px; top: 10px;}
.fly-avatar img{display: block; width: 45px; height: 45px; margin: 0; border-radius: 100%;}
.fly-avatar img{display: block; width: 45px; height: 45px; margin: 0; border-radius: 100%; object-fit: cover;}
.fly-avatar i{position: absolute; left: 35px; top: 25px; }
/* 徽章 */
@ -191,8 +191,8 @@ pre{overflow-y: auto;
.fly-nav-user{position: absolute; top: 0; right: 0;}
.fly-nav-user .iconfont{position: relative;}
.fly-nav-avatar img{width: 36px; height: 36px; margin-left: 10px; border-radius: 100%;}
.fly-nav-avatar .icon-renzheng{font-size: 16px; top: 1px;}
.fly-nav-avatar img{width: 36px; height: 36px; margin-left: 10px; border-radius: 100%; object-fit: cover;}
.fly-nav-avatar .icon-renzheng{font-size: 16px; top: 1px;}
.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;}
@ -409,13 +409,6 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
.fly-signin-main span{padding-left: 10px;}
/* 榜单 */
.fly-rank{padding-bottom: 10px;}
.fly-rank dl{position: relative; overflow: hidden; margin-left: 10px; text-align: center; font-size: 0;}
.fly-rank dd{position: relative; width: 55px; height: 75px; margin: 10px 15px 5px 0; display:inline-block; *display:inline; *zoom:1; vertical-align:top; font-size:12px;}
.fly-rank dd a img{width: 55px; height: 55px; border-radius: 10px;}
.fly-rank dd a cite{ position:absolute; bottom: 20px; left: 0; width: 100%; height:20px; line-height:20px; text-align:center; background-color:rgba(0,0,0,.2); color:#fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
.fly-rank dd a:hover cite{display: block;}
.fly-rank dd a i{position:absolute; bottom: 0; left: 0; width: 100%; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-style: normal;}
/* 温馨通道 */
.fly-list-quick{border: 1px solid #f2f2f2; border-bottom: none; border-right: 0;}
@ -441,7 +434,6 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
.jie-row li i, .jie-row li em, .jie-row li cite{font-size:12px; color:#999; font-style: normal;}
.jie-row li .mine-edit{margin-left:15px; padding:0 6px; background-color: #8FCDA0; color:#fff; font-size:12px;}
.jie-row li em{position:absolute; right:0; top:0;}
.jie-row li .jie-user{}
.jie-row li .jie-title{max-width: 70%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
.jie-row li .jie-user img{position:relative; top: 16px; width: 35px; height: 35px;}
@ -450,7 +442,7 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
.detail .title>h1{float: left; font-size: 22px; line-height: 36px; padding-bottom:10px;}
.detail-box .title span {float: right; padding-right: 5px;}
.detail .fly-avatar{position: absolute; left: 15px; top: 10px;}
.detail .fly-avatar img{display: block; width: 45px; height: 45px; margin: 0; border-radius: 100%;}
.detail .fly-avatar img{display: block; width: 45px; height: 45px; margin: 0; border-radius: 100%; object-fit: cover;}
.detail .fly-avatar .icon-renzheng{display: inline-block; width: 15px; height: 15px; line-height: 15px; top: 25px; left: 32px; background-color: #FFB800; color: #fff; border-radius: 50%; font-size: 14px;}
.fly-detail-info{position: relative; margin: 10px 0 15px;}
@ -466,7 +458,6 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
.detail-about .icon-renzheng{display: inline-block; width: 15px; height: 15px; line-height: 15px; top: 25px; left: 35px; background-color: #FFB800; color: #fff; border-radius: 50%; font-size: 10px;}
.fly-detail-user{white-space: nowrap; overflow: hidden;}
.fly-detail-user a{padding-right: 10px; font-size: 14px;}
.fly-detail-user .guanzhu{position: absolute; right:10px; }
/*详情页管理工具条*/
.detail-assist{
@ -483,6 +474,32 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
border-radius:5px;
z-index: 100;
}
@media screen and (max-width: 750px) {
.detail-assist {
right:calc(50% - 500px);
}
}
@media screen and (min-width: 970px) {
.detail-assist {
right:calc(50% - 530px);
}
}
@media screen and (min-width: 1170px) {
.detail-assist {
right:calc(50% - 620px);
}
}
@media screen and (min-width: 1330px) {
.detail-assist {
right:calc(50% - 720px);
}
}
.detail-assist .fly-admin-box{text-align: center;}
.detail-assist span{height: 30px;width:30px; line-height:30px;}
.detail-assist .layui-btn{border-radius: 0;}
@ -498,13 +515,6 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
.detail-body p{margin-bottom: .6rem;font-size: .9375rem;line-height: 1.875;color: var(--color-secondary);word-wrap: break-word;}
.detail-body img{max-width: 100%; cursor: pointer;}
/*
.detail-body table{margin: 10px 0 15px;}
.detail-body table thead{background-color:#f2f2f2;}
.detail-body table th,
.detail-body table td{padding: 10px 20px; line-height: 22px; border: 1px solid #DFDFDF; font-size: 14px; font-weight: 400;}
*/
.detail-body .layui-btn{margin: 0 10px 10px 0;}
.detail-body .layui-btn a{color: #fff;}
.detail-body ul>li{margin-top: 0;}
@ -512,25 +522,15 @@ body .layui-edit-face .layui-layer-content{padding:0; background-color:#fff; co
/*详情页-问答*/
.user-questions{position:relative; margin: 5px 0 15px;}
.user-questions .user-avatar img{width: 25px; height: 25px; margin-top: 10; border-radius: 100%;}
/*
.detail-body-wenda{margin: 10px 0 5px; line-height: 26px; font-size: 16px; color: rgb(82, 80, 80); word-wrap: break-word;}
.detail-body-wenda p{margin-bottom:15px;}
.detail-body-wenda img{max-width: 100%; cursor: pointer;}
.detail-body-wenda .layui-btn{margin: 0 10px 10px 0;}
.detail-body-wenda .layui-btn a{color: #fff;}
.detail-body-wenda ul>li{margin-top: 0;}
.detail-body-wenda .layui-elem-quote{margin: 10px 0; font-size: 14px; line-height: 26px;}
*/
.user-questions .user-avatar img{width: 25px; height: 25px; border-radius: 100%;object-fit: cover;}
.layui-form-pane{position:relative; width:100%;}
.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%;}
.wenda-user .user-img img{width:150px;height:150px; border-radius: 100%;}
.wenda-user .user-img i{posation:absolute;right:20px;top:30px;width: 25px; height:25px; color:#fff; font-site:18px; border-radius: 100%;background-color:#FFB800;}
.wenda-user{height:200px; margin: 0,auto; text-align: center; padding-top:20px;}
.wenda-user .user-img{position:relative; width:100%;}
.wenda-user .user-img img{width:150px; height:150px; border-radius: 100%; object-fit: cover;}
.wenda-user .user-img i{position:absolute;right:20px;top:30px;width: 25px; height:25px; color:#fff; font-size:18px; border-radius: 100%;background-color:#FFB800;}
.wenda-user .questions{height:30px;margin:20px 20px;}
/*详情页-文章post*/
@ -600,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 (max-width: 768px) {
.fly-user-main>.fly-panel{margin: 0 0 10px 0;}
}
@media screen and (min-width: 768px) {
.fly-panel-user{height: calc(100vh - 280px)}
}
@ -617,7 +621,7 @@ body .fly-user-main{position: relative; min-height: 600px;}
/* 个人主页 */
.fly-home{position: relative; padding: 30px 0 30px; text-align: center;}
.fly-home img{width:120px; height:120px; border-radius:100%;}
.fly-home img{width:120px; height:120px; border-radius:100%; object-fit: cover;}
.fly-home h1{font-size:26px; line-height:30px; margin-top:10px;}
.fly-home h1 span{font-size:14px; color:#999;}
.fly-home h1 .icon-nan{color:#4EBBF9}
@ -787,7 +791,7 @@ p {
margin: 0;
white-space: normal;
word-break: break-all;
-webkit-user-select: none;
/* -webkit-user-select: none; */
}
code[class*="language-"], pre[class*="language-"] {

View File

@ -61,7 +61,7 @@ layui.define(['upload','layer'],function(exports){
img.src = path;
img.onload = function(){
var that = this, quality = 0.7;
var that = this, quality = 0.6;
var w = that.width, h = that.height, scale = w / h;
w = config.width || w;
h = config.height || (w / scale);

View File

@ -1,21 +1,16 @@
/**
TaoLer社区修改 www.aieok.com
@Name: Fly社区主入口
2021-5.21
2024-4.7
*/
layui.define(['layer', 'laytpl', 'form', 'element', 'upload', 'util', 'imgcom'], function(exports){
layui.define(['layer', 'form', 'util'], function(exports){
var $ = layui.jquery
,layer = layui.layer
,laytpl = layui.laytpl
,form = layui.form
,element = layui.element
,upload = layui.upload
,util = layui.util
,imgcom = layui.imgcom
,device = layui.device()
,DISABLED = 'layui-btn-disabled';
var uid = layui.cache.user.uid;
var login = $('.fly-nav-user').attr('userlogin');
@ -50,7 +45,7 @@ layui.define(['layer', 'laytpl', 'form', 'element', 'upload', 'util', 'imgcom'],
};
var fly = {
dir: layui.cache.host + 'static/res/mods/' //模块路径
dir: layui.cache.host + 'static/res/mods/' //模块路径
//Ajax
,json: function(url, data, success, options){
var that = this, type = typeof data === 'function';
@ -93,522 +88,13 @@ layui.define(['layer', 'laytpl', 'form', 'element', 'upload', 'util', 'imgcom'],
,form: {}
//简易编辑器
,layEditor: function(options){
var html = ['<div class="layui-unselect fly-edit">'
,'<span type="strong" title="加粗"><i class="layui-icon layedit-tool-b layedit-tool-active" title="加粗" lay-command="Bold" layedit-event="b" "=""></i></span>'
,'<span type="face" title="表情"><i class="iconfont icon-yxj-expression" style="top: 1px;"></i></span>'
,'<span type="picture" title="图片img[src]"><i class="iconfont icon-tupian"></i></span>'
,'<span type="video" title="视频"><i class="layui-icon layui-icon-video"></i></span>'
,'<span type="audio" title="音频"><i class="layui-icon layui-icon-headset"></i></span>'
,'<span type="href" title="超链接格式a(href)[text]"><i class="iconfont icon-lianjie"></i></span>'
,'<span type="quote" title="引用"><i class="iconfont icon-yinyong" style="top: 1px;"></i></span>'
,'<span type="code" title="插入代码" class="layui-hide-xs"><i class="iconfont icon-emwdaima" style="top: 1px;"></i></span>'
,'<span type="hr" title="水平线">hr</span>'
,'<span type="preview" title="预览"><i class="iconfont icon-yulan1"></i></span>'
,'</div>'].join('');
//简易编辑器 -移除 -2024/4/7
var closeTips = function(){
layer.close(mod.face.index);
};
var log = {}, mod = {
//加粗
strong: function(editor){
var str = window.getSelection().toString();
if(!str == ''){
//var strB = '<b>'+ str + '</b>';
layui.focusInsert(editor[0], '[strong]'+ str + '[/strong]');
//console.log(str);
// console.log(strB);
}
},
face: function(editor, self){ //插入表情
var str = '', ul, face = fly.faces;
for(var key in face){
str += '<li title="'+ key +'"><img src="'+ face[key] +'"></li>';
}
str = '<ul id="LAY-editface" class="layui-clear" style="margin: -10px 0 0 -1px;">'+ str +'</ul>';
layer.close(mod.face.index);
mod.face.index = layer.tips(str, self, {
tips: 3
,time: 0
,skin: 'layui-edit-face'
,tipsMore: true
});
$(document).off('click', closeTips).on('click', closeTips);
$('#LAY-editface li').on('click', function(){
var title = $(this).attr('title') + ' ';
layui.focusInsert(editor[0], 'face' + title);
editor.trigger('keyup');
});
}
,picture: function(editor){ //插入图片
//判断登陆
if(uid == -1){
layer.msg('请登录再发图', {icon: 6}, function(){
location.href = login;
})
return false;
}
layer.open({
type: 1
,id: 'fly-jie-upload'
,title: '插入图片'
,area: 'auto'
,shade: false
//,area: '465px'
,fixed: false
,offset: [
editor.offset().top - $(window).scrollTop() + 'px'
,editor.offset().left + 'px'
]
,skin: 'layui-layer-border'
,content: ['<ul class="layui-form layui-form-pane" style="margin: 20px;">'
,'<li class="layui-form-item">'
,'<label class="layui-form-label">URL</label>'
,'<div class="layui-input-inline">'
,'<input required name="image" placeholder="支持粘贴远程图片地址" value="" class="layui-input">'
,'</div>'
,'<button type="button" class="layui-btn layui-btn-primary" id="uploadImg"><i class="layui-icon">&#xe67c;</i>上传图片</button>'
,'</li>'
,'<li class="layui-form-item" style="text-align: center;">'
,'<button type="button" lay-submit lay-filter="uploadImages" class="layui-btn" id="img-button">确认</button>'
,'</li>'
,'</ul>'].join('')
,success: function(layero, index){
var image = layero.find('input[name="image"]');
//执行上传实例
upload.render({
elem: '#uploadImg'
,accept: 'images'
,acceptMime: 'image/*'
,exts: 'jpg|png|gif|bmp|jpeg'
,url: uploads
,data: {type:'image'}
,auto: false
//,bindAction: '#img-button' //指向一个按钮触发上传
//,field: 'image'
,size: 10240
,choose: function (obj) { //选择文件后的回调
imgcom.uploads(obj);
}
,done: function(res){
if(res.status == 0){
//console.log(res.url);
image.val(res.url);
} else {
layer.msg(res.msg, {icon: 5});
}
}
,error: function(){
layer.msg('系统错误,请联系管理员');
}
});
form.on('submit(uploadImages)', function(data){
var field = data.field;
if(!field.image) return image.focus();
layui.focusInsert(editor[0], 'img['+ field.image + '] ');
layer.close(index);
editor.trigger('keyup');
});
}
});
}
,href: function(editor){ //超链接
layer.prompt({
title: '请输入合法链接'
,shade: false
,fixed: false
,id: 'LAY_flyedit_href'
,offset: [
editor.offset().top - $(window).scrollTop() + 1 + 'px'
,editor.offset().left + 1 + 'px'
]
}, function(val, index, elem){
if(!/^http(s*):\/\/[\S]/.test(val)){
layer.tips('请务必 http 或 https 开头', elem, {tips:1})
return;
}
layui.focusInsert(editor[0], ' a('+ val +')['+ val + '] ');
layer.close(index);
editor.trigger('keyup');
});
}
,quote: function(editor){ //引用
layer.prompt({
title: '请输入引用内容'
,formType: 2
,maxlength: 10000
,shade: false
,id: 'LAY_flyedit_quote'
,offset: [
editor.offset().top - $(window).scrollTop() + 1 + 'px'
,editor.offset().left + 1 + 'px'
]
,area: ['300px', '100px']
}, function(val, index, elem){
layui.focusInsert(editor[0], '[quote]\n '+ val + '\n[/quote]\n');
layer.close(index);
editor.trigger('keyup');
});
}
,code: function(editor){ //插入代码
layer.prompt({
title: '请贴入代码'
,formType: 2
,maxlength: 10000
,shade: false
,id: 'LAY_flyedit_code'
,area: ['800px', '360px']
}, function(val, index, elem){
layui.focusInsert(editor[0], '[pre]\n'+ val + '\n[/pre]\n');
layer.close(index);
editor.trigger('keyup');
});
}
,hr: function(editor){ //插入水平分割线
layui.focusInsert(editor[0], '[hr]\n');
editor.trigger('keyup');
}
,video: function(editor){ //插入视频
//判断登陆
if(uid == -1){
layer.msg('请登录再发视频', {icon: 6}, function(){
location.href = login;
})
return false;
}
layer.open({
type: 1
,id: 'fly-jie-video-upload'
,title: '插入视频'
,area: 'auto'
,shade: false
//,area: '465px'
,fixed: false
,offset: [
editor.offset().top - $(window).scrollTop() + 'px'
,editor.offset().left + 'px'
]
,skin: 'layui-layer-border'
,content: ['<ul class="layui-form layui-form-pane" style="margin: 20px;">'
,'<li class="layui-form-item">'
,'<label class="layui-form-label">封面</label>'
,'<div class="layui-input-inline">'
,'<input type="text" required name="cover" placeholder="支持粘贴远程图片地址" value="" class="layui-input">'
,'</div>'
,'<button type="button" lay-type="image" class="layui-btn" id="video-img"><i class="layui-icon">&#xe67c;</i>上传封图</button>'
,'</li>'
,'<li class="layui-form-item">'
,'<label class="layui-form-label">URL</label>'
,'<div class="layui-input-inline">'
,'<input type="text" required name="video" placeholder="支持粘贴远程视频地址" value="" class="layui-input">'
,'</div>'
,'<button type="button" lay-type="video" class="layui-btn" id="layedit-video"><i class="layui-icon layui-icon-video"></i>上传视频</button>'
,'</li>'
,'<li class="layui-form-item" style="text-align: center;">'
,'<button type="button" lay-submit lay-filter="uploadImages" class="layui-btn">确认</button>'
,'</li>'
,'</ul>'].join('')
,success: function(layero, index){
var video = layero.find('input[name="video"]'), cover = layero.find('input[name="cover"]');
//上传视频
upload.render({
url: uploads
,data: {type:'video'}
,accept: 'video'
,acceptMime: 'video/mp4'
,exts: 'mp4'
,elem: '#layedit-video'
,before: function(obj){ //obj参数包含的信息跟 choose回调完全一致可参见上文。
layer.load(2); //上传loading
}
,done: function(res){
if(res.status == 0){
video.val(res.url);
} else {
layer.msg(res.msg, {icon: 5});
}
layer.closeAll('loading');
}
});
//上传图片
upload.render({
elem: '#video-img'
,accept: 'images'
,acceptMime: 'image/*'
,exts: 'jpg|png|gif|bmp|jpeg'
,url: uploads
,data: {type:'image'}
,auto: false
//,bindAction: '#img-button' //指向一个按钮触发上传
//,field: 'image'
,size: 10240
,choose: function (obj) { //选择文件后的回调
imgcom.uploads(obj);
}
,done: function(res){
if(res.status == 0){
cover.val(res.url);
} else {
layer.msg(res.msg, {icon: 5});
}
}
,error: function(){
layer.msg('系统错误,请联系管理员');
}
});
form.on('submit(uploadImages)', function(data){
var field = data.field;
if(!field.video) return video.focus();
layui.focusInsert(editor[0], 'video('+field.cover+')['+ field.video + '] ');
layer.close(index);
});
}
});
}
,audio: function(editor){ //插入音频
//判断登陆
if(uid == -1){
layer.msg('请登录再发布', {icon: 6}, function(){
location.href = login;
})
return false;
}
layer.open({
type: 1
,id: 'fly-jie-audio-upload'
,title: '插入音频'
,area: 'auto'
,shade: false
//,area: '465px'
,fixed: false
,offset: [
editor.offset().top - $(window).scrollTop() + 'px'
,editor.offset().left + 'px'
]
,skin: 'layui-layer-border'
,content: ['<ul class="layui-form layui-form-pane" style="margin: 20px;">'
,'<li class="layui-form-item">'
,'<label class="layui-form-label">URL</label>'
,'<div class="layui-input-inline">'
,'<input required name="audio" placeholder="支持直接粘贴远程音频地址" value="" class="layui-input">'
,'</div>'
,'<button required type="button" name="file" lay-type="audio" class="layui-btn upload-audio"><i class="layui-icon layui-icon-headset"></i>上传音频</button>'
,'</li>'
,'<li class="layui-form-item" style="text-align: center;">'
,'<button type="button" lay-submit lay-filter="uploadImages" class="layui-btn">确认</button>'
,'</li>'
,'</ul>'].join('')
,success: function(layero, index){
var loding,audio = layero.find('input[name="audio"]');
upload.render({
url: uploads
,data: {type:'audio'}
,elem: '#fly-jie-audio-upload .upload-audio'
,accept: 'audio'
,acceptMime: 'audio/*'
,exts: 'mp3|m4a'
,before: function(obj){
//loding = layer.msg('文件上传中,请稍等哦', { icon: 16 ,shade:0.3,time:0 });
layer.load(2); //上传loading
}
,done: function(res){
if(res.status == 0){
audio.val(res.url);
} else {
layer.msg(res.msg, {icon: 5});
}
layer.closeAll('loading');
}
});
form.on('submit(uploadImages)', function(data){
var field = data.field;
if(!field.audio) return audio.focus();
layui.focusInsert(editor[0], 'audio['+ field.audio + '] ');
layer.close(index);
});
}
});
}
,preview: function(editor, span){ //预览
var othis = $(span), getContent = function(){
var content = editor.val();
return /^\{html\}/.test(content) ? content.replace(/^\{html\}/, '') : fly.content(content)
}, isMobile = device.ios || device.android;
if(mod.preview.isOpen) return layer.close(mod.preview.index);
mod.preview.index = layer.open({
type: 1
,title: '预览'
,shade: false
,offset: 'r'
,id: 'LAY_flyedit_preview'
,area: [
isMobile ? '100%' : '775px'
,'100%'
]
,scrollbar: isMobile ? false : true
,anim: -1
,isOutAnim: false
,content: '<div class="detail-body layui-text" style="margin:20px;">'+ getContent() +'</div>'
,success: function(layero){
editor.on('keyup', function(val){
layero.find('.detail-body').html(getContent());
});
mod.preview.isOpen = true;
othis.addClass('layui-this');
}
,end: function(){
delete mod.preview.isOpen;
othis.removeClass('layui-this');
}
});
}
};
layui.use('face', function(face){
options = options || {};
fly.faces = face;
$(options.elem).each(function(index){
var that = this, othis = $(that), parent = othis.parent();
parent.prepend(html);
parent.find('.fly-edit span').on('click', function(event){
var type = $(this).attr('type');
mod[type].call(that, othis, this);
if(type === 'face'){
event.stopPropagation()
}
});
});
});
}
,escape: function(html){
return String(html||'').replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&amp;')
.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/'/g, '&#39;').replace(/"/g, '&quot;');
}
//内容转义
,content: function(content){
var util = fly
,item = fly.faces;
//支持的html标签
var html = function(end){
return new RegExp('\\n*\\|\\-'+ (end||'') +'(div|span|p|button|table|thead|th|tbody|tr|td|ul|li|ol|li|dl|dt|dd|h2|h3|h4|h5)([\\s\\S]*?)\\-\\|\\n*', 'g');
};
//XSS
content = util.escape(content||'')
//转义图片
.replace(/img\[([^\s]+?)\]/g, function(img){
return '<div><img src="' + img.replace(/(^img\[)|(\]$)/g, '') + '"></div>';
})
//转义@
.replace(/@(\S+)(\s+?|$)/g, '@<a href="javascript:;" class="fly-aite">$1</a>$2')
//转义表情
.replace(/face\[([^\s\[\]]+?)\]/g, function(face){
var alt = face.replace(/^face/g, '');
return '<img alt="'+ alt +'" title="'+ alt +'" src="' + item[alt] + '">';
})
//转义脚本
.replace(/a(\(javascript:)(.+)(;*\))/g, 'a(javascript:layer.msg(\'非法脚本\');)')
//转义链接
.replace(/a\([\s\S]+?\)\[[\s\S]*?\]/g, function(str){
var href = (str.match(/a\(([\s\S]+?)\)\[/)||[])[1];
var text = (str.match(/\)\[([\s\S]*?)\]/)||[])[1];
if(!href) return str;
var rel = /^(http(s)*:\/\/)\b(?!(\w+\.)*(sentsin.com|layui.com))\b/.test(href.replace(/\s/g, ''));
return '<a href="'+ href +'" style="color: red;" target="_blank"'+ (rel ? ' rel="nofollow"' : '') +'>'+ (text||href) +'</a>';
})
//转义横线
.replace(/\[hr\]\n*/g, '<hr>')
//转义表格
.replace(/\[table\]([\s\S]*)\[\/table\]\n*/g, function(str){
return str.replace(/\[(thead|th|tbody|tr|td)\]\n*/g, '<$1>')
.replace(/\n*\[\/(thead|th|tbody|tr|td)\]\n*/g, '</$1>')
.replace(/\[table\]\n*/g, '<table class="layui-table">')
.replace(/\n*\[\/table\]\n*/g, '</table>');
})
//转义 div/span
.replace(/\n*\[(div|span)([\s\S]*?)\]([\s\S]*?)\[\/(div|span)\]\n*/g, function(str){
return str.replace(/\[(div|span)([\s\S]*?)\]\n*/g, '<$1 $2>')
.replace(/\n*\[\/(div|span)\]\n*/g, '</$1>');
})
//转义列表
.replace(/\[ul\]([\s\S]*)\[\/ul\]\n*/g, function(str){
return str.replace(/\[li\]\n*/g, '<li>')
.replace(/\n*\[\/li\]\n*/g, '</li>')
.replace(/\[ul\]\n*/g, '<ul>')
.replace(/\n*\[\/ul\]\n*/g, '</ul>');
})
//转义代码
.replace(/\[pre\]([\s\S]*)\[\/pre\]\n*/g, function(str){
return str.replace(/\[pre\]\n*/g, '<pre>')
.replace(/\n*\[\/pre\]\n*/g, '</pre>');
})
//转义引用
.replace(/\[quote\]([\s\S]*)\[\/quote\]\n*/g, function(str){
return str.replace(/\[quote\]\n*/g, '<div class="layui-elem-quote">')
.replace(/\n*\[\/quote\]\n*/g, '</div>');
})
//转义加粗
.replace(/\[strong\]([\s\S]*)\[\/strong\]\n*/g, function(str){
return str.replace(/\[strong\]\n*/g,'<b>')
.replace(/\n*\[\/strong\]\n*/g, '</b>');
})
//转义换行
.replace(/\n/g, '<br>')
//转义视频
.replace(/video\(.*?\)\[([^\s]+?)\]/g, function(str){
var cover = (str.match(/video\(([\s\S]+?)\)\[/)||[])[1];
var video = (str.match(/\)\[([^\s]+?)\]/)||[])[1];
cover = cover ? cover : '/static/res/images/video_cover.jpg';
return '<video poster="'+ cover + '" controls crossorigin><source src="'+ video + '" type="video/mp4"></video>';
})
//转义音频
.replace(/audio\[([^\s]+?)\]/g, function(audio){
return '<audio controls><source src="'+ audio.replace(/(^audio\[)|(\]$)/g, '')+ '" type="audio/mp3"></audio>';
})
return content;
}
//新消息通知
,newmsg: function(){
var elemUser = $('.fly-nav-user');
var messageNums = elemUser.attr('msg-url'),
messageRead = elemUser.attr('readMsg-url');
var messageNums = elemUser.attr('msg-url');
var messageRead = elemUser.attr('readMsg-url');
if(uid != -1 && elemUser[0]){
fly.json(messageNums, {
_: new Date().getTime()
@ -699,26 +185,6 @@ layui.define(['layer', 'laytpl', 'form', 'element', 'upload', 'util', 'imgcom'],
//签到
//活跃榜
var tplReply = ['{{# layui.each(d.data, function(index, item){ }}'
,'<dd>'
,'<a href="{{item.uid}}">'
,'<img src="{{item.user.avatar}}">'
,'<cite>{{item.user.username}}</cite>'
,'<i>{{item["count"]}}' + replyNum + '</i>'
,'</a>'
,'</dd>'
,'{{# }); }}'].join('')
,elemReply = $('#LAY_replyRank');
var replyUrl = elemReply.attr('data-url');
if(elemReply[0]){
fly.json(replyUrl, {
limit: 20
}, function(res){
var html = laytpl(tplReply).render(res);
elemReply.find('dl').html(html);
});
};
//相册
if($(window).width() > 750){
@ -833,9 +299,7 @@ layui.define(['layer', 'laytpl', 'form', 'element', 'upload', 'util', 'imgcom'],
}
//加载编辑器
fly.layEditor({
elem: '.fly-editor'
});
//手机设备的简单适配 用户中心底部左侧栏导航
var treeMobile = $('.site-tree-mobile')

View File

@ -33,18 +33,53 @@ layui.define(['laypage', 'fly', 'element', 'flow', 'imgcom'], function(exports){
var post = table.render({
elem: '#art-post'
,url: artListUrl
,toolbar: '#toolbarPost'
,title: ''
,cols: [[
{type: 'numbers', fixed: 'left'}
{type: 'checkbox', fixed: 'left'},
{type: 'numbers', fixed: 'left', title: '序号'}
,{field: 'title', title: '标题',minWidth: 250 ,templet: '<div><a href="{{d.url}}" target="_blank">{{-d.title}}</a></div>'}
,{field: 'pv', title:'浏览 <i class="layui-icon layui-icon-tips layui-font-14" lay-event="pv-tips" title="该字段开启了编辑功能" style="margin-left: 5px;"></i>', fieldTitle: 'pv', hide: 0, width:100, expandedMode: 'tips', edit: 'text'}
,{field: 'status', title: '状态', width: 80}
,{field: 'ctime', title: '时间', width: 120}
,{field: 'datas', title: '数据', width: 120}
,{field: 'ctime', title: '发布时间', width: 160}
,{field: 'utime', title: '更新时间', width:160}
,{field: 'datas', title: '数据', width: 80}
,{title: '操作', width: 150, align: 'center', toolbar: '#artTool'}
]]
,text: '对不起,加载出现异常!'
,page: true
});
// 工具栏事件
table.on('toolbar(art-post)', function(obj){
var id = obj.config.id;
var checkStatus = table.checkStatus(id);
var othis = lay(this);
switch(obj.event){
case 'getCheckData':
var data = checkStatus.data;
// layer.alert(layui.util.escape(JSON.stringify(data)));
$.post(updateTime,{"data":data},function(res){
if(res.code === 0){
layer.msg(res.msg,{icon:6,time:2000});
table.reload('art-post')
} else {
layer.open({title:'刷新失败',content:res.msg,icon:5,adim:6})
}
}
);
break;
case 'getData':
var getData = table.getData(id);
console.log(getData);
layer.alert(layui.util.escape(JSON.stringify(getData)));
break;
case 'LAYTABLE_TIPS':
layer.alert('自定义工具栏图标按钮');
break;
};
return false
});
//收藏list
table.render({
@ -62,6 +97,44 @@ layui.define(['laypage', 'fly', 'element', 'flow', 'imgcom'], function(exports){
,text: '对不起,加载出现异常!'
,page: true
});
// 单元格编辑事件
table.on('edit(art-post)', function(obj){
var field = obj.field; // 得到字段
var value = obj.value; // 得到修改后的值
var data = obj.data; // 得到所在行所有键值
// 值的校验
if(field === 'email'){
if(!/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(obj.value)){
layer.tips('输入的邮箱格式不正确,请重新编辑', this, {tips: 1});
return obj.reedit(); // 重新编辑 -- v2.8.0 新增
}
}
// 编辑后续操作,如提交更新请求,以完成真实的数据更新
$.ajax({
type: "post",
url: pvEdit,
data: data,
dataType: 'json',
success: (res) => {
if(res.code === 0) {
layer.msg(res.msg, {icon: 1});
} else {
layer.msg(res.msg, {icon: 2});
return false;
}
}
})
// …
// 其他更新操作
var update = {};
update[field] = value;
obj.update(update);
});
//监听行工具事件
table.on('tool(art-post)', function(obj){

View File

@ -9,15 +9,13 @@ return array(
'9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
'35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'fe62ba7e10580d903cc46d808b5961a4' => $vendorDir . '/tightenco/collect/src/Collect/Support/helpers.php',
'caf31cc6ec7cf2241cb6f12c226c3846' => $vendorDir . '/tightenco/collect/src/Collect/Support/alias.php',
'6b998e7ad3182c0d21d23780badfa07b' => $vendorDir . '/yansongda/supports/src/Functions.php',
'b33e3d135e5d9e47d845c576147bda89' => $vendorDir . '/php-di/php-di/src/functions.php',
'223fa6f9b46fbe5d6b44c5ff847bfceb' => $vendorDir . '/taoser/think-addons/src/helper.php',

View File

@ -7,23 +7,20 @@ $baseDir = dirname($vendorDir);
return array(
'yzh52521\\EasyHttp\\' => array($vendorDir . '/yzh52521/easyhttp/src'),
'wamkj\\thinkphp\\' => array($vendorDir . '/wamkj/thinkphp6.0-databackup/src'),
'think\\view\\driver\\' => array($vendorDir . '/topthink/think-view/src'),
'think\\trace\\' => array($vendorDir . '/topthink/think-trace/src'),
'think\\migration\\' => array($vendorDir . '/topthink/think-migration/src'),
'think\\composer\\' => array($vendorDir . '/topthink/think-installer/src'),
'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'),
'think\\' => array($vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/framework/src/think'),
'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src'),
'taoser\\think\\' => array($vendorDir . '/taoser/think-auth/src'),
'taoser\\' => array($vendorDir . '/taoser/think-addons/src', $vendorDir . '/taoser/think-setarr/src'),
'phpspirit\\databackup\\' => array($vendorDir . '/lotofbadcode/phpspirit_databackup/src'),
'liliuwei\\social\\' => array($vendorDir . '/liliuwei/thinkphp-social/src'),
'app\\' => array($baseDir . '/app'),
'Yansongda\\Supports\\' => array($vendorDir . '/yansongda/supports/src'),
'Yansongda\\Pay\\' => array($vendorDir . '/yansongda/pay/src'),
'Workerman\\' => array($vendorDir . '/workerman/workerman'),
'Tightenco\\Collect\\' => array($vendorDir . '/tightenco/collect/src/Collect'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
@ -38,9 +35,10 @@ return array(
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
'PhpDocReader\\' => array($vendorDir . '/php-di/phpdoc-reader/src/PhpDocReader'),
'Phinx\\' => array($vendorDir . '/topthink/think-migration/phinx/src/Phinx'),
'Phinx\\' => array($vendorDir . '/topthink/think-migration/phinx'),
'PHPSocketIO\\' => array($vendorDir . '/workerman/phpsocket.io/src'),
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
'Overtrue\\EasySms\\' => array($vendorDir . '/overtrue/easy-sms/src'),
'League\\MimeTypeDetection\\' => array($vendorDir . '/league/mime-type-detection/src'),
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
'Laravel\\SerializableClosure\\' => array($vendorDir . '/laravel/serializable-closure/src'),
@ -49,6 +47,7 @@ return array(
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
'Endroid\\QrCode\\' => array($vendorDir . '/endroid/qr-code/src'),
'DI\\' => array($vendorDir . '/php-di/php-di/src'),
'DASPRiD\\Enum\\' => array($vendorDir . '/dasprid/enum/src'),

View File

@ -10,15 +10,13 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
'35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'fe62ba7e10580d903cc46d808b5961a4' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/helpers.php',
'caf31cc6ec7cf2241cb6f12c226c3846' => __DIR__ . '/..' . '/tightenco/collect/src/Collect/Support/alias.php',
'6b998e7ad3182c0d21d23780badfa07b' => __DIR__ . '/..' . '/yansongda/supports/src/Functions.php',
'b33e3d135e5d9e47d845c576147bda89' => __DIR__ . '/..' . '/php-di/php-di/src/functions.php',
'223fa6f9b46fbe5d6b44c5ff847bfceb' => __DIR__ . '/..' . '/taoser/think-addons/src/helper.php',
@ -32,10 +30,6 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
'yzh52521\\EasyHttp\\' => 18,
),
'w' =>
array (
'wamkj\\thinkphp\\' => 15,
),
't' =>
array (
'think\\view\\driver\\' => 18,
@ -48,10 +42,6 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
'taoser\\think\\' => 13,
'taoser\\' => 7,
),
'p' =>
array (
'phpspirit\\databackup\\' => 21,
),
'l' =>
array (
'liliuwei\\social\\' => 16,
@ -69,10 +59,6 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
'Workerman\\' => 10,
),
'T' =>
array (
'Tightenco\\Collect\\' => 18,
),
'S' =>
array (
'Symfony\\Polyfill\\Php80\\' => 23,
@ -99,6 +85,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
'PHPSocketIO\\' => 12,
'PHPMailer\\PHPMailer\\' => 20,
),
'O' =>
array (
'Overtrue\\EasySms\\' => 17,
),
'L' =>
array (
'League\\MimeTypeDetection\\' => 25,
@ -119,6 +109,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
'GuzzleHttp\\Promise\\' => 19,
'GuzzleHttp\\' => 11,
),
'F' =>
array (
'Firebase\\JWT\\' => 13,
),
'E' =>
array (
'Endroid\\QrCode\\' => 15,
@ -146,10 +140,6 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
0 => __DIR__ . '/..' . '/yzh52521/easyhttp/src',
),
'wamkj\\thinkphp\\' =>
array (
0 => __DIR__ . '/..' . '/wamkj/thinkphp6.0-databackup/src',
),
'think\\view\\driver\\' =>
array (
0 => __DIR__ . '/..' . '/topthink/think-view/src',
@ -176,10 +166,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
),
'think\\' =>
array (
0 => __DIR__ . '/..' . '/topthink/think-helper/src',
1 => __DIR__ . '/..' . '/topthink/think-orm/src',
2 => __DIR__ . '/..' . '/topthink/think-template/src',
3 => __DIR__ . '/..' . '/topthink/framework/src/think',
0 => __DIR__ . '/..' . '/topthink/framework/src/think',
1 => __DIR__ . '/..' . '/topthink/think-helper/src',
2 => __DIR__ . '/..' . '/topthink/think-orm/src',
3 => __DIR__ . '/..' . '/topthink/think-template/src',
),
'taoser\\think\\' =>
array (
@ -190,10 +180,6 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
0 => __DIR__ . '/..' . '/taoser/think-addons/src',
1 => __DIR__ . '/..' . '/taoser/think-setarr/src',
),
'phpspirit\\databackup\\' =>
array (
0 => __DIR__ . '/..' . '/lotofbadcode/phpspirit_databackup/src',
),
'liliuwei\\social\\' =>
array (
0 => __DIR__ . '/..' . '/liliuwei/thinkphp-social/src',
@ -214,10 +200,6 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
0 => __DIR__ . '/..' . '/workerman/workerman',
),
'Tightenco\\Collect\\' =>
array (
0 => __DIR__ . '/..' . '/tightenco/collect/src/Collect',
),
'Symfony\\Polyfill\\Php80\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
@ -276,7 +258,7 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
),
'Phinx\\' =>
array (
0 => __DIR__ . '/..' . '/topthink/think-migration/phinx/src/Phinx',
0 => __DIR__ . '/..' . '/topthink/think-migration/phinx',
),
'PHPSocketIO\\' =>
array (
@ -286,6 +268,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
0 => __DIR__ . '/..' . '/phpmailer/phpmailer/src',
),
'Overtrue\\EasySms\\' =>
array (
0 => __DIR__ . '/..' . '/overtrue/easy-sms/src',
),
'League\\MimeTypeDetection\\' =>
array (
0 => __DIR__ . '/..' . '/league/mime-type-detection/src',
@ -318,6 +304,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
array (
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
),
'Firebase\\JWT\\' =>
array (
0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
),
'Endroid\\QrCode\\' =>
array (
0 => __DIR__ . '/..' . '/endroid/qr-code/src',

View File

@ -269,24 +269,18 @@
},
{
"name": "dasprid/enum",
"version": "1.0.4",
"version_normalized": "1.0.4.0",
"version": "1.0.5",
"version_normalized": "1.0.5.0",
"source": {
"type": "git",
"url": "https://github.com/DASPRiD/Enum.git",
"reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f"
"reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
"reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/6faf451159fb8ba4126b925ed2d78acfce0dc016",
"reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016",
"shasum": ""
},
"require": {
"php": ">=7.1 <9.0"
@ -295,7 +289,7 @@
"phpunit/phpunit": "^7 | ^8 | ^9",
"squizlabs/php_codesniffer": "*"
},
"time": "2023-03-01T18:44:03+00:00",
"time": "2023-08-25T16:18:39+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -322,7 +316,7 @@
],
"support": {
"issues": "https://github.com/DASPRiD/Enum/issues",
"source": "https://github.com/DASPRiD/Enum/tree/1.0.4"
"source": "https://github.com/DASPRiD/Enum/tree/1.0.5"
},
"install-path": "../dasprid/enum"
},
@ -401,6 +395,72 @@
],
"install-path": "../endroid/qr-code"
},
{
"name": "firebase/php-jwt",
"version": "v6.10.0",
"version_normalized": "6.10.0.0",
"source": {
"type": "git",
"url": "https://github.com/firebase/php-jwt.git",
"reference": "a49db6f0a5033aef5143295342f1c95521b075ff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/a49db6f0a5033aef5143295342f1c95521b075ff",
"reference": "a49db6f0a5033aef5143295342f1c95521b075ff",
"shasum": ""
},
"require": {
"php": "^7.4||^8.0"
},
"require-dev": {
"guzzlehttp/guzzle": "^6.5||^7.4",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5",
"psr/cache": "^1.0||^2.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0"
},
"suggest": {
"ext-sodium": "Support EdDSA (Ed25519) signatures",
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
},
"time": "2023-12-01T16:26:39+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Firebase\\JWT\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Neuman Vong",
"email": "neuman+pear@twilio.com",
"role": "Developer"
},
{
"name": "Anant Narayanan",
"email": "anant@php.net",
"role": "Developer"
}
],
"description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
"homepage": "https://github.com/firebase/php-jwt",
"keywords": [
"jwt",
"php"
],
"support": {
"issues": "https://github.com/firebase/php-jwt/issues",
"source": "https://github.com/firebase/php-jwt/tree/v6.10.0"
},
"install-path": "../firebase/php-jwt"
},
{
"name": "guzzlehttp/guzzle",
"version": "7.0.0",
@ -693,24 +753,24 @@
},
{
"name": "jaeger/g-http",
"version": "V1.7.2",
"version_normalized": "1.7.2.0",
"version": "V1.7.3",
"version_normalized": "1.7.3.0",
"source": {
"type": "git",
"url": "https://github.com/jae-jae/GHttp.git",
"reference": "82585ddd5e2c6651e37ab1d8166efcdbb6b293d4"
"reference": "035fe0ff6e3e0390769647ce14694875bf02cf22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jae-jae/GHttp/zipball/82585ddd5e2c6651e37ab1d8166efcdbb6b293d4",
"reference": "82585ddd5e2c6651e37ab1d8166efcdbb6b293d4",
"url": "https://api.github.com/repos/jae-jae/GHttp/zipball/035fe0ff6e3e0390769647ce14694875bf02cf22",
"reference": "035fe0ff6e3e0390769647ce14694875bf02cf22",
"shasum": ""
},
"require": {
"cache/filesystem-adapter": "^1",
"guzzlehttp/guzzle": "^6.0 | ^7.0"
"guzzlehttp/guzzle": "^6.0 || ^7.0"
},
"time": "2021-08-08T04:59:44+00:00",
"time": "2024-03-24T14:55:49+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -731,7 +791,7 @@
"description": "Simple Http client base on GuzzleHttp",
"support": {
"issues": "https://github.com/jae-jae/GHttp/issues",
"source": "https://github.com/jae-jae/GHttp/tree/V1.7.2"
"source": "https://github.com/jae-jae/GHttp/tree/V1.7.3"
},
"install-path": "../jaeger/g-http"
},
@ -787,17 +847,17 @@
},
{
"name": "jaeger/querylist",
"version": "V4.2.8",
"version_normalized": "4.2.8.0",
"version": "V4.2.9",
"version_normalized": "4.2.9.0",
"source": {
"type": "git",
"url": "https://github.com/jae-jae/QueryList.git",
"reference": "39dc0ca9c668bec7a793e20472ccd7d26ef89ea4"
"reference": "7aae3aed38214d3d7096174faf49f6c41b2dd550"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jae-jae/QueryList/zipball/39dc0ca9c668bec7a793e20472ccd7d26ef89ea4",
"reference": "39dc0ca9c668bec7a793e20472ccd7d26ef89ea4",
"url": "https://api.github.com/repos/jae-jae/QueryList/zipball/7aae3aed38214d3d7096174faf49f6c41b2dd550",
"reference": "7aae3aed38214d3d7096174faf49f6c41b2dd550",
"shasum": ""
},
"require": {
@ -805,13 +865,12 @@
"jaeger/g-http": "^1.1",
"jaeger/phpquery-single": "^1",
"php": ">=7.1",
"tightenco/collect": ">5.0"
"symfony/var-dumper": ">3.4"
},
"require-dev": {
"phpunit/phpunit": "^8.5",
"symfony/var-dumper": "^3.3"
"phpunit/phpunit": "^8.5"
},
"time": "2021-07-05T06:07:58+00:00",
"time": "2024-04-12T06:29:50+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -838,7 +897,7 @@
],
"support": {
"issues": "https://github.com/jae-jae/QueryList/issues",
"source": "https://github.com/jae-jae/QueryList/tree/V4.2.8"
"source": "https://github.com/jae-jae/QueryList/tree/V4.2.9"
},
"funding": [
{
@ -850,17 +909,17 @@
},
{
"name": "laravel/serializable-closure",
"version": "v1.3.1",
"version_normalized": "1.3.1.0",
"version": "v1.3.3",
"version_normalized": "1.3.3.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/serializable-closure.git",
"reference": "e5a3057a5591e1cfe8183034b0203921abe2c902"
"reference": "3dbf8a8e914634c48d389c1234552666b3d43754"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/e5a3057a5591e1cfe8183034b0203921abe2c902",
"reference": "e5a3057a5591e1cfe8183034b0203921abe2c902",
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/3dbf8a8e914634c48d389c1234552666b3d43754",
"reference": "3dbf8a8e914634c48d389c1234552666b3d43754",
"shasum": ""
},
"require": {
@ -872,7 +931,7 @@
"phpstan/phpstan": "^1.8.2",
"symfony/var-dumper": "^5.4.11"
},
"time": "2023-07-14T13:56:28+00:00",
"time": "2023-11-08T14:08:06+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -1016,29 +1075,29 @@
},
{
"name": "league/mime-type-detection",
"version": "1.11.0",
"version_normalized": "1.11.0.0",
"version": "1.15.0",
"version_normalized": "1.15.0.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/mime-type-detection.git",
"reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd"
"reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
"reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd",
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301",
"reference": "ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"php": "^7.2 || ^8.0"
"php": "^7.4 || ^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.2",
"phpstan/phpstan": "^0.12.68",
"phpunit/phpunit": "^8.5.8 || ^9.3"
"phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0"
},
"time": "2022-04-17T13:12:02+00:00",
"time": "2024-01-28T23:22:08+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1059,7 +1118,7 @@
"description": "Mime-type detection for Flysystem",
"support": {
"issues": "https://github.com/thephpleague/mime-type-detection/issues",
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0"
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.15.0"
},
"funding": [
{
@ -1158,71 +1217,87 @@
"install-path": "../liliuwei/thinkphp-social"
},
{
"name": "lotofbadcode/phpspirit_databackup",
"version": "v1.2",
"version_normalized": "1.2.0.0",
"name": "overtrue/easy-sms",
"version": "2.6.0",
"version_normalized": "2.6.0.0",
"source": {
"type": "git",
"url": "https://github.com/lotofbadcode/phpspirit_databackup.git",
"reference": "77c2421f8461392c044cf8c29918f495c22a5612"
"url": "https://github.com/overtrue/easy-sms.git",
"reference": "bb88b244f0de8d1f74bc50c4c08414f4c5f30281"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/lotofbadcode/phpspirit_databackup/zipball/77c2421f8461392c044cf8c29918f495c22a5612",
"reference": "77c2421f8461392c044cf8c29918f495c22a5612",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
"url": "https://api.github.com/repos/overtrue/easy-sms/zipball/bb88b244f0de8d1f74bc50c4c08414f4c5f30281",
"reference": "bb88b244f0de8d1f74bc50c4c08414f4c5f30281",
"shasum": ""
},
"require": {
"php": ">=7.0"
"ext-json": "*",
"guzzlehttp/guzzle": "^6.2 || ^7.0",
"php": ">=5.6"
},
"time": "2023-05-12T12:02:05+00:00",
"require-dev": {
"brainmaestro/composer-git-hooks": "^2.8",
"jetbrains/phpstorm-attributes": "^1.0",
"mockery/mockery": "~1.3.3 || ^1.4.2",
"phpunit/phpunit": "^5.7 || ^7.5 || ^8.5.19 || ^9.5.8"
},
"time": "2024-03-08T06:36:45+00:00",
"type": "library",
"extra": {
"hooks": {
"pre-commit": [
"composer check-style",
"composer psalm",
"composer test"
],
"pre-push": [
"composer check-style"
]
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"phpspirit\\databackup\\": "src/"
"Overtrue\\EasySms\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
"MIT"
],
"authors": [
{
"name": "代码庸医",
"email": "3359964266@qq.com"
"name": "overtrue",
"email": "i@overtrue.me"
}
],
"description": "一个PHP数据库备份恢复的插件",
"keywords": [
"library",
"php"
],
"description": "The easiest way to send short message.",
"support": {
"issues": "https://github.com/lotofbadcode/phpspirit_databackup/issues",
"source": "https://github.com/lotofbadcode/phpspirit_databackup/tree/v1.2"
"issues": "https://github.com/overtrue/easy-sms/issues",
"source": "https://github.com/overtrue/easy-sms/tree/2.6.0"
},
"install-path": "../lotofbadcode/phpspirit_databackup"
"funding": [
{
"url": "https://github.com/overtrue",
"type": "github"
}
],
"install-path": "../overtrue/easy-sms"
},
{
"name": "php-di/invoker",
"version": "2.3.3",
"version_normalized": "2.3.3.0",
"version": "2.3.4",
"version_normalized": "2.3.4.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-DI/Invoker.git",
"reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786"
"reference": "33234b32dafa8eb69202f950a1fc92055ed76a86"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/cd6d9f267d1a3474bdddf1be1da079f01b942786",
"reference": "cd6d9f267d1a3474bdddf1be1da079f01b942786",
"url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/33234b32dafa8eb69202f950a1fc92055ed76a86",
"reference": "33234b32dafa8eb69202f950a1fc92055ed76a86",
"shasum": ""
},
"require": {
@ -1234,7 +1309,7 @@
"mnapoli/hard-mode": "~0.3.0",
"phpunit/phpunit": "^9.0"
},
"time": "2021-12-13T09:22:56+00:00",
"time": "2023-09-08T09:24:21+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1258,7 +1333,7 @@
],
"support": {
"issues": "https://github.com/PHP-DI/Invoker/issues",
"source": "https://github.com/PHP-DI/Invoker/tree/2.3.3"
"source": "https://github.com/PHP-DI/Invoker/tree/2.3.4"
},
"funding": [
{
@ -1394,17 +1469,17 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.8.0",
"version_normalized": "6.8.0.0",
"version": "v6.9.1",
"version_normalized": "6.9.1.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "df16b615e371d81fb79e506277faea67a1be18f1"
"reference": "039de174cd9c17a8389754d3b877a2ed22743e18"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/df16b615e371d81fb79e506277faea67a1be18f1",
"reference": "df16b615e371d81fb79e506277faea67a1be18f1",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/039de174cd9c17a8389754d3b877a2ed22743e18",
"reference": "039de174cd9c17a8389754d3b877a2ed22743e18",
"shasum": ""
},
"require": {
@ -1414,16 +1489,17 @@
"php": ">=5.5.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.2",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"doctrine/annotations": "^1.2.6 || ^1.13.3",
"php-parallel-lint/php-console-highlighter": "^1.0.0",
"php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.7.1",
"squizlabs/php_codesniffer": "^3.7.2",
"yoast/phpunit-polyfills": "^1.0.4"
},
"suggest": {
"decomplexity/SendOauth2": "Adapter for using XOAUTH2 authentication",
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
"ext-openssl": "Needed for secure SMTP sending and DKIM signing",
"greew/oauth2-azure-provider": "Needed for Microsoft Azure XOAUTH2 authentication",
@ -1433,7 +1509,7 @@
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication"
},
"time": "2023-03-06T14:43:22+00:00",
"time": "2023-11-25T22:23:28+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1465,7 +1541,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.8.0"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.1"
},
"funding": [
{
@ -1642,24 +1718,24 @@
},
{
"name": "psr/http-client",
"version": "1.0.2",
"version_normalized": "1.0.2.0",
"version": "1.0.3",
"version_normalized": "1.0.3.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31"
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0 || ^2.0"
},
"time": "2023-04-10T20:12:12+00:00",
"time": "2023-09-23T14:17:50+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -1691,7 +1767,7 @@
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client/tree/1.0.2"
"source": "https://github.com/php-fig/http-client"
},
"install-path": "../psr/http-client"
},
@ -1922,24 +1998,18 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"version": "v1.29.0",
"version_normalized": "1.29.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"shasum": ""
},
"require": {
"php": ">=7.1"
@ -1950,12 +2020,9 @@
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2022-11-03T14:55:06+00:00",
"time": "2024-01-29T20:11:03+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@ -1994,7 +2061,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0"
},
"funding": [
{
@ -2014,34 +2081,25 @@
},
{
"name": "symfony/polyfill-php72",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"version": "v1.29.0",
"version_normalized": "1.29.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97"
"reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97",
"reference": "869329b1e9894268a8a61dabb69153029b7a8c97",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25",
"reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"time": "2022-11-03T14:55:06+00:00",
"time": "2024-01-29T20:11:03+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@ -2079,7 +2137,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php72/tree/v1.29.0"
},
"funding": [
{
@ -2099,34 +2157,25 @@
},
{
"name": "symfony/polyfill-php80",
"version": "v1.27.0",
"version_normalized": "1.27.0.0",
"version": "v1.29.0",
"version_normalized": "1.29.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
"reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
"reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"time": "2022-11-03T14:55:06+00:00",
"time": "2024-01-29T20:11:03+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
@ -2171,7 +2220,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
"source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0"
},
"funding": [
{
@ -2289,17 +2338,17 @@
},
{
"name": "symfony/var-exporter",
"version": "v5.4.26",
"version_normalized": "5.4.26.0",
"version": "v5.4.35",
"version_normalized": "5.4.35.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-exporter.git",
"reference": "11401fe94f960249b3c63a488c63ba73091c1e4a"
"reference": "abb0a151b62d6b07e816487e20040464af96cae7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/11401fe94f960249b3c63a488c63ba73091c1e4a",
"reference": "11401fe94f960249b3c63a488c63ba73091c1e4a",
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/abb0a151b62d6b07e816487e20040464af96cae7",
"reference": "abb0a151b62d6b07e816487e20040464af96cae7",
"shasum": ""
},
"require": {
@ -2309,7 +2358,7 @@
"require-dev": {
"symfony/var-dumper": "^4.4.9|^5.0.9|^6.0"
},
"time": "2023-07-20T07:21:16+00:00",
"time": "2024-01-23T13:51:25+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -2345,7 +2394,7 @@
"serialize"
],
"support": {
"source": "https://github.com/symfony/var-exporter/tree/v5.4.26"
"source": "https://github.com/symfony/var-exporter/tree/v5.4.35"
},
"funding": [
{
@ -2528,69 +2577,6 @@
},
"install-path": "../taoser/think-setarr"
},
{
"name": "tightenco/collect",
"version": "v8.83.27",
"version_normalized": "8.83.27.0",
"source": {
"type": "git",
"url": "https://github.com/tighten/collect.git",
"reference": "07eed6cf7441c7a69c379fdcb118eec1a1fdd0e6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tighten/collect/zipball/07eed6cf7441c7a69c379fdcb118eec1a1fdd0e6",
"reference": "07eed6cf7441c7a69c379fdcb118eec1a1fdd0e6",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": "^7.3|^8.0",
"symfony/var-dumper": "^3.4 || ^4.0 || ^5.0 || ^6.0"
},
"require-dev": {
"mockery/mockery": "^1.0",
"nesbot/carbon": "^2.23.0",
"phpunit/phpunit": "^8.3"
},
"time": "2023-01-13T18:05:42+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"files": [
"src/Collect/Support/helpers.php",
"src/Collect/Support/alias.php"
],
"psr-4": {
"Tightenco\\Collect\\": "src/Collect"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylorotwell@gmail.com"
}
],
"description": "Collect - Illuminate Collections as a separate package.",
"keywords": [
"collection",
"laravel"
],
"support": {
"issues": "https://github.com/tighten/collect/issues",
"source": "https://github.com/tighten/collect/tree/v8.83.27"
},
"install-path": "../tightenco/collect"
},
{
"name": "topthink/framework",
"version": "v6.1.4",
@ -2832,30 +2818,33 @@
},
{
"name": "topthink/think-migration",
"version": "v3.0.6",
"version_normalized": "3.0.6.0",
"version": "v3.1.1",
"version_normalized": "3.1.1.0",
"source": {
"type": "git",
"url": "https://github.com/top-think/think-migration.git",
"reference": "82c4226cb14f973b9377c7fc6e89c525cbb8b030"
"reference": "22c44058e1454f3af1d346e7f6524fbe654de7fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/top-think/think-migration/zipball/82c4226cb14f973b9377c7fc6e89c525cbb8b030",
"reference": "82c4226cb14f973b9377c7fc6e89c525cbb8b030",
"url": "https://api.github.com/repos/top-think/think-migration/zipball/22c44058e1454f3af1d346e7f6524fbe654de7fb",
"reference": "22c44058e1454f3af1d346e7f6524fbe654de7fb",
"shasum": ""
},
"require": {
"php": ">=7.2",
"topthink/framework": "^6.0 || ^8.0",
"topthink/think-helper": "^3.0.3"
},
"require-dev": {
"fzaninotto/faker": "^1.8"
"composer/composer": "^2.5.8",
"fzaninotto/faker": "^1.8",
"robmorgan/phinx": "^0.13.4"
},
"suggest": {
"fzaninotto/faker": "Required to use the factory builder (^1.8)."
},
"time": "2023-07-01T11:01:52+00:00",
"time": "2023-09-14T05:51:31+00:00",
"type": "library",
"extra": {
"think": {
@ -2867,7 +2856,7 @@
"installation-source": "dist",
"autoload": {
"psr-4": {
"Phinx\\": "phinx/src/Phinx",
"Phinx\\": "phinx",
"think\\migration\\": "src"
}
},
@ -2883,7 +2872,7 @@
],
"support": {
"issues": "https://github.com/top-think/think-migration/issues",
"source": "https://github.com/top-think/think-migration/tree/v3.0.6"
"source": "https://github.com/top-think/think-migration/tree/v3.1.1"
},
"install-path": "../topthink/think-migration"
},
@ -3164,60 +3153,6 @@
"description": "thinkphp template driver",
"install-path": "../topthink/think-view"
},
{
"name": "wamkj/thinkphp6.0-databackup",
"version": "v1.0",
"version_normalized": "1.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/wamkj/thinkphp6.0-databackup.git",
"reference": "28a0e406d827132942723a3c9f69bb20c98e652f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/wamkj/thinkphp6.0-databackup/zipball/28a0e406d827132942723a3c9f69bb20c98e652f",
"reference": "28a0e406d827132942723a3c9f69bb20c98e652f",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.1.0",
"topthink/framework": "^6.0"
},
"time": "2020-02-15T13:04:16+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"wamkj\\thinkphp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "wamkj",
"email": "1149183529@qq.com"
}
],
"description": "thinkphp6.0的数据库自动备份扩展",
"keywords": [
"think-databackup",
"thinkphp"
],
"support": {
"issues": "https://github.com/wamkj/thinkphp6.0-databackup/issues",
"source": "https://github.com/wamkj/thinkphp6.0-databackup/tree/v1.0"
},
"install-path": "../wamkj/thinkphp6.0-databackup"
},
{
"name": "workerman/channel",
"version": "v1.2.0",
@ -3314,17 +3249,17 @@
},
{
"name": "workerman/workerman",
"version": "v4.1.13",
"version_normalized": "4.1.13.0",
"version": "v4.1.15",
"version_normalized": "4.1.15.0",
"source": {
"type": "git",
"url": "https://github.com/walkor/workerman.git",
"reference": "807780ff672775fcd08f89e573a2824e939021ce"
"reference": "afc8242fc769ab7cf22eb4ac22b97cb59d465e4e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/workerman/zipball/807780ff672775fcd08f89e573a2824e939021ce",
"reference": "807780ff672775fcd08f89e573a2824e939021ce",
"url": "https://api.github.com/repos/walkor/workerman/zipball/afc8242fc769ab7cf22eb4ac22b97cb59d465e4e",
"reference": "afc8242fc769ab7cf22eb4ac22b97cb59d465e4e",
"shasum": ""
},
"require": {
@ -3333,7 +3268,7 @@
"suggest": {
"ext-event": "For better performance. "
},
"time": "2023-07-31T05:57:25+00:00",
"time": "2024-02-19T02:10:39+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -3524,31 +3459,25 @@
},
{
"name": "yzh52521/easyhttp",
"version": "v1.0.7",
"version_normalized": "1.0.7.0",
"version": "v1.1.3",
"version_normalized": "1.1.3.0",
"source": {
"type": "git",
"url": "https://github.com/yzh52521/easyhttp.git",
"reference": "52cb9aba60a725bef77acd9c4c48ecc78931af9e"
"url": "https://github.com/yuanzhihai/easyhttp.git",
"reference": "02bcf47eaf723520fa3905d0e6f1852168fe646c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yzh52521/easyhttp/zipball/52cb9aba60a725bef77acd9c4c48ecc78931af9e",
"reference": "52cb9aba60a725bef77acd9c4c48ecc78931af9e",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
"url": "https://api.github.com/repos/yuanzhihai/easyhttp/zipball/02bcf47eaf723520fa3905d0e6f1852168fe646c",
"reference": "02bcf47eaf723520fa3905d0e6f1852168fe646c",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^6.0|^7.0",
"php": "^7.2.5|^8.0",
"php": ">=7.2.5",
"psr/log": "^1.0|^2.0|^3.0"
},
"time": "2023-02-16T03:04:02+00:00",
"time": "2023-11-14T05:49:02+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -3578,8 +3507,8 @@
"phphttp"
],
"support": {
"issues": "https://github.com/yzh52521/easyhttp/issues",
"source": "https://github.com/yzh52521/easyhttp/tree/v1.0.7"
"issues": "https://github.com/yuanzhihai/easyhttp/issues",
"source": "https://github.com/yuanzhihai/easyhttp/tree/v1.1.3"
},
"install-path": "../yzh52521/easyhttp"
}

View File

@ -3,7 +3,7 @@
'name' => 'taoser/taoler',
'pretty_version' => '2.3.10.x-dev',
'version' => '2.3.10.9999999-dev',
'reference' => '0c2f0154a81dd0a6268da627982d1bf41c0ef231',
'reference' => '158340e85a56ec3bd70563cef0bf1491468d7370',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -47,9 +47,9 @@
'dev_requirement' => false,
),
'dasprid/enum' => array(
'pretty_version' => '1.0.4',
'version' => '1.0.4.0',
'reference' => '8e6b6ea76eabbf19ea2bf5b67b98e1860474012f',
'pretty_version' => '1.0.5',
'version' => '1.0.5.0',
'reference' => '6faf451159fb8ba4126b925ed2d78acfce0dc016',
'type' => 'library',
'install_path' => __DIR__ . '/../dasprid/enum',
'aliases' => array(),
@ -64,6 +64,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
'firebase/php-jwt' => array(
'pretty_version' => 'v6.10.0',
'version' => '6.10.0.0',
'reference' => 'a49db6f0a5033aef5143295342f1c95521b075ff',
'type' => 'library',
'install_path' => __DIR__ . '/../firebase/php-jwt',
'aliases' => array(),
'dev_requirement' => false,
),
'guzzlehttp/guzzle' => array(
'pretty_version' => '7.0.0',
'version' => '7.0.0.0',
@ -92,9 +101,9 @@
'dev_requirement' => false,
),
'jaeger/g-http' => array(
'pretty_version' => 'V1.7.2',
'version' => '1.7.2.0',
'reference' => '82585ddd5e2c6651e37ab1d8166efcdbb6b293d4',
'pretty_version' => 'V1.7.3',
'version' => '1.7.3.0',
'reference' => '035fe0ff6e3e0390769647ce14694875bf02cf22',
'type' => 'library',
'install_path' => __DIR__ . '/../jaeger/g-http',
'aliases' => array(),
@ -110,18 +119,18 @@
'dev_requirement' => false,
),
'jaeger/querylist' => array(
'pretty_version' => 'V4.2.8',
'version' => '4.2.8.0',
'reference' => '39dc0ca9c668bec7a793e20472ccd7d26ef89ea4',
'pretty_version' => 'V4.2.9',
'version' => '4.2.9.0',
'reference' => '7aae3aed38214d3d7096174faf49f6c41b2dd550',
'type' => 'library',
'install_path' => __DIR__ . '/../jaeger/querylist',
'aliases' => array(),
'dev_requirement' => false,
),
'laravel/serializable-closure' => array(
'pretty_version' => 'v1.3.1',
'version' => '1.3.1.0',
'reference' => 'e5a3057a5591e1cfe8183034b0203921abe2c902',
'pretty_version' => 'v1.3.3',
'version' => '1.3.3.0',
'reference' => '3dbf8a8e914634c48d389c1234552666b3d43754',
'type' => 'library',
'install_path' => __DIR__ . '/../laravel/serializable-closure',
'aliases' => array(),
@ -137,9 +146,9 @@
'dev_requirement' => false,
),
'league/mime-type-detection' => array(
'pretty_version' => '1.11.0',
'version' => '1.11.0.0',
'reference' => 'ff6248ea87a9f116e78edd6002e39e5128a0d4dd',
'pretty_version' => '1.15.0',
'version' => '1.15.0.0',
'reference' => 'ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301',
'type' => 'library',
'install_path' => __DIR__ . '/../league/mime-type-detection',
'aliases' => array(),
@ -154,19 +163,19 @@
'aliases' => array(),
'dev_requirement' => false,
),
'lotofbadcode/phpspirit_databackup' => array(
'pretty_version' => 'v1.2',
'version' => '1.2.0.0',
'reference' => '77c2421f8461392c044cf8c29918f495c22a5612',
'overtrue/easy-sms' => array(
'pretty_version' => '2.6.0',
'version' => '2.6.0.0',
'reference' => 'bb88b244f0de8d1f74bc50c4c08414f4c5f30281',
'type' => 'library',
'install_path' => __DIR__ . '/../lotofbadcode/phpspirit_databackup',
'install_path' => __DIR__ . '/../overtrue/easy-sms',
'aliases' => array(),
'dev_requirement' => false,
),
'php-di/invoker' => array(
'pretty_version' => '2.3.3',
'version' => '2.3.3.0',
'reference' => 'cd6d9f267d1a3474bdddf1be1da079f01b942786',
'pretty_version' => '2.3.4',
'version' => '2.3.4.0',
'reference' => '33234b32dafa8eb69202f950a1fc92055ed76a86',
'type' => 'library',
'install_path' => __DIR__ . '/../php-di/invoker',
'aliases' => array(),
@ -191,9 +200,9 @@
'dev_requirement' => false,
),
'phpmailer/phpmailer' => array(
'pretty_version' => 'v6.8.0',
'version' => '6.8.0.0',
'reference' => 'df16b615e371d81fb79e506277faea67a1be18f1',
'pretty_version' => 'v6.9.1',
'version' => '6.9.1.0',
'reference' => '039de174cd9c17a8389754d3b877a2ed22743e18',
'type' => 'library',
'install_path' => __DIR__ . '/../phpmailer/phpmailer',
'aliases' => array(),
@ -239,9 +248,9 @@
'dev_requirement' => false,
),
'psr/http-client' => array(
'pretty_version' => '1.0.2',
'version' => '1.0.2.0',
'reference' => '0955afe48220520692d2d09f7ab7e0f93ffd6a31',
'pretty_version' => '1.0.3',
'version' => '1.0.3.0',
'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90',
'type' => 'library',
'install_path' => __DIR__ . '/../psr/http-client',
'aliases' => array(),
@ -302,27 +311,27 @@
'dev_requirement' => false,
),
'symfony/polyfill-mbstring' => array(
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '8ad114f6b39e2c98a8b0e3bd907732c207c2b534',
'pretty_version' => 'v1.29.0',
'version' => '1.29.0.0',
'reference' => '9773676c8a1bb1f8d4340a62efe641cf76eda7ec',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-php72' => array(
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '869329b1e9894268a8a61dabb69153029b7a8c97',
'pretty_version' => 'v1.29.0',
'version' => '1.29.0.0',
'reference' => '861391a8da9a04cbad2d232ddd9e4893220d6e25',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php72',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-php80' => array(
'pretty_version' => 'v1.27.0',
'version' => '1.27.0.0',
'reference' => '7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936',
'pretty_version' => 'v1.29.0',
'version' => '1.29.0.0',
'reference' => '87b68208d5c1188808dd7839ee1e6c8ec3b02f1b',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
'aliases' => array(),
@ -338,9 +347,9 @@
'dev_requirement' => false,
),
'symfony/var-exporter' => array(
'pretty_version' => 'v5.4.26',
'version' => '5.4.26.0',
'reference' => '11401fe94f960249b3c63a488c63ba73091c1e4a',
'pretty_version' => 'v5.4.35',
'version' => '5.4.35.0',
'reference' => 'abb0a151b62d6b07e816487e20040464af96cae7',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/var-exporter',
'aliases' => array(),
@ -349,7 +358,7 @@
'taoser/taoler' => array(
'pretty_version' => '2.3.10.x-dev',
'version' => '2.3.10.9999999-dev',
'reference' => '0c2f0154a81dd0a6268da627982d1bf41c0ef231',
'reference' => '158340e85a56ec3bd70563cef0bf1491468d7370',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@ -382,15 +391,6 @@
'aliases' => array(),
'dev_requirement' => false,
),
'tightenco/collect' => array(
'pretty_version' => 'v8.83.27',
'version' => '8.83.27.0',
'reference' => '07eed6cf7441c7a69c379fdcb118eec1a1fdd0e6',
'type' => 'library',
'install_path' => __DIR__ . '/../tightenco/collect',
'aliases' => array(),
'dev_requirement' => false,
),
'topthink/framework' => array(
'pretty_version' => 'v6.1.4',
'version' => '6.1.4.0',
@ -428,9 +428,9 @@
'dev_requirement' => false,
),
'topthink/think-migration' => array(
'pretty_version' => 'v3.0.6',
'version' => '3.0.6.0',
'reference' => '82c4226cb14f973b9377c7fc6e89c525cbb8b030',
'pretty_version' => 'v3.1.1',
'version' => '3.1.1.0',
'reference' => '22c44058e1454f3af1d346e7f6524fbe654de7fb',
'type' => 'library',
'install_path' => __DIR__ . '/../topthink/think-migration',
'aliases' => array(),
@ -481,15 +481,6 @@
'aliases' => array(),
'dev_requirement' => false,
),
'wamkj/thinkphp6.0-databackup' => array(
'pretty_version' => 'v1.0',
'version' => '1.0.0.0',
'reference' => '28a0e406d827132942723a3c9f69bb20c98e652f',
'type' => 'library',
'install_path' => __DIR__ . '/../wamkj/thinkphp6.0-databackup',
'aliases' => array(),
'dev_requirement' => false,
),
'workerman/channel' => array(
'pretty_version' => 'v1.2.0',
'version' => '1.2.0.0',
@ -509,9 +500,9 @@
'dev_requirement' => false,
),
'workerman/workerman' => array(
'pretty_version' => 'v4.1.13',
'version' => '4.1.13.0',
'reference' => '807780ff672775fcd08f89e573a2824e939021ce',
'pretty_version' => 'v4.1.15',
'version' => '4.1.15.0',
'reference' => 'afc8242fc769ab7cf22eb4ac22b97cb59d465e4e',
'type' => 'library',
'install_path' => __DIR__ . '/../workerman/workerman',
'aliases' => array(),
@ -536,9 +527,9 @@
'dev_requirement' => false,
),
'yzh52521/easyhttp' => array(
'pretty_version' => 'v1.0.7',
'version' => '1.0.7.0',
'reference' => '52cb9aba60a725bef77acd9c4c48ecc78931af9e',
'pretty_version' => 'v1.1.3',
'version' => '1.1.3.0',
'reference' => '02bcf47eaf723520fa3905d0e6f1852168fe646c',
'type' => 'library',
'install_path' => __DIR__ . '/../yzh52521/easyhttp',
'aliases' => array(),

170
vendor/firebase/php-jwt/CHANGELOG.md vendored Normal file
View File

@ -0,0 +1,170 @@
# Changelog
## [6.10.0](https://github.com/firebase/php-jwt/compare/v6.9.0...v6.10.0) (2023-11-28)
### Features
* allow typ header override ([#546](https://github.com/firebase/php-jwt/issues/546)) ([79cb30b](https://github.com/firebase/php-jwt/commit/79cb30b729a22931b2fbd6b53f20629a83031ba9))
## [6.9.0](https://github.com/firebase/php-jwt/compare/v6.8.1...v6.9.0) (2023-10-04)
### Features
* add payload to jwt exception ([#521](https://github.com/firebase/php-jwt/issues/521)) ([175edf9](https://github.com/firebase/php-jwt/commit/175edf958bb61922ec135b2333acf5622f2238a2))
## [6.8.1](https://github.com/firebase/php-jwt/compare/v6.8.0...v6.8.1) (2023-07-14)
### Bug Fixes
* accept float claims but round down to ignore them ([#492](https://github.com/firebase/php-jwt/issues/492)) ([3936842](https://github.com/firebase/php-jwt/commit/39368423beeaacb3002afa7dcb75baebf204fe7e))
* different BeforeValidException messages for nbf and iat ([#526](https://github.com/firebase/php-jwt/issues/526)) ([0a53cf2](https://github.com/firebase/php-jwt/commit/0a53cf2986e45c2bcbf1a269f313ebf56a154ee4))
## [6.8.0](https://github.com/firebase/php-jwt/compare/v6.7.0...v6.8.0) (2023-06-14)
### Features
* add support for P-384 curve ([#515](https://github.com/firebase/php-jwt/issues/515)) ([5de4323](https://github.com/firebase/php-jwt/commit/5de4323f4baf4d70bca8663bd87682a69c656c3d))
### Bug Fixes
* handle invalid http responses ([#508](https://github.com/firebase/php-jwt/issues/508)) ([91c39c7](https://github.com/firebase/php-jwt/commit/91c39c72b22fc3e1191e574089552c1f2041c718))
## [6.7.0](https://github.com/firebase/php-jwt/compare/v6.6.0...v6.7.0) (2023-06-14)
### Features
* add ed25519 support to JWK (public keys) ([#452](https://github.com/firebase/php-jwt/issues/452)) ([e53979a](https://github.com/firebase/php-jwt/commit/e53979abae927de916a75b9d239cfda8ce32be2a))
## [6.6.0](https://github.com/firebase/php-jwt/compare/v6.5.0...v6.6.0) (2023-06-13)
### Features
* allow get headers when decoding token ([#442](https://github.com/firebase/php-jwt/issues/442)) ([fb85f47](https://github.com/firebase/php-jwt/commit/fb85f47cfaeffdd94faf8defdf07164abcdad6c3))
### Bug Fixes
* only check iat if nbf is not used ([#493](https://github.com/firebase/php-jwt/issues/493)) ([398ccd2](https://github.com/firebase/php-jwt/commit/398ccd25ea12fa84b9e4f1085d5ff448c21ec797))
## [6.5.0](https://github.com/firebase/php-jwt/compare/v6.4.0...v6.5.0) (2023-05-12)
### Bug Fixes
* allow KID of '0' ([#505](https://github.com/firebase/php-jwt/issues/505)) ([9dc46a9](https://github.com/firebase/php-jwt/commit/9dc46a9c3e5801294249cfd2554c5363c9f9326a))
### Miscellaneous Chores
* drop support for PHP 7.3 ([#495](https://github.com/firebase/php-jwt/issues/495))
## [6.4.0](https://github.com/firebase/php-jwt/compare/v6.3.2...v6.4.0) (2023-02-08)
### Features
* add support for W3C ES256K ([#462](https://github.com/firebase/php-jwt/issues/462)) ([213924f](https://github.com/firebase/php-jwt/commit/213924f51936291fbbca99158b11bd4ae56c2c95))
* improve caching by only decoding jwks when necessary ([#486](https://github.com/firebase/php-jwt/issues/486)) ([78d3ed1](https://github.com/firebase/php-jwt/commit/78d3ed1073553f7d0bbffa6c2010009a0d483d5c))
## [6.3.2](https://github.com/firebase/php-jwt/compare/v6.3.1...v6.3.2) (2022-11-01)
### Bug Fixes
* check kid before using as array index ([bad1b04](https://github.com/firebase/php-jwt/commit/bad1b040d0c736bbf86814c6b5ae614f517cf7bd))
## [6.3.1](https://github.com/firebase/php-jwt/compare/v6.3.0...v6.3.1) (2022-11-01)
### Bug Fixes
* casing of GET for PSR compat ([#451](https://github.com/firebase/php-jwt/issues/451)) ([60b52b7](https://github.com/firebase/php-jwt/commit/60b52b71978790eafcf3b95cfbd83db0439e8d22))
* string interpolation format for php 8.2 ([#446](https://github.com/firebase/php-jwt/issues/446)) ([2e07d8a](https://github.com/firebase/php-jwt/commit/2e07d8a1524d12b69b110ad649f17461d068b8f2))
## 6.3.0 / 2022-07-15
- Added ES256 support to JWK parsing ([#399](https://github.com/firebase/php-jwt/pull/399))
- Fixed potential caching error in `CachedKeySet` by caching jwks as strings ([#435](https://github.com/firebase/php-jwt/pull/435))
## 6.2.0 / 2022-05-14
- Added `CachedKeySet` ([#397](https://github.com/firebase/php-jwt/pull/397))
- Added `$defaultAlg` parameter to `JWT::parseKey` and `JWT::parseKeySet` ([#426](https://github.com/firebase/php-jwt/pull/426)).
## 6.1.0 / 2022-03-23
- Drop support for PHP 5.3, 5.4, 5.5, 5.6, and 7.0
- Add parameter typing and return types where possible
## 6.0.0 / 2022-01-24
- **Backwards-Compatibility Breaking Changes**: See the [Release Notes](https://github.com/firebase/php-jwt/releases/tag/v6.0.0) for more information.
- New Key object to prevent key/algorithm type confusion (#365)
- Add JWK support (#273)
- Add ES256 support (#256)
- Add ES384 support (#324)
- Add Ed25519 support (#343)
## 5.0.0 / 2017-06-26
- Support RS384 and RS512.
See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)!
- Add an example for RS256 openssl.
See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)!
- Detect invalid Base64 encoding in signature.
See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)!
- Update `JWT::verify` to handle OpenSSL errors.
See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)!
- Add `array` type hinting to `decode` method
See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)!
- Add all JSON error types.
See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)!
- Bugfix 'kid' not in given key list.
See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)!
- Miscellaneous cleanup, documentation and test fixes.
See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115),
[#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and
[#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman),
[@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)!
## 4.0.0 / 2016-07-17
- Add support for late static binding. See [#88](https://github.com/firebase/php-jwt/pull/88) for details. Thanks to [@chappy84](https://github.com/chappy84)!
- Use static `$timestamp` instead of `time()` to improve unit testing. See [#93](https://github.com/firebase/php-jwt/pull/93) for details. Thanks to [@josephmcdermott](https://github.com/josephmcdermott)!
- Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)!
- Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)!
## 3.0.0 / 2015-07-22
- Minimum PHP version updated from `5.2.0` to `5.3.0`.
- Add `\Firebase\JWT` namespace. See
[#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to
[@Dashron](https://github.com/Dashron)!
- Require a non-empty key to decode and verify a JWT. See
[#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to
[@sjones608](https://github.com/sjones608)!
- Cleaner documentation blocks in the code. See
[#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to
[@johanderuijter](https://github.com/johanderuijter)!
## 2.2.0 / 2015-06-22
- Add support for adding custom, optional JWT headers to `JWT::encode()`. See
[#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to
[@mcocaro](https://github.com/mcocaro)!
## 2.1.0 / 2015-05-20
- Add support for adding a leeway to `JWT:decode()` that accounts for clock skew
between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)!
- Add support for passing an object implementing the `ArrayAccess` interface for
`$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)!
## 2.0.0 / 2015-04-01
- **Note**: It is strongly recommended that you update to > v2.0.0 to address
known security vulnerabilities in prior versions when both symmetric and
asymmetric keys are used together.
- Update signature for `JWT::decode(...)` to require an array of supported
algorithms to use when verifying token signatures.

View File

@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/firebase/php-jwt.png?branch=master)](https://travis-ci.org/firebase/php-jwt)
![Build Status](https://github.com/firebase/php-jwt/actions/workflows/tests.yml/badge.svg)
[![Latest Stable Version](https://poser.pugx.org/firebase/php-jwt/v/stable)](https://packagist.org/packages/firebase/php-jwt)
[![Total Downloads](https://poser.pugx.org/firebase/php-jwt/downloads)](https://packagist.org/packages/firebase/php-jwt)
[![License](https://poser.pugx.org/firebase/php-jwt/license)](https://packagist.org/packages/firebase/php-jwt)
@ -29,13 +29,13 @@ Example
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$key = "example_key";
$payload = array(
"iss" => "http://example.org",
"aud" => "http://example.com",
"iat" => 1356999524,
"nbf" => 1357000000
);
$key = 'example_key';
$payload = [
'iss' => 'http://example.org',
'aud' => 'http://example.com',
'iat' => 1356999524,
'nbf' => 1357000000
];
/**
* IMPORTANT:
@ -45,9 +45,12 @@ $payload = array(
*/
$jwt = JWT::encode($payload, $key, 'HS256');
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
print_r($decoded);
// Pass a stdClass in as the third parameter to get the decoded header values
$decoded = JWT::decode($jwt, new Key($key, 'HS256'), $headers = new stdClass());
print_r($headers);
/*
NOTE: This will now be an object instead of an associative array. To get
an associative array, you will need to cast it as such:
@ -65,6 +68,40 @@ $decoded_array = (array) $decoded;
JWT::$leeway = 60; // $leeway in seconds
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
```
Example encode/decode headers
-------
Decoding the JWT headers without verifying the JWT first is NOT recommended, and is not supported by
this library. This is because without verifying the JWT, the header values could have been tampered with.
Any value pulled from an unverified header should be treated as if it could be any string sent in from an
attacker. If this is something you still want to do in your application for whatever reason, it's possible to
decode the header values manually simply by calling `json_decode` and `base64_decode` on the JWT
header part:
```php
use Firebase\JWT\JWT;
$key = 'example_key';
$payload = [
'iss' => 'http://example.org',
'aud' => 'http://example.com',
'iat' => 1356999524,
'nbf' => 1357000000
];
$headers = [
'x-forwarded-for' => 'www.google.com'
];
// Encode headers in the JWT string
$jwt = JWT::encode($payload, $key, 'HS256', null, $headers);
// Decode headers from the JWT string WITHOUT validation
// **IMPORTANT**: This operation is vulnerable to attacks, as the JWT has not yet been verified.
// These headers could be any value sent by an attacker.
list($headersB64, $payloadB64, $sig) = explode('.', $jwt);
$decoded = json_decode(base64_decode($headersB64), true);
print_r($decoded);
```
Example with RS256 (openssl)
----------------------------
```php
@ -73,37 +110,52 @@ use Firebase\JWT\Key;
$privateKey = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC8kGa1pSjbSYZVebtTRBLxBz5H4i2p/llLCrEeQhta5kaQu/Rn
vuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t0tyazyZ8JXw+KgXTxldMPEL9
5+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4ehde/zUxo6UvS7UrBQIDAQAB
AoGAb/MXV46XxCFRxNuB8LyAtmLDgi/xRnTAlMHjSACddwkyKem8//8eZtw9fzxz
bWZ/1/doQOuHBGYZU8aDzzj59FZ78dyzNFoF91hbvZKkg+6wGyd/LrGVEB+Xre0J
Nil0GReM2AHDNZUYRv+HYJPIOrB0CRczLQsgFJ8K6aAD6F0CQQDzbpjYdx10qgK1
cP59UHiHjPZYC0loEsk7s+hUmT3QHerAQJMZWC11Qrn2N+ybwwNblDKv+s5qgMQ5
5tNoQ9IfAkEAxkyffU6ythpg/H0Ixe1I2rd0GbF05biIzO/i77Det3n4YsJVlDck
ZkcvY3SK2iRIL4c9yY6hlIhs+K9wXTtGWwJBAO9Dskl48mO7woPR9uD22jDpNSwe
k90OMepTjzSvlhjbfuPN1IdhqvSJTDychRwn1kIJ7LQZgQ8fVz9OCFZ/6qMCQGOb
qaGwHmUK6xzpUbbacnYrIM6nLSkXgOAwv7XXCojvY614ILTK3iXiLBOxPu5Eu13k
eUz9sHyD6vkgZzjtxXECQAkp4Xerf5TGfQXGXhxIX52yH+N2LtujCdkQZjXAsGdm
B2zNzvrlgRmgBrklMTrMYgm1NPcW+bRLGcwgW2PTvNM=
MIIEowIBAAKCAQEAuzWHNM5f+amCjQztc5QTfJfzCC5J4nuW+L/aOxZ4f8J3Frew
M2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJhzkPYLae7bTVro3hok0zDITR8F6S
JGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548tu4czCuqU8BGVOlnp6IqBHhAswNMM
78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vSopcT51koWOgiTf3C7nJUoMWZHZI5
HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTzTTqo1SCSH2pooJl9O8at6kkRYsrZ
WwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/BwQIDAQABAoIBAFtGaOqNKGwggn9k
6yzr6GhZ6Wt2rh1Xpq8XUz514UBhPxD7dFRLpbzCrLVpzY80LbmVGJ9+1pJozyWc
VKeCeUdNwbqkr240Oe7GTFmGjDoxU+5/HX/SJYPpC8JZ9oqgEA87iz+WQX9hVoP2
oF6EB4ckDvXmk8FMwVZW2l2/kd5mrEVbDaXKxhvUDf52iVD+sGIlTif7mBgR99/b
c3qiCnxCMmfYUnT2eh7Vv2LhCR/G9S6C3R4lA71rEyiU3KgsGfg0d82/XWXbegJW
h3QbWNtQLxTuIvLq5aAryV3PfaHlPgdgK0ft6ocU2de2FagFka3nfVEyC7IUsNTK
bq6nhAECgYEA7d/0DPOIaItl/8BWKyCuAHMss47j0wlGbBSHdJIiS55akMvnAG0M
39y22Qqfzh1at9kBFeYeFIIU82ZLF3xOcE3z6pJZ4Dyvx4BYdXH77odo9uVK9s1l
3T3BlMcqd1hvZLMS7dviyH79jZo4CXSHiKzc7pQ2YfK5eKxKqONeXuECgYEAyXlG
vonaus/YTb1IBei9HwaccnQ/1HRn6MvfDjb7JJDIBhNClGPt6xRlzBbSZ73c2QEC
6Fu9h36K/HZ2qcLd2bXiNyhIV7b6tVKk+0Psoj0dL9EbhsD1OsmE1nTPyAc9XZbb
OPYxy+dpBCUA8/1U9+uiFoCa7mIbWcSQ+39gHuECgYAz82pQfct30aH4JiBrkNqP
nJfRq05UY70uk5k1u0ikLTRoVS/hJu/d4E1Kv4hBMqYCavFSwAwnvHUo51lVCr/y
xQOVYlsgnwBg2MX4+GjmIkqpSVCC8D7j/73MaWb746OIYZervQ8dbKahi2HbpsiG
8AHcVSA/agxZr38qvWV54QKBgCD5TlDE8x18AuTGQ9FjxAAd7uD0kbXNz2vUYg9L
hFL5tyL3aAAtUrUUw4xhd9IuysRhW/53dU+FsG2dXdJu6CxHjlyEpUJl2iZu/j15
YnMzGWHIEX8+eWRDsw/+Ujtko/B7TinGcWPz3cYl4EAOiCeDUyXnqnO1btCEUU44
DJ1BAoGBAJuPD27ErTSVtId90+M4zFPNibFP50KprVdc8CR37BE7r8vuGgNYXmnI
RLnGP9p3pVgFCktORuYS2J/6t84I3+A17nEoB4xvhTLeAinAW/uTQOUmNicOP4Ek
2MsLL2kHgL8bLTmvXV4FX+PXphrDKg1XxzOYn0otuoqdAQrkK4og
-----END RSA PRIVATE KEY-----
EOD;
$publicKey = <<<EOD
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8kGa1pSjbSYZVebtTRBLxBz5H
4i2p/llLCrEeQhta5kaQu/RnvuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t
0tyazyZ8JXw+KgXTxldMPEL95+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4
ehde/zUxo6UvS7UrBQIDAQAB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzWHNM5f+amCjQztc5QT
fJfzCC5J4nuW+L/aOxZ4f8J3FrewM2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJ
hzkPYLae7bTVro3hok0zDITR8F6SJGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548t
u4czCuqU8BGVOlnp6IqBHhAswNMM78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vS
opcT51koWOgiTf3C7nJUoMWZHZI5HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTz
TTqo1SCSH2pooJl9O8at6kkRYsrZWwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/B
wQIDAQAB
-----END PUBLIC KEY-----
EOD;
$payload = array(
"iss" => "example.org",
"aud" => "example.com",
"iat" => 1356999524,
"nbf" => 1357000000
);
$payload = [
'iss' => 'example.org',
'aud' => 'example.com',
'iat' => 1356999524,
'nbf' => 1357000000
];
$jwt = JWT::encode($payload, $privateKey, 'RS256');
echo "Encode:\n" . print_r($jwt, true) . "\n";
@ -139,12 +191,12 @@ $privateKey = openssl_pkey_get_private(
$passphrase
);
$payload = array(
"iss" => "example.org",
"aud" => "example.com",
"iat" => 1356999524,
"nbf" => 1357000000
);
$payload = [
'iss' => 'example.org',
'aud' => 'example.com',
'iat' => 1356999524,
'nbf' => 1357000000
];
$jwt = JWT::encode($payload, $privateKey, 'RS256');
echo "Encode:\n" . print_r($jwt, true) . "\n";
@ -173,12 +225,12 @@ $privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));
$publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));
$payload = array(
"iss" => "example.org",
"aud" => "example.com",
"iat" => 1356999524,
"nbf" => 1357000000
);
$payload = [
'iss' => 'example.org',
'aud' => 'example.com',
'iat' => 1356999524,
'nbf' => 1357000000
];
$jwt = JWT::encode($payload, $privateKey, 'EdDSA');
echo "Encode:\n" . print_r($jwt, true) . "\n";
@ -187,6 +239,44 @@ $decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA'));
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
````
Example with multiple keys
--------------------------
```php
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
// Example RSA keys from previous example
// $privateKey1 = '...';
// $publicKey1 = '...';
// Example EdDSA keys from previous example
// $privateKey2 = '...';
// $publicKey2 = '...';
$payload = [
'iss' => 'example.org',
'aud' => 'example.com',
'iat' => 1356999524,
'nbf' => 1357000000
];
$jwt1 = JWT::encode($payload, $privateKey1, 'RS256', 'kid1');
$jwt2 = JWT::encode($payload, $privateKey2, 'EdDSA', 'kid2');
echo "Encode 1:\n" . print_r($jwt1, true) . "\n";
echo "Encode 2:\n" . print_r($jwt2, true) . "\n";
$keys = [
'kid1' => new Key($publicKey1, 'RS256'),
'kid2' => new Key($publicKey2, 'EdDSA'),
];
$decoded1 = JWT::decode($jwt1, $keys);
$decoded2 = JWT::decode($jwt2, $keys);
echo "Decode 1:\n" . print_r((array) $decoded1, true) . "\n";
echo "Decode 2:\n" . print_r((array) $decoded2, true) . "\n";
```
Using JWKs
----------
@ -198,72 +288,117 @@ use Firebase\JWT\JWT;
// this endpoint: https://www.gstatic.com/iap/verify/public_key-jwk
$jwks = ['keys' => []];
// JWK::parseKeySet($jwks) returns an associative array of **kid** to private
// key. Pass this as the second parameter to JWT::decode.
// NOTE: The deprecated $supportedAlgorithm must be supplied when parsing from JWK.
JWT::decode($payload, JWK::parseKeySet($jwks), $supportedAlgorithm);
// JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key
// objects. Pass this as the second parameter to JWT::decode.
JWT::decode($payload, JWK::parseKeySet($jwks));
```
Changelog
---------
Using Cached Key Sets
---------------------
#### 5.0.0 / 2017-06-26
- Support RS384 and RS512.
See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)!
- Add an example for RS256 openssl.
See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)!
- Detect invalid Base64 encoding in signature.
See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)!
- Update `JWT::verify` to handle OpenSSL errors.
See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)!
- Add `array` type hinting to `decode` method
See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)!
- Add all JSON error types.
See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)!
- Bugfix 'kid' not in given key list.
See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)!
- Miscellaneous cleanup, documentation and test fixes.
See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115),
[#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and
[#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman),
[@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)!
The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI.
This has the following advantages:
#### 4.0.0 / 2016-07-17
- Add support for late static binding. See [#88](https://github.com/firebase/php-jwt/pull/88) for details. Thanks to [@chappy84](https://github.com/chappy84)!
- Use static `$timestamp` instead of `time()` to improve unit testing. See [#93](https://github.com/firebase/php-jwt/pull/93) for details. Thanks to [@josephmcdermott](https://github.com/josephmcdermott)!
- Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)!
- Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)!
1. The results are cached for performance.
2. If an unrecognized key is requested, the cache is refreshed, to accomodate for key rotation.
3. If rate limiting is enabled, the JWKS URI will not make more than 10 requests a second.
#### 3.0.0 / 2015-07-22
- Minimum PHP version updated from `5.2.0` to `5.3.0`.
- Add `\Firebase\JWT` namespace. See
[#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to
[@Dashron](https://github.com/Dashron)!
- Require a non-empty key to decode and verify a JWT. See
[#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to
[@sjones608](https://github.com/sjones608)!
- Cleaner documentation blocks in the code. See
[#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to
[@johanderuijter](https://github.com/johanderuijter)!
```php
use Firebase\JWT\CachedKeySet;
use Firebase\JWT\JWT;
#### 2.2.0 / 2015-06-22
- Add support for adding custom, optional JWT headers to `JWT::encode()`. See
[#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to
[@mcocaro](https://github.com/mcocaro)!
// The URI for the JWKS you wish to cache the results from
$jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk';
#### 2.1.0 / 2015-05-20
- Add support for adding a leeway to `JWT:decode()` that accounts for clock skew
between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)!
- Add support for passing an object implementing the `ArrayAccess` interface for
`$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)!
// Create an HTTP client (can be any PSR-7 compatible HTTP client)
$httpClient = new GuzzleHttp\Client();
#### 2.0.0 / 2015-04-01
- **Note**: It is strongly recommended that you update to > v2.0.0 to address
known security vulnerabilities in prior versions when both symmetric and
asymmetric keys are used together.
- Update signature for `JWT::decode(...)` to require an array of supported
algorithms to use when verifying token signatures.
// Create an HTTP request factory (can be any PSR-17 compatible HTTP request factory)
$httpFactory = new GuzzleHttp\Psr\HttpFactory();
// Create a cache item pool (can be any PSR-6 compatible cache item pool)
$cacheItemPool = Phpfastcache\CacheManager::getInstance('files');
$keySet = new CachedKeySet(
$jwksUri,
$httpClient,
$httpFactory,
$cacheItemPool,
null, // $expiresAfter int seconds to set the JWKS to expire
true // $rateLimit true to enable rate limit of 10 RPS on lookup of invalid keys
);
$jwt = 'eyJhbGci...'; // Some JWT signed by a key from the $jwkUri above
$decoded = JWT::decode($jwt, $keySet);
```
Miscellaneous
-------------
#### Exception Handling
When a call to `JWT::decode` is invalid, it will throw one of the following exceptions:
```php
use Firebase\JWT\JWT;
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use Firebase\JWT\ExpiredException;
use DomainException;
use InvalidArgumentException;
use UnexpectedValueException;
try {
$decoded = JWT::decode($payload, $keys);
} catch (InvalidArgumentException $e) {
// provided key/key-array is empty or malformed.
} catch (DomainException $e) {
// provided algorithm is unsupported OR
// provided key is invalid OR
// unknown error thrown in openSSL or libsodium OR
// libsodium is required but not available.
} catch (SignatureInvalidException $e) {
// provided JWT signature verification failed.
} catch (BeforeValidException $e) {
// provided JWT is trying to be used before "nbf" claim OR
// provided JWT is trying to be used before "iat" claim.
} catch (ExpiredException $e) {
// provided JWT is trying to be used after "exp" claim.
} catch (UnexpectedValueException $e) {
// provided JWT is malformed OR
// provided JWT is missing an algorithm / using an unsupported algorithm OR
// provided JWT algorithm does not match provided key OR
// provided key ID in key/key-array is empty or invalid.
}
```
All exceptions in the `Firebase\JWT` namespace extend `UnexpectedValueException`, and can be simplified
like this:
```php
use Firebase\JWT\JWT;
use UnexpectedValueException;
try {
$decoded = JWT::decode($payload, $keys);
} catch (LogicException $e) {
// errors having to do with environmental setup or malformed JWT Keys
} catch (UnexpectedValueException $e) {
// errors having to do with JWT signature and claims
}
```
#### Casting to array
The return value of `JWT::decode` is the generic PHP object `stdClass`. If you'd like to handle with arrays
instead, you can do the following:
```php
// return type is stdClass
$decoded = JWT::decode($payload, $keys);
// cast to array
$decoded = json_decode(json_encode($decoded), true);
```
Tests
-----

View File

@ -20,10 +20,11 @@
],
"license": "BSD-3-Clause",
"require": {
"php": ">=5.3.0"
"php": "^7.4||^8.0"
},
"suggest": {
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present",
"ext-sodium": "Support EdDSA (Ed25519) signatures"
},
"autoload": {
"psr-4": {
@ -31,6 +32,11 @@
}
},
"require-dev": {
"phpunit/phpunit": ">=4.8 <=9"
"guzzlehttp/guzzle": "^6.5||^7.4",
"phpspec/prophecy-phpunit": "^2.0",
"phpunit/phpunit": "^9.5",
"psr/cache": "^1.0||^2.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0"
}
}

View File

@ -2,6 +2,17 @@
namespace Firebase\JWT;
class BeforeValidException extends \UnexpectedValueException
class BeforeValidException extends \UnexpectedValueException implements JWTExceptionWithPayloadInterface
{
private object $payload;
public function setPayload(object $payload): void
{
$this->payload = $payload;
}
public function getPayload(): object
{
return $this->payload;
}
}

View File

@ -0,0 +1,268 @@
<?php
namespace Firebase\JWT;
use ArrayAccess;
use InvalidArgumentException;
use LogicException;
use OutOfBoundsException;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use RuntimeException;
use UnexpectedValueException;
/**
* @implements ArrayAccess<string, Key>
*/
class CachedKeySet implements ArrayAccess
{
/**
* @var string
*/
private $jwksUri;
/**
* @var ClientInterface
*/
private $httpClient;
/**
* @var RequestFactoryInterface
*/
private $httpFactory;
/**
* @var CacheItemPoolInterface
*/
private $cache;
/**
* @var ?int
*/
private $expiresAfter;
/**
* @var ?CacheItemInterface
*/
private $cacheItem;
/**
* @var array<string, array<mixed>>
*/
private $keySet;
/**
* @var string
*/
private $cacheKey;
/**
* @var string
*/
private $cacheKeyPrefix = 'jwks';
/**
* @var int
*/
private $maxKeyLength = 64;
/**
* @var bool
*/
private $rateLimit;
/**
* @var string
*/
private $rateLimitCacheKey;
/**
* @var int
*/
private $maxCallsPerMinute = 10;
/**
* @var string|null
*/
private $defaultAlg;
public function __construct(
string $jwksUri,
ClientInterface $httpClient,
RequestFactoryInterface $httpFactory,
CacheItemPoolInterface $cache,
int $expiresAfter = null,
bool $rateLimit = false,
string $defaultAlg = null
) {
$this->jwksUri = $jwksUri;
$this->httpClient = $httpClient;
$this->httpFactory = $httpFactory;
$this->cache = $cache;
$this->expiresAfter = $expiresAfter;
$this->rateLimit = $rateLimit;
$this->defaultAlg = $defaultAlg;
$this->setCacheKeys();
}
/**
* @param string $keyId
* @return Key
*/
public function offsetGet($keyId): Key
{
if (!$this->keyIdExists($keyId)) {
throw new OutOfBoundsException('Key ID not found');
}
return JWK::parseKey($this->keySet[$keyId], $this->defaultAlg);
}
/**
* @param string $keyId
* @return bool
*/
public function offsetExists($keyId): bool
{
return $this->keyIdExists($keyId);
}
/**
* @param string $offset
* @param Key $value
*/
public function offsetSet($offset, $value): void
{
throw new LogicException('Method not implemented');
}
/**
* @param string $offset
*/
public function offsetUnset($offset): void
{
throw new LogicException('Method not implemented');
}
/**
* @return array<mixed>
*/
private function formatJwksForCache(string $jwks): array
{
$jwks = json_decode($jwks, true);
if (!isset($jwks['keys'])) {
throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
}
if (empty($jwks['keys'])) {
throw new InvalidArgumentException('JWK Set did not contain any keys');
}
$keys = [];
foreach ($jwks['keys'] as $k => $v) {
$kid = isset($v['kid']) ? $v['kid'] : $k;
$keys[(string) $kid] = $v;
}
return $keys;
}
private function keyIdExists(string $keyId): bool
{
if (null === $this->keySet) {
$item = $this->getCacheItem();
// Try to load keys from cache
if ($item->isHit()) {
// item found! retrieve it
$this->keySet = $item->get();
// If the cached item is a string, the JWKS response was cached (previous behavior).
// Parse this into expected format array<kid, jwk> instead.
if (\is_string($this->keySet)) {
$this->keySet = $this->formatJwksForCache($this->keySet);
}
}
}
if (!isset($this->keySet[$keyId])) {
if ($this->rateLimitExceeded()) {
return false;
}
$request = $this->httpFactory->createRequest('GET', $this->jwksUri);
$jwksResponse = $this->httpClient->sendRequest($request);
if ($jwksResponse->getStatusCode() !== 200) {
throw new UnexpectedValueException(
sprintf('HTTP Error: %d %s for URI "%s"',
$jwksResponse->getStatusCode(),
$jwksResponse->getReasonPhrase(),
$this->jwksUri,
),
$jwksResponse->getStatusCode()
);
}
$this->keySet = $this->formatJwksForCache((string) $jwksResponse->getBody());
if (!isset($this->keySet[$keyId])) {
return false;
}
$item = $this->getCacheItem();
$item->set($this->keySet);
if ($this->expiresAfter) {
$item->expiresAfter($this->expiresAfter);
}
$this->cache->save($item);
}
return true;
}
private function rateLimitExceeded(): bool
{
if (!$this->rateLimit) {
return false;
}
$cacheItem = $this->cache->getItem($this->rateLimitCacheKey);
if (!$cacheItem->isHit()) {
$cacheItem->expiresAfter(1); // # of calls are cached each minute
}
$callsPerMinute = (int) $cacheItem->get();
if (++$callsPerMinute > $this->maxCallsPerMinute) {
return true;
}
$cacheItem->set($callsPerMinute);
$this->cache->save($cacheItem);
return false;
}
private function getCacheItem(): CacheItemInterface
{
if (\is_null($this->cacheItem)) {
$this->cacheItem = $this->cache->getItem($this->cacheKey);
}
return $this->cacheItem;
}
private function setCacheKeys(): void
{
if (empty($this->jwksUri)) {
throw new RuntimeException('JWKS URI is empty');
}
// ensure we do not have illegal characters
$key = preg_replace('|[^a-zA-Z0-9_\.!]|', '', $this->jwksUri);
// add prefix
$key = $this->cacheKeyPrefix . $key;
// Hash keys if they exceed $maxKeyLength of 64
if (\strlen($key) > $this->maxKeyLength) {
$key = substr(hash('sha256', $key), 0, $this->maxKeyLength);
}
$this->cacheKey = $key;
if ($this->rateLimit) {
// add prefix
$rateLimitKey = $this->cacheKeyPrefix . 'ratelimit' . $key;
// Hash keys if they exceed $maxKeyLength of 64
if (\strlen($rateLimitKey) > $this->maxKeyLength) {
$rateLimitKey = substr(hash('sha256', $rateLimitKey), 0, $this->maxKeyLength);
}
$this->rateLimitCacheKey = $rateLimitKey;
}
}
}

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