1.新增插件。2.升级各依赖组件

This commit is contained in:
taoser 2021-11-02 15:40:58 +08:00
parent afada3a373
commit 184eb4ce30
80 changed files with 2815 additions and 900 deletions

View File

@ -2,13 +2,13 @@
> TaoLer是一个简单迅捷的轻论坛系统适用于个人或组织区域型信息交流发布平台。
* 官网https://www.aieok.com
* 官网https://www.aieok.com:8443
* 前台http://bbs.aieok.com:888
* 后台http://adm.aieok.com:888
* 账号test
* 密码test123
* 版本TaoLer 1.8.8
* 日期2021.10.12
* 版本TaoLer 1.8.10
* 日期2021.11.2
#### 项目地址
@ -97,6 +97,15 @@
#### 前后台独立域名的绑定
1. 手动修改`config/app.php`文件内的`'domain_bind'`对应的应用。
```html
// 域名绑定(自动多应用模式有效)
'domain_bind' => [
'bbs' => 'index', //bbs.xxx.com 访问的是Index应用
'adm' => 'admin', //adm.xxx.com 访问的是Admin应用
'api' => 'api' //api.xxx.com 访问的是Admin应用
'www.test.com' => 'test' //www.test.com 访问的是Test应用
],
```
2. 后面会针对动态的设置绑定域名功能开发...此处待完成

57
app/404.html Normal file
View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>404 - TaoLer社区</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="keywords" content="fly,layui,前端社区">
<meta name="description" content="Fly社区是模块化前端UI框架Layui的官网社区致力于为web开发提供强劲动力">
<link rel="stylesheet" href="/static/layui/css/layui.css">
<link rel="stylesheet" href="/static/res/css/global.css" charset="utf-8">
</head>
<body>
<include file="/view/taoler/index/public/header" />
<include file="./taoler/index/public/column" />
<div class="layui-container fly-marginTop">
<div class="fly-panel">
<div class="fly-none">
<h2><i class="iconfont icon-404"></i></h2>
<p>页面或者数据被<a href="/" target="_blank"> 纸飞机app </a>运到火星了,啥都看不到了…<a href="/">请返回首页</a></p>
</div>
</div>
</div>
<include file="./footer" />
<script src="/static/layui/jquery.min.js" charset="utf-8"></script>
<script src="/static/layui/layui.js" charset="utf-8"></script>
<script>
layui.cache.user = {
username: '{$user.name??'游客'}'
,uid: {$user.id ? 168*$user.id : -1}
,avatar: '{if condition="$user['user_img'] neq ''"}/uploads/{$user['user_img']}{else /}/static/res/images/avatar/00.jpg{/if}'
,experience: 83
,sex: '{if condition="$user['sex'] eq 0"}男{else/}女{/if}'
};
layui.config({
version: "3.0.0"
,base: '/static/res/mods/'
}).extend({
fly: 'index'
}).use('fly');
</script>
</body>
</html>

View File

@ -9,133 +9,131 @@ use think\facade\Config;
use app\admin\model\Addons as AddonsModel;
use taoler\com\Files;
use taoler\com\Api;
use app\common\lib\SetConf;
use think\App;
use app\common\lib\ZipFile;
class Addons extends AdminController
{
/**
* 显示资源列表
*
* @return \think\Response
* @return string
*/
public function index()
{
$type = input('type');
//$filter = input('filter') ? input('filter') : 'public-list';
//动态field
switch($type){
//已安装
case 'installed':
$col = [
['type' => 'numbers', 'fixed'=> 'left'],
['field' => 'name','title'=> '插件', 'width'=> 150],
['field'=> 'title','title'=> '标题', 'width'=> 100],
['field'=> 'version','title'=> '版本', 'width'=> 100],
['field' => 'author','title'=> '作者', 'width'=> 100],
['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'status','title'=> '状态', 'width'=> 100],
['field' => 'install','title'=> '安装', 'width'=> 100],
['field' => 'ctime','title'=> '到期时间', 'width'=> 150],
['title' => '操作', 'width'=> 220, 'align'=>'center', 'toolbar'=> '#addons-installed-tool']
];
break;
//在线
case 'onlineAddons':
$col = [
['type' => 'numbers', 'fixed'=> 'left'],
['field' => 'name','title'=> '插件', 'width'=> 150],
['field'=> 'title','title'=> '标题', 'width'=> 100],
['field'=> 'version','title'=> '版本', 'width'=> 100],
['field' => 'author','title'=> '作者', 'width'=> 100],
['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'price','title'=> '价格(元)'],
['field' => 'status','title'=> '状态', 'width'=> 100],
['field' => 'install','title'=> '安装', 'width'=> 100],
['field' => 'ctime','title'=> '时间', 'width'=> 150],
['title' => '操作', 'width'=> 150, 'align'=>'center', 'toolbar'=> '#addons-tool']
];
break;
default:
$col = [
['type' => 'numbers', 'fixed'=> 'left'],
['field' => 'name','title'=> '插件', 'width'=> 150],
['field'=> 'title','title'=> '标题', 'width'=> 100],
['field'=> 'version','title'=> '版本', 'width'=> 100],
['field' => 'author','title'=> '作者', 'width'=> 100],
['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'status','title'=> '状态', 'width'=> 100],
['field' => 'install','title'=> '安装', 'width'=> 100],
['field' => 'ctime','title'=> '到期时间', 'width'=> 150],
['title' => '操作', 'width'=> 220, 'align'=>'center', 'toolbar'=> '#addons-installed-tool']
];
}
View::assign('col',$col);
//$conf = new \addons\social\model\Conf;
//$arr = $conf->getConf();
//dump($arr);
//dump($arr[0]['value']['app_key']);
return View::fetch();
}
public function addonsList()
{
$type = input('type') ? input('type') : 'installed';
$type = input('type');
$res = [];
switch($type){
//已安装
case 'installed':
$addons = Files::getDirName('../addons/');
if($addons){
$res = ['code'=>0,'msg'=>'','count'=>5];
foreach($addons as $v){
$info_file = '../addons/'.$v.'/info.ini';
$info = parse_ini_file($info_file);
$res['data'][] = $info;
}
}
break;
//在线
case 'onlineAddons':
$url = $this->getSystem()['api_url'].'/v1/addons';
$addons = Api::urlPost($url,[]);
if( $addons->code !== -1){
$res['code'] = 0;
$res['msg'] = '';
$res['data'] = $addons->data;
}
break;
//已安装
default:
$addons = Files::getDirName('../addons/');
if($addons){
$res = ['code'=>0,'msg'=>'','count'=>5];
foreach($addons as $v){
$info_file = '../addons/'.$v.'/info.ini';
$info = parse_ini_file($info_file);
$res['data'][] = $info;
}
}
break;
}
return json($res);
switch($type){
//已安装
case 'installed':
$addons = Files::getDirName('../addons/');
if($addons){
$res = ['code'=>0,'msg'=>'','count'=>5];
foreach($addons as $v){
$info_file = '../addons/'.$v.'/info.ini';
$info = parse_ini_file($info_file);
$res['data'][] = $info;
}
$res['col'] = [
['type' => 'numbers'],
['field' => 'name','title'=> '插件', 'width'=> 150],
['field'=> 'title','title'=> '标题', 'width'=> 100],
['field'=> 'version','title'=> '版本', 'width'=> 100],
['field' => 'author','title'=> '作者', 'width'=> 100],
['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'status','title'=> '状态', 'width'=> 100],
['field' => 'install','title'=> '安装', 'width'=> 100],
['field' => 'ctime','title'=> '到期时间', 'width'=> 150],
['title' => '操作', 'width'=> 220, 'align'=>'center', 'toolbar'=> '#addons-installed-tool']
];
} else {
$res = ['code'=>-1,'msg'=>'没有安装任何插件'];
}
break;
//在线
case 'onlineAddons':
$url = $this->getSystem()['api_url'].'/v1/addons';
$addons = Api::urlPost($url,[]);
if( $addons->code !== -1){
$res['code'] = 0;
$res['msg'] = '';
$res['data'] = $addons->data;
$res['col'] = [
['type' => 'numbers'],
['field' => 'name','title'=> '插件', 'width'=> 150],
['field'=> 'title','title'=> '标题', 'width'=> 100],
['field'=> 'version','title'=> '版本', 'width'=> 100],
['field' => 'author','title'=> '作者', 'width'=> 100],
['field' => 'description','title'=> '简介', 'minWidth'=> 200],
['field' => 'price','title'=> '价格(元)'],
['field' => 'status','title'=> '状态', 'width'=> 100],
['field' => 'install','title'=> '安装', 'width'=> 100],
['field' => 'ctime','title'=> '时间', 'width'=> 150],
['title' => '操作', 'width'=> 150, 'align'=>'center', 'toolbar'=> '#addons-tool']
];
} else {
$res = ['code'=>-1,'msg'=>''];
}
break;
}
return json($res);
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function install()
public function add()
{
//
//添加版本
if(Request::isAjax()){
$data = Request::param();
$result = AddonsModel::create($data);
if($result){
$res = ['code'=>0,'msg'=>'添加成功'];
}else{
$res = ['code'=>-1,'msg'=>'添加失败'];
}
return json($res);
}
return View::fetch();
}
/**
* 编辑版本
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
$addons = AddonsModel::find($id);
if(Request::isAjax()){
$data = Request::only(['id','addons_name','addons_version','addons_auther','addons_resume','addons_price','addons_src']);
$result = $addons->where('id',$id)->save($data);
if($result){
$res = ['code'=>0,'msg'=>'编辑成功'];
}else{
$res = ['code'=>-1,'msg'=>'编辑失败'];
}
return json($res);
}
View::assign('addons',$addons);
return View::fetch();
}
/**
* 上传版本的zip资源
@ -146,23 +144,193 @@ class Addons extends AdminController
*/
public function uploadZip()
{
//
$id = Request::param();
$file = request()->file('file');
try {
validate(['file'=>'filesize:2048|fileExt:zip,rar,7z'])
->check(array($file));
$savename = \think\facade\Filesystem::disk('public')->putFile('addons',$file);
} catch (think\exception\ValidateException $e) {
echo $e->getMessage();
}
$upload = Config::get('filesystem.disks.public.url');
if($savename){
$name_path =str_replace('\\',"/",$upload.'/'.$savename);
$res = ['code'=>0,'msg'=>'插件上传成功','src'=>$name_path];
} else {
$res = ['code'=>-1,'msg'=>'上传错误'];
}
return json($res);
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
//安装插件
public function install()
{
$version = AddonsModel::find($id);
$res = $version->delete();
$data = Request::param();
$url = $this->getSystem()['api_url'].'/v1/getaddons';
$addons = Api::urlPost($url,['name'=>$data['name'],'version'=>$data['version']]);
if( $addons->code == -1) {
return json(['code'=>$addons->code,'msg'=>$addons->msg]);
}
//是否安装?
$addInstalledVersion = get_addons_info($data['name']);
if(!empty($addInstalledVersion)){
$verRes = version_compare($data['version'],$addInstalledVersion['version'],'>');
if(!$verRes){
return json(['code'=>-1,'msg'=>'不能降级,请选择正确版本']);
}
}
$file_url = $addons->addons_src;
//判断远程文件是否可用存在
$header = get_headers($file_url, true);
if(!isset($header[0]) && (strpos($header[0], '200') || strpos($header[0], '304'))){
return json(['code'=>-1,'msg'=>'获取远程文件失败']);
}
//把远程文件放入本地
//拼接路径
$addons_dir = Files::getDirPath('../runtime/addons/');
Files::mkdirs($addons_dir);
$package_file = $addons_dir . $data['name'] .'.zip'; //升级的压缩包文件
// halt($package_file);
$cpfile = copy($file_url,$package_file);
if(!$cpfile)
{
return json(['code'=>-1,'msg'=>'下载升级文件失败']);
}
$uzip = new ZipFile();
$zipDir = strstr($package_file, '.zip',true); //返回文件名后缀前的字符串
$zipPath = Files::getDirPath($zipDir); //转换为带/的路径 压缩文件解压到的路径
$unzip_res = $uzip->unzip($package_file,$zipPath,true);
if(!$unzip_res)
{
return json(['code'=>-1,'msg'=>'解压失败']);
}
//升级插件
if(is_dir($zipPath))
{
//升级前的写入文件权限检查
$allUpdateFiles = Files::getAllFile($zipPath);
if (empty($allUpdateFiles)) return json(['code' => -1, 'msg' => '无可更新文件。']);
$checkString = '';
foreach ($allUpdateFiles as $updateFile) {
$coverFile = ltrim(str_replace($zipPath, '', $updateFile), DIRECTORY_SEPARATOR);
$dirPath = dirname('../'.$coverFile);
if (file_exists('../'.$coverFile)) {
if (!is_writable('../'.$coverFile)) $checkString .= $coverFile . '&nbsp;[<span class="text-red">' . '无写入权限' . '</span>]<br>';
} else {
if (!is_dir($dirPath)) @mkdir($dirPath, 0777, true);
if (!is_writable($dirPath)) $checkString .= $dirPath . '&nbsp;[<span class="text-red">' . '无写入权限' . '</span>]<br>';
}
}
if (!empty($checkString)) return json(['code' => -1, 'msg' => $checkString]);
$addonsPath = '../';
$cpRes = Files::copyDirs($zipPath,$addonsPath);
$cpData = $cpRes->getData();
//更新失败
if($cpData['code'] == -1)
{
return json(['code'=>-1,'msg'=>$cpData['msg']]);
}
//清除
Files::delDirAndFile('../runtime/addons/');
}
return json(['code'=>0,'msg'=>'插件安装成功!']);
}
/**
* 卸载插件
*/
public function delete()
{
$name = input('name');
$addonsPath = '../addons/'.$name;
$staticPath = 'addons/'.$name;
if (is_dir($staticPath)) {
Files::delDir($staticPath);
}
$res = Files::delDir($addonsPath);
if($res){
return json(['code'=>0,'msg'=>'删除成功']);
return json(['code'=>0,'msg'=>'卸载成功']);
} else {
return json(['code'=>-1,'msg'=>'删除失败']);
return json(['code'=>-1,'msg'=>'卸载失败']);
}
}
//启用插件
public function start()
{
$name = input('name');
$arr = ['status' => 1];
//$res = get_addons_info($name);
//$res = get_addons_instance($name);
$res = set_addons_info($name,$arr);
return json(['code'=>0,'msg'=>$name.'插件已启用']);
}
//暂停插件
public function shutDown()
{
$name = input('name');
$arr = ['status' => 0];
$res = set_addons_info($name,$arr);
var_dump($res);
return json(['code'=>-1,'msg'=>$name.'插件已禁用']);
}
//配置插件
public function config($name)
{
$name = input('name');
//var_dump($name);
$config = get_addons_config($name);
if(empty($config)) return json(['code'=>-1,'msg'=>'无配置项!']);
if(Request::isAjax()){
$params = Request::param('params/a');
if ($params) {
foreach ($config as $k => &$v) {
if (isset($params[$k])) {
if ($v['type'] == 'array') {
$arr = [];
$params[$k] = is_array($params[$k]) ? $params[$k] :[];
foreach ($params[$k]['key'] as $kk=>$vv){
$arr[$vv] = $params[$k]['value'][$kk];
}
$params[$k] = $arr;
$value = $params[$k];
$v['content'] = $value;
$v['value'] = $value;
} else {
$value = $params[$k];
}
$v['value'] = $value;
}
}
unset($v);
set_addons_config($name,$config);
}
return json(['code'=>0,'msg'=>'配置成功!']);
}
//模板引擎初始化
$view = ['formData'=>$config,'title'=>'title'];
View::assign($view);
return View::fetch();
}
}

View File

@ -78,6 +78,8 @@ class Admin extends Model
//用户名密码正确返回1
return 1;
}
} else {
return "用户名或密码错误!";
}
}
}

View File

@ -0,0 +1,93 @@
{extend name="public/base" /}
{block name="body"}
<div class="layui-form" lay-filter="layuiadmin-form-addons" id="layuiadmin-form-addons" style="padding: 20px 40px 0 0;">
<div class="layui-form-item">
<label class="layui-form-label">名称</label>
<div class="layui-input-inline">
<input type="text" name="addons_name" lay-verify="required" placeholder="请输入名称" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">版本</label>
<div class="layui-input-inline">
<input type="text" name="addons_version" lay-verify="required" placeholder="请输入版本" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">作者</label>
<div class="layui-input-inline">
<input type="text" name="addons_auther" lay-verify="required" placeholder="请输入作者名" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">简介</label>
<div class="layui-input-inline">
<textarea name="addons_resume" placeholder="请输入简介" lay-verify="required" class="layui-textarea"></textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">价格</label>
<div class="layui-input-inline">
<input type="text" name="addons_price" lay-verify="required" placeholder="请输入价格" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">压缩包</label>
<div class="layui-input-inline">
<input type="text" name="addons_src" lay-verify="required" placeholder="请上传zip包" autocomplete="off" class="layui-input" >
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label"></label>
<div class="layui-input-inline">
<button style="float: left;" type="button" class="layui-btn " id="layuiadmin-upload-addons">上传插件</button>
</div>
</div>
<div class="layui-form-item layui-hide">
<input type="button" lay-submit lay-filter="LAY-addons-submit" id="LAY-addons-submit" value="确认">
</div>
</div>
{/block}
{block name="js"}
<script>
layui.config({
base: '/static/admin/' //静态资源所在路径
}).extend({
index: 'lib/index' //主入口模块
}).use(['index', 'form', 'upload'], function(){
var $ = layui.$
,form = layui.form
,upload = layui.upload ;
upload.render({
elem: '#layuiadmin-upload-addons'
,url: 'uploadZip'
,accept: 'file'
,field: 'file'
,method: 'get'
,exts: 'zip|rar|7z'
,done: function(res){
//console.log(res)
$(this.item).prev("div").children("input").val(res.src)
if(res.code == 0){
layer.msg(res.msg,{
icon:6,
tiye:2000
});
} else {
layer.open({
title:"上传失败",
content:res.msg,
icon:5,
anim:6
});
}
}
});
})
</script>
{/block}

View File

@ -0,0 +1,51 @@
{extend name="public/base" /}
{block name="body"}
<div class="layui-form" lay-filter="layuiadmin-form-addons" id="layuiadmin-form-addons" style="padding: 20px 30px 0 0;">
{foreach name="formData" item="vo" key="k"}
{php}$name = "params[".$k."]";{/php}
{switch name="$vo.type"}
{case value="text"}
{:form_input($name,'text',['label'=>$vo.title,'tip'=>$vo.tip],$vo.value)}
{/case}
{case value="textarea"}
{:form_textarea($name,['label'=>$vo.title,'tip'=>$vo.tip],$vo.value)}
{/case}
{case value="password"}
{:form_input($name,'password',['label'=>$vo.title,'tip'=>$vo.tip],$vo.value)}
{/case}
{case value="radio"}
{:form_radio($name,$vo.content,['label'=>$vo.title,'tip'=>$vo.tip],$vo.value)}
{/case}
{case value="select"}
{:form_select($name,$vo.content,['label'=>$vo.title,'verify'=>$vo.rule,'tip'=>$vo.tip,'search'=>1] ,[],$vo.value)}
{/case}
{case value="image"}
{:form_upload($name,$vo.value,['label'=>$vo.title,'tip'=>$vo.tip,'verify'=>$vo.rule,'type'=>'radio','num'=>'1','mime'=>'image'])}
{/case}
{case value="images"}
{:form_upload($name,$vo.value,['label'=>$vo.title,'tip'=>$vo.tip,'verify'=>$vo.rule,'type'=>'checkbox','num'=>$vo.num,'mime'=>'image'])}
{/case}
{case value="file"}
{:form_upload($name,$vo.value,['label'=>$vo.title,'tip'=>$vo.tip,'verify'=>$vo.rule,'type'=>'radio','num'=>$vo.num,'mime'=>'*'])}
{/case}
{case value="files"}
{:form_upload($name,$vo.value,['label'=>$vo.title,'tip'=>$vo.tip,'verify'=>$vo.rule,'type'=>'checkbox','num'=>$vo.num,'mime'=>'*'])}
{/case}
{case value="editor"}
{:form_editor($name,$name,2,['label'=>$vo.title,'tip'=>$vo.tip,'verify'=>$vo.rule])}
{/case}
{case value="array"}
{:form_arrays($name,['label'=>$vo.title,'tip'=>$vo.tip,'verify'=>$vo.rule],$vo.value?$vo.value:$vo.content)}
{/case}
{/switch}
{/foreach}
<div class="layui-form-item layui-hide">
<input type="hidden" name="name" value="{:input('name')}">
<input type="button" lay-submit lay-filter="LAY-addons-config-submit" id="LAY-addons-config-submit" value="确认">
</div>
</div>
{/block}
{block name="js"}
{/block}

View File

@ -0,0 +1,93 @@
{extend name="public/base" /}
{block name="body"}
<div class="layui-form" lay-filter="layuiadmin-form-addons" id="layuiadmin-form-addons" style="padding: 20px 30px 0 0;">
<div class="layui-form-item layui-hide">
<input type="text" name="id" value="{$addons.id}">
</div>
<div class="layui-form-item">
<label class="layui-form-label">名称</label>
<div class="layui-input-inline">
<input type="text" name="addons_name" lay-verify="required" placeholder="请输入名称" autocomplete="off" class="layui-input" value="{$addons.addons_name}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">版本</label>
<div class="layui-input-inline">
<input type="text" name="addons_version" lay-verify="required" placeholder="请输入版本" autocomplete="off" class="layui-input" value="{$addons.addons_version}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">作者</label>
<div class="layui-input-inline">
<input type="text" name="addons_auther" lay-verify="required" placeholder="请输入作者名" autocomplete="off" class="layui-input" value="{$addons.addons_auther}">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">简介</label>
<div class="layui-input-inline">
<textarea name="addons_resume" placeholder="请输入简介" lay-verify="required" class="layui-textarea">{$addons.addons_resume}</textarea>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">价格</label>
<div class="layui-input-inline">
<input type="text" name="addons_price" lay-verify="required" placeholder="请输入价格" autocomplete="off" class="layui-input" value="{$addons.addons_price}">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">压缩包</label>
<div class="layui-input-inline">
<input type="text" name="addons_src" lay-verify="required" placeholder="请上传zip包" autocomplete="off" class="layui-input" value="{$addons.addons_src}">
</div>
<button style="float: left;" type="button" class="layui-btn " id="layuiadmin-upload-addons">上传插件</button>
</div>
<div class="layui-form-item layui-hide">
<input type="button" lay-submit lay-filter="LAY-addons-submit" id="LAY-addons-submit" value="确认">
</div>
</div>
{/block}
{block name="js"}
<script>
layui.config({
base: '/static/admin/' //静态资源所在路径
}).extend({
index: 'lib/index' //主入口模块
}).use(['index', 'form', 'upload'], function(){
var $ = layui.$
,form = layui.form
,upload = layui.upload ;
upload.render({
elem: '#layuiadmin-upload-addons'
,url: 'uploadZip'
,accept: 'file'
,field: 'file'
,method: 'get'
,exts: 'zip|rar|7z'
,done: function(res){
$(this.item).prev("div").children("input").val(res.src);
if(res.code == 0){
layer.msg(res.msg,{
icon:6,
tiye:2000
});
} else {
layer.open({
title:"上传失败",
content:res.msg,
icon:5,
anim:6
});
}
}
});
})
</script>
{/block}

View File

@ -2,8 +2,9 @@
{block name="body"}
<div class="layui-fluid">
<div class="layui-form layui-card-header layuiadmin-card-header-auto">
<div class="layui-card">
<div class="layui-card-body">
<div class="layui-form layui-card-header layuiadmin-card-header-auto">
<div class="layui-form-item">
<div class="layui-inline">
插件分类
@ -13,50 +14,55 @@
<option value="">全部插件</option>
<option value="">支付</option>
<option value="">第三方登陆</option>
</select>
</div>
</div>
</div>
<table id="addons-list" lay-filter="addons-list"></table>
</div>
<table id="addons-list" lay-filter="addons-list"></table>
<script type="text/html" id="toolbar">
<div class="layui-btn-group" style="padding-bottom: 10px;">
<button class="layui-btn layuiadmin-btn-admin" data-type="batchdel">刷新</button>
<button class="layui-btn layuiadmin-btn-admin" data-type="add1">离线安装</button>
<button class="layui-btn layui-btn-sm layuiadmin-btn-admin" data-type="batchdel">刷新</button>
<button class="layui-btn layui-btn-sm layuiadmin-btn-admin" data-type="add">离线安装</button>
</div>
<div class="layui-btn-group" style="padding-bottom: 10px;">
<button type="button" class="layui-btn layui-btn-sm" lay-event="installed">已安装</button>
<button type="button" class="layui-btn layui-btn-sm" lay-event="onlineAddons">在线</button>
<button type="button" class="layui-btn layui-btn-sm" lay-event="freeAddons">免费</button>
<button type="button" class="layui-btn layui-btn-sm" lay-event="payAddons">付费</button>
</div>
</script>
<script type="text/html" id="addons-installed-tool">
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="install"><i class="layui-icon layui-icon-edit"></i>安装</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="set"><i class="layui-icon layui-icon-edit"></i>设置</a>
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i>卸载</a>
{{# if(d.status == 1){ }}
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="shutdown"><i class="layui-icon layui-icon-pause"></i>禁用</a>
{{# } else { }}
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="start"><i class="layui-icon layui-icon-play"></i>启动</a>
{{# } }}
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="config"><i class="layui-icon layui-icon-set"></i>设置</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i>卸载</a>
</script>
<script type="text/html" id="addons-tool">
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="install"><i class="layui-icon layui-icon-edit"></i>安装</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="set"><i class="layui-icon layui-icon-edit"></i>设置</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="config"><i class="layui-icon layui-icon-set"></i>设置</a>
</script>
</div>
</div>
</div>
{/block}
{block name="js"}
<script>
var filter = "{:url('Addons')}";
//console.log(filter);
var addonsIndex = "{:url('Addons/index')}",
addonsList = "{:url('Addons/addonsList')}",
pluginsList = "{:url('Addons/pluginsList')}",
addonsDelete = "{:url('Addons/delete')}",
addonsEdit = "{:url('Addons/edit')}";
var col = new Array();
col = {:json_encode($col)};
var addonsStart = "{:url('Addons/start')}";
var addonsShut = "{:url('Addons/shutDown')}";
var addonsInstall = "{:url('Addons/install')}";
var addonsConfig = "{:url('Addons/config')}";
layui.config({
base: '/static/admin/' //静态资源所在路径
@ -68,7 +74,6 @@
,form = layui.form
,upload = layui.upload;
//事件
var active = {
add: function(){

Binary file not shown.

View File

@ -39,14 +39,14 @@
<input type="hidden" class="layui-hide" name="__token__" value="{:token()}" />
<button class="layui-btn layui-btn-fluid" lay-submit lay-filter="LAY-user-login-submit" id="LAY-user-login-submit">登 入</button>
</div>
<div class="layui-trans layui-form-item layadmin-user-login-other">
<!--div class="layui-trans layui-form-item layadmin-user-login-other">
<label>社交账号登入</label>
<a href="javascript:;"><i class="layui-icon layui-icon-login-qq"></i></a>
<a href="javascript:;"><i class="layui-icon layui-icon-login-wechat"></i></a>
<a href="javascript:;"><i class="layui-icon layui-icon-login-weibo"></i></a>
<a href="{:url('admin/login/reg')}" class="layadmin-user-jump-change layadmin-link">注册帐号</a>
</div>
</div-->
{:hook('socialhook')}
</div>
</div>
@ -77,6 +77,7 @@
{/block}
{block name="js"}
{:hook('bacimghook')}
<script>
layui.config({
base: '/static/admin/' //静态资源所在路径
@ -89,9 +90,11 @@
,form = layui.form
,router = layui.router()
,search = router.search;
form.render();
//回车登陆
$(document).keydown(function(e){
if(e.keyCode == 13){
@ -142,4 +145,5 @@
});
</script>
{/block}

View File

@ -9,14 +9,15 @@
<div class="layui-tab layui-tab-brief" lay-filter="server-tabs-brief">
<ul class="layui-tab-title">
<li class="layui-this" lay-id="score">积分设置</li>
<li lay-id="vip">用户等级</li>
{if hook('signstatushook') == 1}
<li class="layui-this" lay-id="score">签到规则</li>
{/if}
<li lay-id="vip" {if hook('signstatushook') == 0}class="layui-this"{/if}>用户等级</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
{:hook('signadminhook')}
<!--div class="layui-tab-item layui-show">
<div class="layui-tab-content" style="padding: 20px 0;">
<div class="layui-form layui-card-header layuiadmin-card-header-auto">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">连续签到</label>
@ -54,13 +55,11 @@
{else /}<a class="layui-btn layui-btn-danger layui-btn-xs layui-btn-disabled"><i class="layui-icon layui-icon-delete"></i>删除</a>{/if}
</script>
</div>
</div>
</div>
</div>
<div class="layui-tab-item">
</div-->
<div class="layui-tab-item {if hook('signstatushook') == 0}layui-show{/if}">
<div class="layui-tab-content" style="padding: 20px 0;">
<div class="layui-form layui-card-header layuiadmin-card-header-auto">
<div class="layui-form">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">用户积分</label>
@ -85,18 +84,18 @@
</div>
</div>
</div>
</div>
<div class="layui-form-item">
<table id="vip-rule" lay-filter="vip-rule"></table>
<script type="text/html" id="vip-rule-button">
{if condition="checkRuleButton('admin/Vip/vipEdit')"}
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i class="layui-icon layui-icon-edit"></i>编辑</a>
{else /}<a class="layui-btn layui-btn-normal layui-btn-xs layui-btn-disabled"><i class="layui-icon layui-icon-edit"></i>编辑</a>{/if}
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i class="layui-icon layui-icon-edit"></i></a>
{else /}<a class="layui-btn layui-btn-normal layui-btn-xs layui-btn-disabled"><i class="layui-icon layui-icon-edit"></i></a>{/if}
{if condition="checkRuleButton('admin/Vip/delete')"}
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i>删除</a>
{else /}<a class="layui-btn layui-btn-danger layui-btn-xs layui-btn-disabled"><i class="layui-icon layui-icon-delete"></i>删除</a>{/if}
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i></a>
{else /}<a class="layui-btn layui-btn-danger layui-btn-xs layui-btn-disabled"><i class="layui-icon layui-icon-delete"></i></a>{/if}
</script>
</div>
</div>
</div>
</div>
</div>
@ -132,7 +131,7 @@
var field = data.field;
$.ajax({
type:"post",
url:"{:url('admin/Sign/add')}",
url: signAddAddons,
data:field,
daType:"json",
success:function (data){
@ -154,7 +153,7 @@
}
});
return false;
});
});
//添加VIP规则
form.on('submit(vip-rule-submit)',function(data){

View File

@ -164,7 +164,7 @@ CREATE TABLE `tao_auth_rule` (
`pid` smallint(5) NOT NULL DEFAULT '0' COMMENT '父级ID',
`level` tinyint(1) NOT NULL DEFAULT '1' COMMENT '菜单层级',
`icon` varchar(50) NOT NULL DEFAULT '' COMMENT '图标',
`ishidden` enum('1','0') NOT NULL DEFAULT '1' COMMENT '0隐藏,1显示',
`ishidden` enum('1','0','-1') NOT NULL DEFAULT '1' COMMENT '0隐藏,1显示-1其它',
`sort` tinyint(4) NOT NULL DEFAULT '50' COMMENT '排序',
`condition` char(100) NOT NULL DEFAULT '',
`create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
@ -177,11 +177,11 @@ CREATE TABLE `tao_auth_rule` (
-- ----------------------------
-- Records of tao_auth_rule
-- ----------------------------
INSERT INTO `tao_auth_rule` VALUES ('1', 'admin', '管理', '', '1', '1', '0', '0', 'layui-icon-user', '1', '3', '', '0', '0', '0');
INSERT INTO `tao_auth_rule` VALUES ('2', 'set', '设置', '', '1', '1', '0', '0', 'layui-icon-set', '1', '4', '', '0', '0', '0');
INSERT INTO `tao_auth_rule` VALUES ('3', 'administrator', '账户', '', '1', '1', '0', '0', 'layui-icon-username', '1', '5', '', '0', '1578980034', '0');
INSERT INTO `tao_auth_rule` VALUES ('4', 'app', '应用', '', '1', '1', '0', '0', 'layui-icon-app', '1', '2', '', '0', '0', '0');
INSERT INTO `tao_auth_rule` VALUES ('5', 'article', '内容', '', '1', '1', '0', '0', 'layui-icon-read', '1', '0', '', '0', '1578902321', '0');
INSERT INTO `tao_auth_rule` VALUES ('1', 'admin', '管理', '', '1', '1', '0', '0', 'layui-icon-user', '1', '5', '', '0', '1635757559', '0');
INSERT INTO `tao_auth_rule` VALUES ('2', 'set', '设置', '', '1', '1', '0', '0', 'layui-icon-set', '1', '6', '', '0', '1635757571', '0');
INSERT INTO `tao_auth_rule` VALUES ('3', 'administrator', '账户', '', '1', '1', '0', '0', 'layui-icon-username', '1', '7', '', '0', '1635757594', '0');
INSERT INTO `tao_auth_rule` VALUES ('4', 'app', '应用', '', '1', '1', '0', '0', 'layui-icon-app', '1', '4', '', '0', '1635757536', '0');
INSERT INTO `tao_auth_rule` VALUES ('5', 'article', '内容', '', '1', '1', '0', '0', 'layui-icon-read', '1', '1', '', '0', '1635757294', '0');
INSERT INTO `tao_auth_rule` VALUES ('6', 'admin/User/list', '用户管理', '', '1', '1', '1', '1', '', '1', '1', '', '0', '1578901015', '0');
INSERT INTO `tao_auth_rule` VALUES ('7', 'admin/Admin/index', '管理员', '', '1', '1', '1', '1', '', '1', '6', '', '0', '1578901133', '0');
INSERT INTO `tao_auth_rule` VALUES ('8', 'admin/AuthGroup/list', '角色管理', '', '1', '1', '1', '1', '', '1', '11', '', '0', '1578901282', '0');
@ -257,10 +257,13 @@ INSERT INTO `tao_auth_rule` VALUES ('89', 'admin/User/auth', '设置超级用户
INSERT INTO `tao_auth_rule` VALUES ('90', 'admin/Forum/tagshot', '开启热点', '', '1', '1', '16', '2', '', '0', '15', '', '1585841826', '1611997546', '0');
INSERT INTO `tao_auth_rule` VALUES ('91', 'admin/Admin/infoSet', '资料设置', '', '1', '1', '12', '2', '', '0', '62', '', '1586245669', '1611998517', '0');
INSERT INTO `tao_auth_rule` VALUES ('92', 'admin/Admin/repassSet', '密码设置', '', '1', '1', '13', '2', '', '0', '64', '', '1586245727', '1611998534', '0');
INSERT INTO `tao_auth_rule` VALUES ('93', 'servers', '服务', '', '1', '1', '0', '0', 'layui-icon-cols', '1', '2', '', '1611286515', '1611997619', '0');
INSERT INTO `tao_auth_rule` VALUES ('93', 'servers', '服务', '', '1', '1', '0', '0', 'layui-icon-cols', '1', '3', '', '1611286515', '1635757525', '0');
INSERT INTO `tao_auth_rule` VALUES ('94', 'admin/Database/index', '数据备份', '', '1', '1', '93', '1', '', '1', '9', '', '1611897141', '1611902589', '0');
INSERT INTO `tao_auth_rule` VALUES ('95', 'admin/Database/backup', '进行备份', '', '1', '1', '94', '2', '', '0', '10', '', '1611897285', '1611902610', '0');
INSERT INTO `tao_auth_rule` VALUES ('96', 'admin/Database/delete', '备份删除', '', '1', '1', '94', '2', '', '0', '0', '', '1611902429', '0', '0');
INSERT INTO `tao_auth_rule` VALUES ('97', 'addons', '插件', '', '1', '1', '0', '0', 'layui-icon-flag', '1', '2', '', '1635757328', '1635757632', '0');
INSERT INTO `tao_auth_rule` VALUES ('98', 'admin/Addons/index', '插件市场', '', '1', '1', '97', '1', '', '1', '0', '', '1635757426', '0', '0');
INSERT INTO `tao_auth_rule` VALUES ('99', 'admin/Addons/addonsList', '插件列表', '', '1', '1', '98', '2', '', '', '0', '', '1635758251', '0', '0');
-- ----------------------------
-- Table structure for tao_cate
@ -471,7 +474,7 @@ CREATE TABLE `tao_system` (
`cache` tinyint(5) NOT NULL DEFAULT '0' COMMENT '缓存时间分钟',
`upsize` int(5) NOT NULL DEFAULT '0' COMMENT '上传文件大小KB',
`uptype` varchar(255) NOT NULL DEFAULT '0' COMMENT '上传文件类型',
`copyright` varchar(80) NOT NULL DEFAULT '' COMMENT '版权',
`copyright` varchar(100) NOT NULL DEFAULT '' COMMENT '版权',
`keywords` tinytext NOT NULL COMMENT '网站关键字',
`descript` tinytext NOT NULL COMMENT '网站描述',
`is_open` enum('0','1') NOT NULL DEFAULT '1' COMMENT '是否开启站点1开启0关闭',

View File

@ -0,0 +1,18 @@
<?php
namespace app\middleware;
use think\facade\Request;
use think\facade\Lang;
class AddonsLang
{
public function handle($request, \Closure $next)
{
Lang::load([
//$this->app->getRootPath() . '/vendor/zzstudio/think-addons/src/lang/zh-cn.php',
app()->getRootPath().'addons/sign/lang/zh-cn.php',
]);
return $next($request);
}
}

View File

@ -18,7 +18,7 @@ class Auth
public function handle($request, \Closure $next)
{
$path = app('http')->getName().'/'.stristr($request->pathinfo(),".html",true);
//var_dump($path);
//没有登录及当前非登录页重定向登录页
if(!Session::has('admin_id') && $path !== 'admin/login/index' && !stristr($request->pathinfo(),"captcha.html") )
{
@ -31,14 +31,16 @@ class Auth
}
// 排除公共权限
$not_check = ['admin/','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'];
$not_check = ['admin/','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/'];
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 view('public/auth');
//return response("<script>alert('没有操作权限')</script>");
return json(['code'=>-1,'msg'=>'无权限']);
}
}
return $next($request);

View File

@ -8,13 +8,14 @@ class CheckRegister
{
public function handle($request, \Closure $next)
{
//排除特殊注册用户名
//排除禁止注册用户名的字段
if($request->action(true)=='reg'){
$name = $request->param('name');
$disname = Db::name('system')->where('id',1)->value('blackname');
$data = explode("|",$disname);
foreach($data as $v){
if ($request->param('name') == $v) {
return json(['msg'=>'该用户名禁止注册,请更换名称']);
if(stripos($name,$v) !== false){
return json(['msg'=>'非法字段或该用户名禁止注册,请更换']);
}
}
}

View File

@ -24,10 +24,10 @@
"topthink/think-view": "^1.0",
"topthink/think-captcha": "^3.0",
"phpmailer/phpmailer": "^6.1",
"zzstudio/think-addons": "^2.0",
"firebase/php-jwt": "^5.2",
"lotofbadcode/phpspirit_databackup": "^1.1",
"wamkj/thinkphp6.0-databackup": "^1.0"
"wamkj/thinkphp6.0-databackup": "^1.0",
"taoser/think-addons": "^1.0"
},
"require-dev": {
"symfony/var-dumper": "^4.2",
@ -39,7 +39,10 @@
},
"psr-0": {
"": "extend/"
}
},
"files": [
"extend/taoler/com/form.php"
]
},
"config": {
"preferred-install": "dist"

180
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": "c6dc1dcd45b2b2cd2e7bd36c0e76eb04",
"content-hash": "3ef61427e5d1c98f5ca1e197d25ef688",
"packages": [
{
"name": "firebase/php-jwt",
@ -71,16 +71,16 @@
},
{
"name": "league/flysystem",
"version": "1.1.4",
"version": "1.1.5",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
"reference": "f3ad69181b8afed2c9edf7be5a2918144ff4ea32"
"reference": "18634df356bfd4119fe3d6156bdb990c414c14ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/f3ad69181b8afed2c9edf7be5a2918144ff4ea32",
"reference": "f3ad69181b8afed2c9edf7be5a2918144ff4ea32",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/18634df356bfd4119fe3d6156bdb990c414c14ea",
"reference": "18634df356bfd4119fe3d6156bdb990c414c14ea",
"shasum": "",
"mirrors": [
{
@ -159,7 +159,7 @@
],
"support": {
"issues": "https://github.com/thephpleague/flysystem/issues",
"source": "https://github.com/thephpleague/flysystem/tree/1.1.4"
"source": "https://github.com/thephpleague/flysystem/tree/1.1.5"
},
"funding": [
{
@ -167,7 +167,7 @@
"type": "other"
}
],
"time": "2021-06-23T21:56:05+00:00"
"time": "2021-08-17T13:49:42+00:00"
},
{
"name": "league/flysystem-cached-adapter",
@ -228,16 +228,16 @@
},
{
"name": "league/mime-type-detection",
"version": "1.7.0",
"version": "1.8.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/mime-type-detection.git",
"reference": "3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3"
"reference": "b38b25d7b372e9fddb00335400467b223349fd7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3",
"reference": "3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3",
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/b38b25d7b372e9fddb00335400467b223349fd7e",
"reference": "b38b25d7b372e9fddb00335400467b223349fd7e",
"shasum": "",
"mirrors": [
{
@ -274,7 +274,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.7.0"
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.8.0"
},
"funding": [
{
@ -286,7 +286,7 @@
"type": "tidelift"
}
],
"time": "2021-01-18T20:58:21+00:00"
"time": "2021-09-25T08:23:19+00:00"
},
{
"name": "lotofbadcode/phpspirit_databackup",
@ -340,16 +340,16 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.5.0",
"version": "v6.5.1",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c"
"reference": "dd803df5ad7492e1b40637f7ebd258fee5ca7355"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a5b5c43e50b7fba655f793ad27303cd74c57363c",
"reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/dd803df5ad7492e1b40637f7ebd258fee5ca7355",
"reference": "dd803df5ad7492e1b40637f7ebd258fee5ca7355",
"shasum": "",
"mirrors": [
{
@ -367,10 +367,12 @@
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"doctrine/annotations": "^1.2",
"php-parallel-lint/php-console-highlighter": "^0.5.0",
"php-parallel-lint/php-parallel-lint": "^1.3",
"phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.5.6",
"yoast/phpunit-polyfills": "^0.2.0"
"squizlabs/php_codesniffer": "^3.6.0",
"yoast/phpunit-polyfills": "^1.0.0"
},
"suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
@ -410,7 +412,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.5.0"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.5.1"
},
"funding": [
{
@ -418,7 +420,7 @@
"type": "github"
}
],
"time": "2021-06-16T14:33:43+00:00"
"time": "2021-08-18T09:14:16+00:00"
},
{
"name": "psr/cache",
@ -642,6 +644,68 @@
},
"time": "2017-10-23T01:57:42+00:00"
},
{
"name": "taoser/think-addons",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/taoser/think-addons.git",
"reference": "bd8b0bfa4543fe8d2da65355c134250f78c0d457"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/taoser/think-addons/zipball/bd8b0bfa4543fe8d2da65355c134250f78c0d457",
"reference": "bd8b0bfa4543fe8d2da65355c134250f78c0d457",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.1.0",
"topthink/framework": "^6.0",
"topthink/think-helper": "^3.0.0",
"topthink/think-view": "^1.0"
},
"type": "library",
"extra": {
"think": {
"services": [
"taoser\\addons\\Service"
],
"config": {
"addons": "src/config.php"
}
}
},
"autoload": {
"psr-4": {
"taoser\\": "src/"
},
"files": [
"src/helper.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"mit"
],
"authors": [
{
"name": "taoler",
"email": "changlin_zhao@qq.com"
}
],
"description": "The ThinkPHP6 Addons Package",
"support": {
"issues": "https://github.com/taoser/think-addons/issues",
"source": "https://github.com/taoser/think-addons/tree/v1.0.1"
},
"time": "2021-09-18T08:41:10+00:00"
},
{
"name": "taoser/think-auth",
"version": "v1.0.0",
@ -1139,68 +1203,6 @@
"source": "https://github.com/wamkj/thinkphp6.0-databackup/tree/v1.0"
},
"time": "2020-02-15T13:04:16+00:00"
},
{
"name": "zzstudio/think-addons",
"version": "2.0.5",
"source": {
"type": "git",
"url": "https://github.com/zz-studio/think-addons.git",
"reference": "7eb740cb219a111d593a05ad88248a74f640fe5c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zz-studio/think-addons/zipball/7eb740cb219a111d593a05ad88248a74f640fe5c",
"reference": "7eb740cb219a111d593a05ad88248a74f640fe5c",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.1.0",
"topthink/framework": "^6.0",
"topthink/think-helper": "^3.0.0",
"topthink/think-view": "^1.0"
},
"type": "library",
"extra": {
"think": {
"services": [
"think\\addons\\Service"
],
"config": {
"addons": "src/config.php"
}
}
},
"autoload": {
"psr-4": {
"think\\": "src/"
},
"files": [
"src/helper.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "byron",
"email": "xiaobo.sun@qq.com"
}
],
"description": "The ThinkPHP6 Addons Package",
"support": {
"issues": "https://github.com/zz-studio/think-addons/issues",
"source": "https://github.com/zz-studio/think-addons/tree/2.0.5"
},
"time": "2020-01-06T06:42:39+00:00"
}
],
"packages-dev": [
@ -1463,16 +1465,16 @@
},
{
"name": "symfony/var-dumper",
"version": "v4.4.27",
"version": "v4.4.33",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "391d6d0e7a06ab54eb7c38fab29b8d174471b3ba"
"reference": "50286e2b7189bfb4f419c0731e86632cddf7c5ee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/391d6d0e7a06ab54eb7c38fab29b8d174471b3ba",
"reference": "391d6d0e7a06ab54eb7c38fab29b8d174471b3ba",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/50286e2b7189bfb4f419c0731e86632cddf7c5ee",
"reference": "50286e2b7189bfb4f419c0731e86632cddf7c5ee",
"shasum": "",
"mirrors": [
{
@ -1538,7 +1540,7 @@
"dump"
],
"support": {
"source": "https://github.com/symfony/var-dumper/tree/v4.4.27"
"source": "https://github.com/symfony/var-dumper/tree/v4.4.33"
},
"funding": [
{
@ -1554,7 +1556,7 @@
"type": "tidelift"
}
],
"time": "2021-07-23T15:41:52+00:00"
"time": "2021-10-25T20:24:58+00:00"
},
{
"name": "topthink/think-trace",

View File

@ -21,7 +21,7 @@ return [
'app_map' => [],
// 域名绑定(自动多应用模式有效)
'domain_bind' => [
//'www' => 'index',
//'bbs' => 'index',
//'adm' => 'admin',
//'api' => 'api'
],
@ -29,15 +29,16 @@ return [
'deny_app_list' => [],
// 异常页面的模板文件
'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl',
//'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl',
'exception_tmpl' => app()->getAppPath() . '404.html',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => true,
'show_error_msg' => false,
//异常页面模板
'http_exception_template' => [
404 => '404.html',
500 => '404.html'
404 => \think\facade\App::getAppPath() . '404.html',
500 => \think\facade\App::getAppPath() . '404.html',
]
];

View File

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

223
extend/taoler/com/form.php Normal file
View File

@ -0,0 +1,223 @@
<?php
use taoler\com\FormHelper;
if (!function_exists('form_input')) {
/**
* @param $type
* @param $name
* @return string
*/
function form_input($name='',$type='text',$options=[],$value=null)
{
return FormHelper::input($name,$type,$options,$value);
}
}
if (!function_exists('form_radio')) {
/**
* @param $id
* @param $name
* @return string
*/
function form_radio($name=null, $radiolist = null, $options = [],$value='')
{
return FormHelper::radio($name,$radiolist,$options,$value);
}
}
if (!function_exists('form_switch')) {
/**
* @param $id
* @param $name
* @param $switch
* @param $option
* @param $value
* @return string
*/
function form_switch($name,$switch=[] , $option=[],$value='')
{
return FormHelper::switchs($name,$switch , $option,$value);
}
}
if (!function_exists('form_checkbox')) {
/**
* @param $id
* @param $name
* @return string
*/
function form_checkbox($name,$list, $option, $value)
{
return FormHelper::checkbox($name,$list, $option, $value);
}
}
if (!function_exists('form_arrays')) {
/**
* @param $id
* @param $name
* @return string
*/
function form_arrays($name, $option, $list=[])
{
return FormHelper::arrays($name, $option, $list);
}
}
if (!function_exists('form_textarea')) {
/**
* @param $id
* @param $name
* @return string
*/
function form_textarea($name=null, $option=[], $value=null)
{
return FormHelper::textarea($name, $option,$value);
}
}
if (!function_exists('form_select')) {
/**
* @param null $name
* @param array $options
* @return string
*/
function form_select($name = null,$select=[], $options = [],$attr='',$value=null)
{
if(!empty($attr) and !is_array($attr)) $attr = explode(',',$attr);
return FormHelper::multiselect($name,$select,$options,$attr,$value);
}
}
if (!function_exists('form_multiselect')) {
/**
* @param null $name
* @param array $options
* @return string
*/
function form_multiselect($name = null,$select=[], $options = [],$attr='',$value='')
{
if(!empty($attr) and !is_array($attr))$attr = explode(',',$attr);
return FormHelper::multiselect($name,$select,$options,$attr,$value);
}
}
if (!function_exists('form_xmselect')) {
/**
* @param null $name
* @param array $options
* @return string
*/
function form_xmselect($name = null,$select=[], $options = [],$attr='',$value='')
{
if(!empty($attr) and !is_array($attr))$attr = explode(',',$attr);
return FormHelper::xmselect($name,$select,$options,$attr,$value);
}
}
if (!function_exists('form_icon')) {
/**
* @param array $options
* @return string
*/
function form_icon($name=null,$options = [],$value=null)
{
return FormHelper::icon($name, $options,$value);
}
}
if (!function_exists('form_date')) {
/**
* @param array $options
* @return string
*/
function form_date($name=null,$options = [],$value='')
{
return FormHelper::date($name, $options,$value);
}
}
if (!function_exists('form_city')) {
/**
* @param array $options
* @return string
*/
function form_city($name='cityPicker',$id='cityPicker',$options = [])
{
return FormHelper::city($name,$id,$options);
}
}
if (!function_exists('form_region')) {
/**
* @param array $options
* @return string
*/
function form_region($name='regionCheck',$id='regionCheck',$options = [])
{
return FormHelper::region($name,$id,$options);
}
}
if (!function_exists('form_tags')) {
/**
* @param array $options
* @return string
*/
function form_tags($id='tags',$name='',$options = [],$value='')
{
return FormHelper::tags($id,$name,$options,$value);
}
}
if (!function_exists('form_color')) {
/**
* @param array $options
* @return string
*/
function form_color($id='iconPicker',$name=null,$options = [],$value='')
{
return FormHelper::color($id,$name,$options,$value);
}
}
if (!function_exists('form_submitbtn')) {
/**
* @param bool $reset
* @param array $options
* @return string
*/
function form_submitbtn($reset = true, $options=[])
{
return FormHelper::submitbtn($reset, $options);
}
}
if (!function_exists('form_closebtn')) {
/**
* @param bool $reset
* @param array $options
* @return string
*/
function form_closebtn($reset = true, $options=[])
{
return FormHelper::closebtn($reset,$options);
}
}
if (!function_exists('form_upload')) {
/**
* @param $name
* @param null $formdata
* @return string
*/
function form_upload($name=null,$formdata=[],$options=[])
{
return FormHelper::upload($name,$formdata,$options);
}
}
if (!function_exists('form_editor')) {
/**
* @param $id
* @param $name
* @return string
*/
function form_editor($name='container',$id='container',$type=1,$options=[])
{
return FormHelper::editor($name,$id,$type,$options);
}
}

View File

@ -1,55 +0,0 @@
/**
@NamelayuiAdmin 登入注册页
@Author贤心
@Sitehttp://www.layui.com/admin/
@LicenseGPL-2
*/
html,body,#LAY_app{height:100%; background: url(res/bg1.jpg) no-repeat center; background-size: cover;}
.layui-layout-body{overflow: auto;}
#LAY-user-login,
.layadmin-user-display-show{display: block !important;}
.layadmin-user-login{position: relative; left: 0; top: 0; padding: 110px 0; min-height: 100%; box-sizing: border-box;}
.layadmin-user-login-main{width: 375px; margin: 0 auto; box-sizing: border-box; background-color:rgba(0,0,0,.6); border:1px solid; border-radius:15px}
.layadmin-user-login-box{padding: 20px;}
.layadmin-user-login-header{text-align: center;}
.layadmin-user-login-header h2{margin-bottom: 10px; font-weight: 300; font-size: 30px; color: #000;}
.layadmin-user-login-header p{font-weight: 300; color: #999;}
.layadmin-user-login-body .layui-form-item{position: relative;}
.layadmin-user-login-icon{position: absolute; left: 1px; top: 1px; width: 38px; line-height: 36px; text-align: center; color: #d2d2d2;}
.layadmin-user-login-body .layui-form-item .layui-input{padding-left: 38px;}
.layadmin-user-login-codeimg{max-height: 38px; width: 100%; cursor: pointer; box-sizing: border-box;}
.layadmin-user-login-other{position: relative; font-size: 0; line-height: 38px; padding-top: 20px;}
.layadmin-user-login-other>*{display: inline-block; vertical-align: middle; margin-right: 10px; font-size: 14px;}
.layadmin-user-login-other .layui-icon{position: relative; top: 2px; font-size: 26px;}
.layadmin-user-login-other a:hover{opacity: 0.8;}
.layadmin-user-jump-change{float: right;}
.layadmin-user-login-footer{position: absolute; left: 0; bottom: 0; width: 100%; line-height: 30px; padding: 20px; text-align: center; box-sizing: border-box; color: rgba(0,0,0,.5)}
.layadmin-user-login-footer span{padding: 0 5px;}
.layadmin-user-login-footer a{padding: 0 5px; color: rgba(0,0,0,.5);}
.layadmin-user-login-footer a:hover{color: rgba(0,0,0,1);}
/* 有背景图时 */
.layadmin-user-login-main[bgimg]{background-color: #fff; box-shadow: 0 0 5px rgba(0,0,0,0.05);}
/* 主题背景 */
.ladmin-user-login-theme{position: fixed; bottom: 0; left: 0; width: 100%; text-align: center;}
.ladmin-user-login-theme ul{display: inline-block; padding: 5px; background-color: #fff;}
.ladmin-user-login-theme ul li{display: inline-block; vertical-align: top; width: 64px; height: 43px; cursor: pointer; transition: all .3s; -webkit-transition: all .3s; background-color: #f2f2f2;}
.ladmin-user-login-theme ul li:hover{opacity: 0.9}
@media screen and (max-width: 768px) {
.layadmin-user-login{padding-top: 60px;}
.layadmin-user-login-main{width: 300px;}
.layadmin-user-login-box{padding: 10px;}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 KiB

View File

@ -6,86 +6,66 @@ layui.define(['table', 'form','upload'], function(exports){
,form = layui.form
,upload = layui.upload;
//安装插件
table.render({
elem: '#addons-list',
toolbar: '#toolbar',
url: addonsList,
cols:[
col
]
,page: true
,limit: 10
,height: 'full-220'
,text: '对不起,加载出现异常!'
});
function addList(type)
{
$.ajax({
type: 'post',
url: addonsList ,
data: {type:type},
dataType: 'json',
success: function (res) {
//渲染表格
table.render({
elem: '#addons-list',
toolbar: '#toolbar',
defaultToolbar: [],
url: addonsList + '?type='+ type,
cols: [
res['col']
]
, page: true
, limit: 10
, height: 'full-220'
, text: '对不起,加载出现异常!'
});
}
});
}
addList('installed');
//头工具栏事件
table.on('toolbar(addons-list)', function(obj){
var checkStatus = table.checkStatus(obj.config.id);
switch(obj.event){
case 'installed':
$.post(addonsIndex + '?type=installed',function(){
location.href = addonsIndex + '?type=installed';
});
$.post(addonsList + '?type=installed',{"type":"installed"});
table.reload('addons-list', {
where: {"type":"installed"}
}); //数据刷新
addList("installed");
break;
case 'onlineAddons':
$.post(addonsIndex + '?type=onlineAddons',function(){
location.href = addonsIndex + '?type=onlineAddons';
});
$.post(addonsList + '?type=onlineAddons',{"type":"onlineAddons"});
table.reload('addons-list', {
where: {"type":"onlineAddons"}
}); //数据刷新
addList("onlineAddons");
break;
case 'isAll':
layer.msg(checkStatus.isAll ? '全选': '未全选');
break;
//自定义头工具栏右侧图标 - 提示
case 'LAYTABLE_TIPS':
layer.alert('这是工具栏右侧自定义的一个图标按钮');
break;
};
}
});
//监听工具条
table.on('tool(addons-list)', function(obj){
var data = obj.data;
if(obj.event === 'del'){
layer.prompt({
formType: 1
,title: '敏感操作,请验证口令'
}, function(value, index){
layer.close(index);
layer.confirm('真的删除行么', function(index){
//obj.del();
$.ajax({
type:'post',
url:addonsDelete,
data:{id:data.id},
dataType:'json',
success:function(data){
if(data.code == 0){
layer.msg(data.msg,{
icon:6,
time:2000
});
} else {
layer.open({
title:'删除失败',
content:data.msg,
icon:5,
adim:6
})
}
}
});
$.post(addonsDelete,{name:data.name},function (res) {
if (res.code == 0) {
layer.msg(res.msg,{icon:6,time:2000});
} else {
layer.open({tiele:'修改失败',content:res.msg,icon:5,anim:6});
}
});
table.reload('addons-list');
layer.close(index);
});
@ -100,7 +80,6 @@ layui.define(['table', 'form','upload'], function(exports){
,area: ['400px', '620px']
,btn: ['确定', '取消']
,yes: function(index, layero){
var iframeWindow = window['layui-layer-iframe'+ index]
,submitID = 'LAY-addons-submit'
,submit = layero.find('iframe').contents().find('#'+ submitID);
@ -117,17 +96,9 @@ layui.define(['table', 'form','upload'], function(exports){
daType:"json",
success:function (res){
if (res.code == 0) {
layer.msg(res.msg,{
icon:6,
time:2000
});
layer.msg(res.msg,{icon:6,time:2000});
} else {
layer.open({
tiele:'修改失败',
content:res.msg,
icon:5,
anim:6
});
layer.open({tiele:'修改失败',content:res.msg,icon:5,anim:6});
}
}
});
@ -142,7 +113,106 @@ layui.define(['table', 'form','upload'], function(exports){
}
});
}
} else if (obj.event === 'start'){
//提交 Ajax 成功后,静态更新表格中的数据
$.ajax({
type:"post",
url:addonsStart,
data:{name:data.name},
daType:"json",
success:function (res){
if (res.code == 0) {
layer.msg(res.msg,{icon:6,time:2000});
} else {
layer.open({tiele:'修改失败',content:res.msg,icon:5,anim:6});
}
}
});
} else if(obj.event === 'shutdown'){
//提交 Ajax 成功后,静态更新表格中的数据
$.ajax({
type:"post",
url:addonsShut,
data:{name:data.name},
daType:"json",
success:function (res){
if (res.code == 0) {
layer.msg(res.msg,{icon:6,time:2000});
} else {
layer.open({tiele:'修改失败',content:res.msg,icon:5,anim:6});
}
}
});
} else if(obj.event === 'install'){
//安装插件
$.post(addonsInstall,{name:data.name,version:data.version},function (res) {
if (res.code == 0) {
layer.msg(res.msg,{icon:6,time:2000});
} else {
layer.open({tiele:'修改失败',content:res.msg,icon:5,anim:6});
}
});
} else if(obj.event === 'config'){
layer.open({
type: 2
,title: '配置插件'
,content: addonsConfig + '?name='+ data.name
,maxmin: true
,area: ['780px', '90%']
,btn: ['确定', '取消']
,yes: function(index, layero){
var iframeWindow = window['layui-layer-iframe'+ index]
,submitID = 'LAY-addons-config-submit'
,submit = layero.find('iframe').contents().find('#'+ submitID);
//监听提交
iframeWindow.layui.form.on('submit('+ submitID +')', function(data){
var field = data.field; //获取提交的字段
$.ajax({
type:"post",
url:addonsConfig,
data:field,
daType:"json",
success:function (res){
if (res.code == 0) {
layer.msg(res.msg,{icon:6,time:2000});
} else {
layer.open({tiele:'修改失败',content:res.msg,icon:5,anim:6});
}
}
});
layer.close(index); //关闭弹层
});
submit.trigger('click');
}
,success: function(layero, index){
var forms = layero.find('iframe').contents().find('.layui-form');
var button = forms.find('button');
//事件委托
forms.on('click','button',function (data) {
var even = this.getAttribute('lay-event');
var names = this.dataset.name;
if(even == 'addInput'){
var html = '<div class="layui-form-item"><label class="layui-form-label"></label><div class="layui-input-inline">\n' +
' <input type="text" name="'+ names +'[key][]" value="" placeholder="key" autocomplete="off" class="layui-input input-double-width">\n' +
' </div><div class="layui-input-inline">\n' +
' <input type="text" name="'+ names +'[value][]" value="" placeholder="value" autocomplete="off" class="layui-input input-double-width">\n' +
' </div>\n' +
' <button data-name="'+ names +'" type="button" class="layui-btn layui-btn-danger layui-btn-sm removeInupt" lay-event="removeInupt">\n' +
' <i class="layui-icon"></i>\n' +
' </button>\n' +
' </div>';
$(this).parent().parent().append(html);
} else {
$(this).parent().remove();
}
});
}
});
}
table.reload('addons-list'); //数据刷新
});
exports('addons', {})

View File

@ -6,14 +6,14 @@
@LicenseGPL-2
*/
html,body,#LAY_app{height:100%;}
.layui-layout-body{overflow: auto;}
#LAY-user-login,
.layadmin-user-display-show{display: block !important;}
.layadmin-user-login{position: relative; left: 0; top: 0; padding: 110px 0; min-height: 100%; box-sizing: border-box;}
.layadmin-user-login-main{width: 375px; margin: 0 auto; box-sizing: border-box;}
.layadmin-user-login-main{width: 375px; margin-top: 0px; margin-left: 5%; box-sizing: border-box; background-color:rgba(0,0,0,.3); border:1px solid; border-radius:15px}
.layadmin-user-login-box{padding: 20px;}
.layadmin-user-login-header{text-align: center;}
.layadmin-user-login-header h2{margin-bottom: 10px; font-weight: 300; font-size: 30px; color: #000;}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -35,12 +35,12 @@ private static $installed = array (
),
'league/flysystem' =>
array (
'pretty_version' => '1.1.4',
'version' => '1.1.4.0',
'pretty_version' => '1.1.5',
'version' => '1.1.5.0',
'aliases' =>
array (
),
'reference' => 'f3ad69181b8afed2c9edf7be5a2918144ff4ea32',
'reference' => '18634df356bfd4119fe3d6156bdb990c414c14ea',
),
'league/flysystem-cached-adapter' =>
array (
@ -53,12 +53,12 @@ private static $installed = array (
),
'league/mime-type-detection' =>
array (
'pretty_version' => '1.7.0',
'version' => '1.7.0.0',
'pretty_version' => '1.8.0',
'version' => '1.8.0.0',
'aliases' =>
array (
),
'reference' => '3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3',
'reference' => 'b38b25d7b372e9fddb00335400467b223349fd7e',
),
'lotofbadcode/phpspirit_databackup' =>
array (
@ -71,12 +71,12 @@ private static $installed = array (
),
'phpmailer/phpmailer' =>
array (
'pretty_version' => 'v6.5.0',
'version' => '6.5.0.0',
'pretty_version' => 'v6.5.1',
'version' => '6.5.1.0',
'aliases' =>
array (
),
'reference' => 'a5b5c43e50b7fba655f793ad27303cd74c57363c',
'reference' => 'dd803df5ad7492e1b40637f7ebd258fee5ca7355',
),
'psr/cache' =>
array (
@ -143,12 +143,12 @@ private static $installed = array (
),
'symfony/var-dumper' =>
array (
'pretty_version' => 'v4.4.27',
'version' => '4.4.27.0',
'pretty_version' => 'v4.4.33',
'version' => '4.4.33.0',
'aliases' =>
array (
),
'reference' => '391d6d0e7a06ab54eb7c38fab29b8d174471b3ba',
'reference' => '50286e2b7189bfb4f419c0731e86632cddf7c5ee',
),
'taoser/taoler' =>
array (
@ -159,6 +159,15 @@ private static $installed = array (
),
'reference' => NULL,
),
'taoser/think-addons' =>
array (
'pretty_version' => 'v1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => 'bd8b0bfa4543fe8d2da65355c134250f78c0d457',
),
'taoser/think-auth' =>
array (
'pretty_version' => 'v1.0.0',
@ -249,15 +258,6 @@ private static $installed = array (
),
'reference' => '28a0e406d827132942723a3c9f69bb20c98e652f',
),
'zzstudio/think-addons' =>
array (
'pretty_version' => '2.0.5',
'version' => '2.0.5.0',
'aliases' =>
array (
),
'reference' => '7eb740cb219a111d593a05ad88248a74f640fe5c',
),
),
);

View File

@ -11,7 +11,8 @@ return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'223fa6f9b46fbe5d6b44c5ff847bfceb' => $vendorDir . '/taoser/think-addons/src/helper.php',
'1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php',
'39594db8502267d6df2fe2dca5f3914d' => $vendorDir . '/zzstudio/think-addons/src/helper.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'd421242fd42b2ea6cd13f802bcf18a6e' => $baseDir . '/extend/taoler/com/form.php',
);

View File

@ -11,8 +11,9 @@ return array(
'think\\trace\\' => array($vendorDir . '/topthink/think-trace/src'),
'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'),
'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/zzstudio/think-addons/src'),
'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'),
'phpspirit\\databackup\\' => array($vendorDir . '/lotofbadcode/phpspirit_databackup/src'),
'app\\' => array($baseDir . '/app'),
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),

View File

@ -12,9 +12,10 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'223fa6f9b46fbe5d6b44c5ff847bfceb' => __DIR__ . '/..' . '/taoser/think-addons/src/helper.php',
'1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
'39594db8502267d6df2fe2dca5f3914d' => __DIR__ . '/..' . '/zzstudio/think-addons/src/helper.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'd421242fd42b2ea6cd13f802bcf18a6e' => __DIR__ . '/../..' . '/extend/taoler/com/form.php',
);
public static $prefixLengthsPsr4 = array (
@ -30,6 +31,7 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
'think\\app\\' => 10,
'think\\' => 6,
'taoser\\think\\' => 13,
'taoser\\' => 7,
),
'p' =>
array (
@ -93,12 +95,15 @@ class ComposerStaticInit1b32198725235c8d6500c87262ef30c2
1 => __DIR__ . '/..' . '/topthink/think-helper/src',
2 => __DIR__ . '/..' . '/topthink/think-orm/src',
3 => __DIR__ . '/..' . '/topthink/think-template/src',
4 => __DIR__ . '/..' . '/zzstudio/think-addons/src',
),
'taoser\\think\\' =>
array (
0 => __DIR__ . '/..' . '/taoser/think-auth/src',
),
'taoser\\' =>
array (
0 => __DIR__ . '/..' . '/taoser/think-addons/src',
),
'phpspirit\\databackup\\' =>
array (
0 => __DIR__ . '/..' . '/lotofbadcode/phpspirit_databackup/src',

View File

@ -68,17 +68,17 @@
},
{
"name": "league/flysystem",
"version": "1.1.4",
"version_normalized": "1.1.4.0",
"version": "1.1.5",
"version_normalized": "1.1.5.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
"reference": "f3ad69181b8afed2c9edf7be5a2918144ff4ea32"
"reference": "18634df356bfd4119fe3d6156bdb990c414c14ea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/f3ad69181b8afed2c9edf7be5a2918144ff4ea32",
"reference": "f3ad69181b8afed2c9edf7be5a2918144ff4ea32",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/18634df356bfd4119fe3d6156bdb990c414c14ea",
"reference": "18634df356bfd4119fe3d6156bdb990c414c14ea",
"shasum": "",
"mirrors": [
{
@ -114,7 +114,7 @@
"spatie/flysystem-dropbox": "Allows you to use Dropbox storage",
"srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications"
},
"time": "2021-06-23T21:56:05+00:00",
"time": "2021-08-17T13:49:42+00:00",
"type": "library",
"extra": {
"branch-alias": {
@ -159,7 +159,7 @@
],
"support": {
"issues": "https://github.com/thephpleague/flysystem/issues",
"source": "https://github.com/thephpleague/flysystem/tree/1.1.4"
"source": "https://github.com/thephpleague/flysystem/tree/1.1.5"
},
"funding": [
{
@ -227,17 +227,17 @@
},
{
"name": "league/mime-type-detection",
"version": "1.7.0",
"version_normalized": "1.7.0.0",
"version": "1.8.0",
"version_normalized": "1.8.0.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/mime-type-detection.git",
"reference": "3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3"
"reference": "b38b25d7b372e9fddb00335400467b223349fd7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3",
"reference": "3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3",
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/b38b25d7b372e9fddb00335400467b223349fd7e",
"reference": "b38b25d7b372e9fddb00335400467b223349fd7e",
"shasum": "",
"mirrors": [
{
@ -255,7 +255,7 @@
"phpstan/phpstan": "^0.12.68",
"phpunit/phpunit": "^8.5.8 || ^9.3"
},
"time": "2021-01-18T20:58:21+00:00",
"time": "2021-09-25T08:23:19+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -276,7 +276,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.7.0"
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.8.0"
},
"funding": [
{
@ -345,17 +345,17 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.5.0",
"version_normalized": "6.5.0.0",
"version": "v6.5.1",
"version_normalized": "6.5.1.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c"
"reference": "dd803df5ad7492e1b40637f7ebd258fee5ca7355"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/a5b5c43e50b7fba655f793ad27303cd74c57363c",
"reference": "a5b5c43e50b7fba655f793ad27303cd74c57363c",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/dd803df5ad7492e1b40637f7ebd258fee5ca7355",
"reference": "dd803df5ad7492e1b40637f7ebd258fee5ca7355",
"shasum": "",
"mirrors": [
{
@ -373,10 +373,12 @@
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"doctrine/annotations": "^1.2",
"php-parallel-lint/php-console-highlighter": "^0.5.0",
"php-parallel-lint/php-parallel-lint": "^1.3",
"phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.5.6",
"yoast/phpunit-polyfills": "^0.2.0"
"squizlabs/php_codesniffer": "^3.6.0",
"yoast/phpunit-polyfills": "^1.0.0"
},
"suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
@ -386,7 +388,7 @@
"stevenmaguire/oauth2-microsoft": "Needed for Microsoft XOAUTH2 authentication",
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)"
},
"time": "2021-06-16T14:33:43+00:00",
"time": "2021-08-18T09:14:16+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -418,7 +420,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.5.0"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.5.1"
},
"funding": [
{
@ -924,17 +926,17 @@
},
{
"name": "symfony/var-dumper",
"version": "v4.4.27",
"version_normalized": "4.4.27.0",
"version": "v4.4.33",
"version_normalized": "4.4.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "391d6d0e7a06ab54eb7c38fab29b8d174471b3ba"
"reference": "50286e2b7189bfb4f419c0731e86632cddf7c5ee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/391d6d0e7a06ab54eb7c38fab29b8d174471b3ba",
"reference": "391d6d0e7a06ab54eb7c38fab29b8d174471b3ba",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/50286e2b7189bfb4f419c0731e86632cddf7c5ee",
"reference": "50286e2b7189bfb4f419c0731e86632cddf7c5ee",
"shasum": "",
"mirrors": [
{
@ -964,7 +966,7 @@
"ext-intl": "To show region name in time zone dump",
"symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
},
"time": "2021-07-23T15:41:52+00:00",
"time": "2021-10-25T20:24:58+00:00",
"bin": [
"Resources/bin/var-dump-server"
],
@ -1002,7 +1004,7 @@
"dump"
],
"support": {
"source": "https://github.com/symfony/var-dumper/tree/v4.4.27"
"source": "https://github.com/symfony/var-dumper/tree/v4.4.33"
},
"funding": [
{
@ -1020,6 +1022,71 @@
],
"install-path": "../symfony/var-dumper"
},
{
"name": "taoser/think-addons",
"version": "v1.0.1",
"version_normalized": "1.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/taoser/think-addons.git",
"reference": "bd8b0bfa4543fe8d2da65355c134250f78c0d457"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/taoser/think-addons/zipball/bd8b0bfa4543fe8d2da65355c134250f78c0d457",
"reference": "bd8b0bfa4543fe8d2da65355c134250f78c0d457",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.1.0",
"topthink/framework": "^6.0",
"topthink/think-helper": "^3.0.0",
"topthink/think-view": "^1.0"
},
"time": "2021-09-18T08:41:10+00:00",
"type": "library",
"extra": {
"think": {
"services": [
"taoser\\addons\\Service"
],
"config": {
"addons": "src/config.php"
}
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"taoser\\": "src/"
},
"files": [
"src/helper.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"mit"
],
"authors": [
{
"name": "taoler",
"email": "changlin_zhao@qq.com"
}
],
"description": "The ThinkPHP6 Addons Package",
"support": {
"issues": "https://github.com/taoser/think-addons/issues",
"source": "https://github.com/taoser/think-addons/tree/v1.0.1"
},
"install-path": "../taoser/think-addons"
},
{
"name": "taoser/think-auth",
"version": "v1.0.0",
@ -1584,67 +1651,6 @@
"source": "https://github.com/wamkj/thinkphp6.0-databackup/tree/v1.0"
},
"install-path": "../wamkj/thinkphp6.0-databackup"
},
{
"name": "zzstudio/think-addons",
"version": "2.0.5",
"version_normalized": "2.0.5.0",
"source": {
"type": "git",
"url": "https://github.com/zz-studio/think-addons.git",
"reference": "7eb740cb219a111d593a05ad88248a74f640fe5c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zz-studio/think-addons/zipball/7eb740cb219a111d593a05ad88248a74f640fe5c",
"reference": "7eb740cb219a111d593a05ad88248a74f640fe5c",
"shasum": "",
"mirrors": [
{
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
"preferred": true
}
]
},
"require": {
"php": ">=7.1.0",
"topthink/framework": "^6.0",
"topthink/think-helper": "^3.0.0",
"topthink/think-view": "^1.0"
},
"time": "2020-01-06T06:42:39+00:00",
"type": "library",
"extra": {
"think": {
"services": [
"think\\addons\\Service"
],
"config": {
"addons": "src/config.php"
}
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"think\\": "src/"
},
"files": [
"src/helper.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "byron",
"email": "xiaobo.sun@qq.com"
}
],
"description": "The ThinkPHP6 Addons Package",
"install-path": "../zzstudio/think-addons"
}
],
"dev": true

View File

@ -22,12 +22,12 @@
),
'league/flysystem' =>
array (
'pretty_version' => '1.1.4',
'version' => '1.1.4.0',
'pretty_version' => '1.1.5',
'version' => '1.1.5.0',
'aliases' =>
array (
),
'reference' => 'f3ad69181b8afed2c9edf7be5a2918144ff4ea32',
'reference' => '18634df356bfd4119fe3d6156bdb990c414c14ea',
),
'league/flysystem-cached-adapter' =>
array (
@ -40,12 +40,12 @@
),
'league/mime-type-detection' =>
array (
'pretty_version' => '1.7.0',
'version' => '1.7.0.0',
'pretty_version' => '1.8.0',
'version' => '1.8.0.0',
'aliases' =>
array (
),
'reference' => '3b9dff8aaf7323590c1d2e443db701eb1f9aa0d3',
'reference' => 'b38b25d7b372e9fddb00335400467b223349fd7e',
),
'lotofbadcode/phpspirit_databackup' =>
array (
@ -58,12 +58,12 @@
),
'phpmailer/phpmailer' =>
array (
'pretty_version' => 'v6.5.0',
'version' => '6.5.0.0',
'pretty_version' => 'v6.5.1',
'version' => '6.5.1.0',
'aliases' =>
array (
),
'reference' => 'a5b5c43e50b7fba655f793ad27303cd74c57363c',
'reference' => 'dd803df5ad7492e1b40637f7ebd258fee5ca7355',
),
'psr/cache' =>
array (
@ -130,12 +130,12 @@
),
'symfony/var-dumper' =>
array (
'pretty_version' => 'v4.4.27',
'version' => '4.4.27.0',
'pretty_version' => 'v4.4.33',
'version' => '4.4.33.0',
'aliases' =>
array (
),
'reference' => '391d6d0e7a06ab54eb7c38fab29b8d174471b3ba',
'reference' => '50286e2b7189bfb4f419c0731e86632cddf7c5ee',
),
'taoser/taoler' =>
array (
@ -146,6 +146,15 @@
),
'reference' => NULL,
),
'taoser/think-addons' =>
array (
'pretty_version' => 'v1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => 'bd8b0bfa4543fe8d2da65355c134250f78c0d457',
),
'taoser/think-auth' =>
array (
'pretty_version' => 'v1.0.0',
@ -236,14 +245,5 @@
),
'reference' => '28a0e406d827132942723a3c9f69bb20c98e652f',
),
'zzstudio/think-addons' =>
array (
'pretty_version' => '2.0.5',
'version' => '2.0.5.0',
'aliases' =>
array (
),
'reference' => '7eb740cb219a111d593a05ad88248a74f640fe5c',
),
),
);

View File

@ -160,7 +160,7 @@ class Ftp extends AbstractFtpAdapter
{
if ($this->utf8) {
$response = ftp_raw($this->connection, "OPTS UTF8 ON");
if (substr($response[0], 0, 3) !== '200') {
if (!in_array(substr($response[0], 0, 3), ['200', '202'])) {
throw new ConnectionRuntimeException(
'Could not set UTF-8 mode for connection: ' . $this->getHost() . '::' . $this->getPort()
);

View File

@ -1,5 +1,11 @@
# Changelog
## 1.8.0 - 2021-09-25
### Added
- Added the decorator `OverridingExtensionToMimeTypeMap` which allows you to override values.
## 1.7.0 - 2021-01-18
### Added

View File

@ -45,6 +45,7 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'air' => 'application/vnd.adobe.air-application-installer-package+zip',
'ait' => 'application/vnd.dvb.ait',
'ami' => 'application/vnd.amiga.ami',
'amr' => 'audio/amr',
'apk' => 'application/vnd.android.package-archive',
'apng' => 'image/apng',
'appcache' => 'text/cache-manifest',
@ -265,6 +266,7 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'evy' => 'application/x-envoy',
'exe' => 'application/octet-stream',
'exi' => 'application/exi',
'exp' => 'application/express',
'exr' => 'image/aces',
'ext' => 'application/vnd.novadigm.ext',
'ez' => 'application/andrew-inset',
@ -351,8 +353,8 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'gv' => 'text/vnd.graphviz',
'gxf' => 'application/gxf',
'gxt' => 'application/vnd.geonext',
'gz' => 'application/x-gzip',
'gzip' => 'application/x-gzip',
'gz' => 'application/gzip',
'gzip' => 'application/gzip',
'h' => 'text/x-c',
'h261' => 'video/h261',
'h263' => 'video/h263',
@ -457,7 +459,7 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'karbon' => 'application/vnd.kde.karbon',
'kdb' => 'application/octet-stream',
'kdbx' => 'application/x-keepass2',
'key' => 'application/vnd.apple.keynote',
'key' => 'application/x-iwork-keynote-sffkey',
'kfo' => 'application/vnd.kde.kformula',
'kia' => 'application/vnd.kidspiration',
'kml' => 'application/vnd.google-earth.kml+xml',
@ -507,6 +509,7 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'm3u8' => 'application/vnd.apple.mpegurl',
'm4a' => 'audio/x-m4a',
'm4p' => 'application/mp4',
'm4s' => 'video/iso.segment',
'm4u' => 'application/vnd.mpegurl',
'm4v' => 'video/x-m4v',
'm13' => 'application/x-msmediaview',
@ -608,6 +611,7 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'musd' => 'application/mmt-usd+xml',
'musicxml' => 'application/vnd.recordare.musicxml+xml',
'mvb' => 'application/x-msmediaview',
'mvt' => 'application/vnd.mapbox-vector-tile',
'mwf' => 'application/vnd.mfer',
'mxf' => 'application/mxf',
'mxl' => 'application/vnd.recordare.musicxml',
@ -635,7 +639,7 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'nsf' => 'application/vnd.lotus-notes',
'nt' => 'application/n-triples',
'ntf' => 'application/vnd.nitf',
'numbers' => 'application/vnd.apple.numbers',
'numbers' => 'application/x-iwork-numbers-sffnumbers',
'nzb' => 'application/x-nzb',
'oa2' => 'application/vnd.fujitsu.oasys2',
'oa3' => 'application/vnd.fujitsu.oasys3',
@ -696,7 +700,7 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'p10' => 'application/x-pkcs10',
'p12' => 'application/x-pkcs12',
'pac' => 'application/x-ns-proxy-autoconfig',
'pages' => 'application/vnd.apple.pages',
'pages' => 'application/x-iwork-pages-sffpages',
'pas' => 'text/x-pascal',
'paw' => 'application/vnd.pawaafile',
'pbd' => 'application/vnd.powerbuilder6',
@ -921,6 +925,9 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'sti' => 'application/vnd.sun.xml.impress.template',
'stk' => 'application/hyperstudio',
'stl' => 'model/stl',
'stpx' => 'model/step+xml',
'stpxz' => 'model/step-xml+zip',
'stpz' => 'model/step+zip',
'str' => 'application/vnd.pg.format',
'stw' => 'application/vnd.sun.xml.writer.template',
'styl' => 'text/stylus',
@ -977,6 +984,7 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'tpt' => 'application/vnd.trid.tpt',
'tr' => 'text/troff',
'tra' => 'application/vnd.trueapp',
'trig' => 'application/trig',
'trm' => 'application/x-msterminal',
'ts' => 'video/mp2t',
'tsd' => 'application/timestamped-data',
@ -1047,6 +1055,7 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'vcs' => 'text/x-vcalendar',
'vcx' => 'application/vnd.vcx',
'vdi' => 'application/x-virtualbox-vdi',
'vds' => 'model/vnd.sap.vds',
'vhd' => 'application/x-virtualbox-vhd',
'vis' => 'application/vnd.visionary',
'viv' => 'video/vnd.vivo',
@ -1136,7 +1145,7 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'xdw' => 'application/vnd.fujixerox.docuworks',
'xel' => 'application/xcap-el+xml',
'xenc' => 'application/xenc+xml',
'xer' => 'application/xcap-error+xml',
'xer' => 'application/patch-ops-error+xml',
'xfdf' => 'application/vnd.adobe.xfdf',
'xfdl' => 'application/vnd.xfdl',
'xht' => 'application/xhtml+xml',
@ -1195,7 +1204,7 @@ class GeneratedExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
'z7' => 'application/x-zmachine',
'z8' => 'application/x-zmachine',
'zaz' => 'application/vnd.zzazz.deck+xml',
'zip' => 'application/x-zip',
'zip' => 'application/zip',
'zir' => 'application/vnd.zul',
'zirz' => 'application/vnd.zul',
'zmm' => 'application/vnd.handheld-entertainment+xml',

View File

@ -0,0 +1,30 @@
<?php
namespace League\MimeTypeDetection;
class OverridingExtensionToMimeTypeMap implements ExtensionToMimeTypeMap
{
/**
* @var ExtensionToMimeTypeMap
*/
private $innerMap;
/**
* @var string[]
*/
private $overrides;
/**
* @param array<string, string> $overrides
*/
public function __construct(ExtensionToMimeTypeMap $innerMap, array $overrides)
{
$this->innerMap = $innerMap;
$this->overrides = $overrides;
}
public function lookupMimeType(string $extension): ?string
{
return $this->overrides[$extension] ?? $this->innerMap->lookupMimeType($extension);
}
}

View File

@ -2,7 +2,12 @@
# PHPMailer A full-featured email creation and transfer class for PHP
[![Test status](https://github.com/PHPMailer/PHPMailer/workflows/Tests/badge.svg)](https://github.com/PHPMailer/PHPMailer/actions) [![Latest Stable Version](https://poser.pugx.org/phpmailer/phpmailer/v/stable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![Total Downloads](https://poser.pugx.org/phpmailer/phpmailer/downloads)](https://packagist.org/packages/phpmailer/phpmailer) [![License](https://poser.pugx.org/phpmailer/phpmailer/license.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![API Docs](https://github.com/phpmailer/phpmailer/workflows/Docs/badge.svg)](https://phpmailer.github.io/PHPMailer/)
[![Test status](https://github.com/PHPMailer/PHPMailer/workflows/Tests/badge.svg)](https://github.com/PHPMailer/PHPMailer/actions)
[![codecov.io](https://codecov.io/gh/PHPMailer/PHPMailer/branch/master/graph/badge.svg?token=iORZpwmYmM)](https://codecov.io/gh/PHPMailer/PHPMailer)
[![Latest Stable Version](https://poser.pugx.org/phpmailer/phpmailer/v/stable.svg)](https://packagist.org/packages/phpmailer/phpmailer)
[![Total Downloads](https://poser.pugx.org/phpmailer/phpmailer/downloads)](https://packagist.org/packages/phpmailer/phpmailer)
[![License](https://poser.pugx.org/phpmailer/phpmailer/license.svg)](https://packagist.org/packages/phpmailer/phpmailer)
[![API Docs](https://github.com/phpmailer/phpmailer/workflows/Docs/badge.svg)](https://phpmailer.github.io/PHPMailer/)
## Features
- Probably the world's most popular code for sending email from PHP!
@ -17,7 +22,7 @@
- Protects against header injection attacks
- Error messages in over 50 languages!
- DKIM and S/MIME signing support
- Compatible with PHP 5.5 and later, including PHP 8.0
- Compatible with PHP 5.5 and later, including PHP 8.1
- Namespaced to prevent name clashes
- Much more!
@ -39,7 +44,7 @@ This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lg
PHPMailer is available on [Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), and installation via [Composer](https://getcomposer.org) is the recommended way to install PHPMailer. Just add this line to your `composer.json` file:
```json
"phpmailer/phpmailer": "^6.2"
"phpmailer/phpmailer": "^6.5"
```
or run
@ -89,7 +94,7 @@ use PHPMailer\PHPMailer\Exception;
//Load Composer's autoloader
require 'vendor/autoload.php';
//Instantiation and passing `true` enables exceptions
//Create an instance; passing `true` enables exceptions
$mail = new PHPMailer(true);
try {
@ -100,8 +105,8 @@ try {
$mail->SMTPAuth = true; //Enable SMTP authentication
$mail->Username = 'user@example.com'; //SMTP username
$mail->Password = 'secret'; //SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; //Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
$mail->Port = 587; //TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption
$mail->Port = 465; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
//Recipients
$mail->setFrom('from@example.com', 'Mailer');

View File

@ -1 +1 @@
6.5.0
6.5.1

View File

@ -34,10 +34,12 @@
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"doctrine/annotations": "^1.2",
"php-parallel-lint/php-console-highlighter": "^0.5.0",
"php-parallel-lint/php-parallel-lint": "^1.3",
"phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.5.6",
"yoast/phpunit-polyfills": "^0.2.0"
"squizlabs/php_codesniffer": "^3.6.0",
"yoast/phpunit-polyfills": "^1.0.0"
},
"suggest": {
"ext-mbstring": "Needed to send email in multibyte encoding charset or decode encoded addresses",
@ -60,6 +62,10 @@
"license": "LGPL-2.1-only",
"scripts": {
"check": "./vendor/bin/phpcs",
"test": "./vendor/bin/phpunit"
"test": "./vendor/bin/phpunit --no-coverage",
"coverage": "./vendor/bin/phpunit",
"lint": [
"@php ./vendor/php-parallel-lint/php-parallel-lint/parallel-lint . -e php,phps --exclude vendor --exclude .git --exclude build"
]
}
}

View File

@ -5,24 +5,25 @@
* @package PHPMailer
* @author Mitsuhiro Yoshida <http://mitstek.com/>
* @author Yoshi Sakai <http://bluemooninc.jp/>
* @author Arisophy <https://github.com/arisophy/>
*/
$PHPMAILER_LANG['authenticate'] = 'SMTPエラー: 認証できませんでした。';
$PHPMAILER_LANG['connect_host'] = 'SMTPエラー: SMTPホストに接続できませんでした。';
$PHPMAILER_LANG['data_not_accepted'] = 'SMTPエラー: データが受け付けられませんでした。';
//$PHPMAILER_LANG['empty_message'] = 'Message body empty';
$PHPMAILER_LANG['empty_message'] = 'メール本文が空です。';
$PHPMAILER_LANG['encoding'] = '不明なエンコーディング: ';
$PHPMAILER_LANG['execute'] = '実行できませんでした: ';
$PHPMAILER_LANG['file_access'] = 'ファイルにアクセスできません: ';
$PHPMAILER_LANG['file_open'] = 'ファイルエラー: ファイルを開けません: ';
$PHPMAILER_LANG['from_failed'] = 'Fromアドレスを登録する際にエラーが発生しました: ';
$PHPMAILER_LANG['instantiate'] = 'メール関数が正常に動作しませんでした。';
//$PHPMAILER_LANG['invalid_address'] = 'Invalid address: ';
$PHPMAILER_LANG['invalid_address'] = '不正なメールアドレス: ';
$PHPMAILER_LANG['provide_address'] = '少なくとも1つメールアドレスを 指定する必要があります。';
$PHPMAILER_LANG['mailer_not_supported'] = ' メーラーがサポートされていません。';
$PHPMAILER_LANG['recipients_failed'] = 'SMTPエラー: 次の受信者アドレスに 間違いがあります: ';
//$PHPMAILER_LANG['signing'] = 'Signing Error: ';
//$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
//$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
//$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
//$PHPMAILER_LANG['extension_missing'] = 'Extension missing: ';
$PHPMAILER_LANG['signing'] = '署名エラー: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP接続に失敗しました。';
$PHPMAILER_LANG['smtp_error'] = 'SMTPサーバーエラー: ';
$PHPMAILER_LANG['variable_set'] = '変数が存在しません: ';
$PHPMAILER_LANG['extension_missing'] = '拡張機能が見つかりません: ';

View File

@ -7,23 +7,28 @@
*/
$PHPMAILER_LANG['authenticate'] = 'SMTP-fout: authenticatie mislukt.';
$PHPMAILER_LANG['buggy_php'] = 'PHP versie gededecteerd die onderhavig is aan een bug die kan resulteren in gecorrumpeerde berichten. Om dit te voorkomen, gebruik SMTP voor het verzenden van berichten, zet de mail.add_x_header optie in uw php.ini file uit, gebruik MacOS of Linux, of pas de gebruikte PHP versie aan naar versie 7.0.17+ or 7.1.3+.';
$PHPMAILER_LANG['connect_host'] = 'SMTP-fout: kon niet verbinden met SMTP-host.';
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP-fout: data niet geaccepteerd.';
$PHPMAILER_LANG['empty_message'] = 'Berichttekst is leeg';
$PHPMAILER_LANG['encoding'] = 'Onbekende codering: ';
$PHPMAILER_LANG['execute'] = 'Kon niet uitvoeren: ';
$PHPMAILER_LANG['extension_missing'] = 'Extensie afwezig: ';
$PHPMAILER_LANG['file_access'] = 'Kreeg geen toegang tot bestand: ';
$PHPMAILER_LANG['file_open'] = 'Bestandsfout: kon bestand niet openen: ';
$PHPMAILER_LANG['from_failed'] = 'Het volgende afzendersadres is mislukt: ';
$PHPMAILER_LANG['instantiate'] = 'Kon mailfunctie niet initialiseren.';
$PHPMAILER_LANG['invalid_address'] = 'Ongeldig adres: ';
$PHPMAILER_LANG['invalid_header'] = 'Ongeldige header naam of waarde';
$PHPMAILER_LANG['invalid_hostentry'] = 'Ongeldige hostentry: ';
$PHPMAILER_LANG['invalid_host'] = 'Ongeldige host: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer wordt niet ondersteund.';
$PHPMAILER_LANG['provide_address'] = 'Er moet minstens één ontvanger worden opgegeven.';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP-fout: de volgende ontvangers zijn mislukt: ';
$PHPMAILER_LANG['signing'] = 'Signeerfout: ';
$PHPMAILER_LANG['smtp_code'] = 'SMTP code: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Aanvullende SMTP informatie: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Verbinding mislukt.';
$PHPMAILER_LANG['smtp_detail'] = 'Detail: ';
$PHPMAILER_LANG['smtp_error'] = 'SMTP-serverfout: ';
$PHPMAILER_LANG['variable_set'] = 'Kan de volgende variabele niet instellen of resetten: ';
$PHPMAILER_LANG['extension_missing'] = 'Extensie afwezig: ';

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.5/phpunit.xsd"
backupGlobals="true"
bootstrap="vendor/autoload.php"
verbose="true"
colors="true"
forceCoversAnnotation="false"
>
<testsuites>
<testsuite name="PHPMailerTests">
<directory>./test/</directory>
</testsuite>
</testsuites>
<listeners>
<listener class="PHPMailer\Test\DebugLogTestListener" />
</listeners>
<groups>
<exclude>
<group>languages</group>
<group>pop3</group>
</exclude>
</groups>
<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./src</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-text" target="php://stdout" showUncoveredFiles="true"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
<log type="junit" target="build/logs/junit.xml"/>
</logging>
</phpunit>

View File

@ -35,6 +35,6 @@ class Exception extends \Exception
*/
public function errorMessage()
{
return '<strong>' . htmlspecialchars($this->getMessage()) . "</strong><br />\n";
return '<strong>' . htmlspecialchars($this->getMessage(), ENT_COMPAT | ENT_HTML401) . "</strong><br />\n";
}
}

View File

@ -103,14 +103,14 @@ class PHPMailer
*
* @var string
*/
public $From = 'root@localhost';
public $From = '';
/**
* The From name of the message.
*
* @var string
*/
public $FromName = 'Root User';
public $FromName = '';
/**
* The envelope sender of the message.
@ -689,7 +689,7 @@ class PHPMailer
protected $boundary = [];
/**
* The array of available languages.
* The array of available text strings for the current language.
*
* @var array
*/
@ -750,7 +750,7 @@ class PHPMailer
*
* @var string
*/
const VERSION = '6.5.0';
const VERSION = '6.5.1';
/**
* Error severity: message only, continue processing.
@ -1188,25 +1188,33 @@ class PHPMailer
*
* @return array
*/
public static function parseAddresses($addrstr, $useimap = true)
public static function parseAddresses($addrstr, $useimap = true, $charset = self::CHARSET_ISO88591)
{
$addresses = [];
if ($useimap && function_exists('imap_rfc822_parse_adrlist')) {
//Use this built-in parser if it's available
$list = imap_rfc822_parse_adrlist($addrstr, '');
// Clear any potential IMAP errors to get rid of notices being thrown at end of script.
imap_errors();
foreach ($list as $address) {
if (
('.SYNTAX-ERROR.' !== $address->host) && static::validateAddress(
$address->mailbox . '@' . $address->host
)
'.SYNTAX-ERROR.' !== $address->host &&
static::validateAddress($address->mailbox . '@' . $address->host)
) {
//Decode the name part if it's present and encoded
if (
property_exists($address, 'personal') &&
extension_loaded('mbstring') &&
preg_match('/^=\?.*\?=$/', $address->personal)
//Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled
defined('MB_CASE_UPPER') &&
preg_match('/^=\?.*\?=$/s', $address->personal)
) {
$origCharset = mb_internal_encoding();
mb_internal_encoding($charset);
//Undo any RFC2047-encoded spaces-as-underscores
$address->personal = str_replace('_', '=20', $address->personal);
//Decode the name
$address->personal = mb_decode_mimeheader($address->personal);
mb_internal_encoding($origCharset);
}
$addresses[] = [
@ -1234,9 +1242,16 @@ class PHPMailer
$email = trim(str_replace('>', '', $email));
$name = trim($name);
if (static::validateAddress($email)) {
//Check for a Mbstring constant rather than using extension_loaded, which is sometimes disabled
//If this name is encoded, decode it
if (preg_match('/^=\?.*\?=$/', $name)) {
if (defined('MB_CASE_UPPER') && preg_match('/^=\?.*\?=$/s', $name)) {
$origCharset = mb_internal_encoding();
mb_internal_encoding($charset);
//Undo any RFC2047-encoded spaces-as-underscores
$name = str_replace('_', '=20', $name);
//Decode the name
$name = mb_decode_mimeheader($name);
mb_internal_encoding($origCharset);
}
$addresses[] = [
//Remove any surrounding quotes and spaces from the name
@ -1508,12 +1523,7 @@ class PHPMailer
&& ini_get('mail.add_x_header') === '1'
&& stripos(PHP_OS, 'WIN') === 0
) {
trigger_error(
'Your version of PHP is affected by a bug that may result in corrupted messages.' .
' To fix it, switch to sending using SMTP, disable the mail.add_x_header option in' .
' your php.ini, switch to MacOS or Linux, or upgrade your PHP to version 7.0.17+ or 7.1.3+.',
E_USER_WARNING
);
trigger_error($this->lang('buggy_php'), E_USER_WARNING);
}
try {
@ -1724,7 +1734,7 @@ class PHPMailer
fwrite($mail, $header);
fwrite($mail, $body);
$result = pclose($mail);
$addrinfo = static::parseAddresses($toAddr);
$addrinfo = static::parseAddresses($toAddr, true, $this->charSet);
$this->doCallback(
($result === 0),
[[$addrinfo['address'], $addrinfo['name']]],
@ -1884,7 +1894,7 @@ class PHPMailer
if ($this->SingleTo && count($toArr) > 1) {
foreach ($toArr as $toAddr) {
$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
$addrinfo = static::parseAddresses($toAddr);
$addrinfo = static::parseAddresses($toAddr, true, $this->charSet);
$this->doCallback(
$result,
[[$addrinfo['address'], $addrinfo['name']]],
@ -2181,14 +2191,15 @@ class PHPMailer
/**
* Set the language for error messages.
* Returns false if it cannot load the language file.
* The default language is English.
*
* @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
* Optionally, the language code can be enhanced with a 4-character
* script annotation and/or a 2-character country annotation.
* @param string $lang_path Path to the language file directory, with trailing separator (slash).D
* Do not set this from user input!
*
* @return bool
* @return bool Returns true if the requested language was loaded, false otherwise.
*/
public function setLanguage($langcode = 'en', $lang_path = '')
{
@ -2211,44 +2222,77 @@ class PHPMailer
//Define full set of translatable strings in English
$PHPMAILER_LANG = [
'authenticate' => 'SMTP Error: Could not authenticate.',
'buggy_php' => 'Your version of PHP is affected by a bug that may result in corrupted messages.' .
' To fix it, switch to sending using SMTP, disable the mail.add_x_header option in' .
' your php.ini, switch to MacOS or Linux, or upgrade your PHP to version 7.0.17+ or 7.1.3+.',
'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
'data_not_accepted' => 'SMTP Error: data not accepted.',
'empty_message' => 'Message body empty',
'encoding' => 'Unknown encoding: ',
'execute' => 'Could not execute: ',
'extension_missing' => 'Extension missing: ',
'file_access' => 'Could not access file: ',
'file_open' => 'File Error: Could not open file: ',
'from_failed' => 'The following From address failed: ',
'instantiate' => 'Could not instantiate mail function.',
'invalid_address' => 'Invalid address: ',
'invalid_header' => 'Invalid header name or value',
'invalid_hostentry' => 'Invalid hostentry: ',
'invalid_host' => 'Invalid host: ',
'mailer_not_supported' => ' mailer is not supported.',
'provide_address' => 'You must provide at least one recipient email address.',
'recipients_failed' => 'SMTP Error: The following recipients failed: ',
'signing' => 'Signing Error: ',
'smtp_code' => 'SMTP code: ',
'smtp_code_ex' => 'Additional SMTP info: ',
'smtp_connect_failed' => 'SMTP connect() failed.',
'smtp_detail' => 'Detail: ',
'smtp_error' => 'SMTP server error: ',
'variable_set' => 'Cannot set or reset variable: ',
'extension_missing' => 'Extension missing: ',
];
if (empty($lang_path)) {
//Calculate an absolute path so it can work if CWD is not here
$lang_path = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR;
}
//Validate $langcode
if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $langcode)) {
$foundlang = true;
$langcode = strtolower($langcode);
if (
!preg_match('/^(?P<lang>[a-z]{2})(?P<script>_[a-z]{4})?(?P<country>_[a-z]{2})?$/', $langcode, $matches)
&& $langcode !== 'en'
) {
$foundlang = false;
$langcode = 'en';
}
$foundlang = true;
$lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
//There is no English translation file
if ('en' !== $langcode) {
//Make sure language file path is readable
if (!static::fileIsAccessible($lang_file)) {
$langcodes = [];
if (!empty($matches['script']) && !empty($matches['country'])) {
$langcodes[] = $matches['lang'] . $matches['script'] . $matches['country'];
}
if (!empty($matches['country'])) {
$langcodes[] = $matches['lang'] . $matches['country'];
}
if (!empty($matches['script'])) {
$langcodes[] = $matches['lang'] . $matches['script'];
}
$langcodes[] = $matches['lang'];
//Try and find a readable language file for the requested language.
$foundFile = false;
foreach ($langcodes as $code) {
$lang_file = $lang_path . 'phpmailer.lang-' . $code . '.php';
if (static::fileIsAccessible($lang_file)) {
$foundFile = true;
break;
}
}
if ($foundFile === false) {
$foundlang = false;
} else {
//$foundlang = include $lang_file;
$lines = file($lang_file);
foreach ($lines as $line) {
//Translation file lines look like this:
@ -2283,6 +2327,10 @@ class PHPMailer
*/
public function getTranslations()
{
if (empty($this->language)) {
$this->setLanguage(); // Set the default language.
}
return $this->language;
}
@ -2551,7 +2599,17 @@ class PHPMailer
//Only allow a custom message ID if it conforms to RFC 5322 section 3.6.4
//https://tools.ietf.org/html/rfc5322#section-3.6.4
if ('' !== $this->MessageID && preg_match('/^<.*@.*>$/', $this->MessageID)) {
if (
'' !== $this->MessageID &&
preg_match(
'/^<((([a-z\d!#$%&\'*+\/=?^_`{|}~-]+(\.[a-z\d!#$%&\'*+\/=?^_`{|}~-]+)*)' .
'|("(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]|[\x21\x23-\x5B\x5D-\x7E])' .
'|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*"))@(([a-z\d!#$%&\'*+\/=?^_`{|}~-]+' .
'(\.[a-z\d!#$%&\'*+\/=?^_`{|}~-]+)*)|(\[(([\x01-\x08\x0B\x0C\x0E-\x1F\x7F]' .
'|[\x21-\x5A\x5E-\x7E])|(\\[\x01-\x09\x0B\x0C\x0E-\x7F]))*\])))>$/Di',
$this->MessageID
)
) {
$this->lastMessageID = $this->MessageID;
} else {
$this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname());
@ -3935,13 +3993,13 @@ class PHPMailer
if (!empty($lasterror['error'])) {
$msg .= $this->lang('smtp_error') . $lasterror['error'];
if (!empty($lasterror['detail'])) {
$msg .= ' Detail: ' . $lasterror['detail'];
$msg .= ' ' . $this->lang('smtp_detail') . $lasterror['detail'];
}
if (!empty($lasterror['smtp_code'])) {
$msg .= ' SMTP code: ' . $lasterror['smtp_code'];
$msg .= ' ' . $this->lang('smtp_code') . $lasterror['smtp_code'];
}
if (!empty($lasterror['smtp_code_ex'])) {
$msg .= ' Additional SMTP info: ' . $lasterror['smtp_code_ex'];
$msg .= ' ' . $this->lang('smtp_code_ex') . $lasterror['smtp_code_ex'];
}
}
}
@ -4002,7 +4060,7 @@ class PHPMailer
empty($host)
|| !is_string($host)
|| strlen($host) > 256
|| !preg_match('/^([a-zA-Z\d.-]*|\[[a-fA-F\d:]+])$/', $host)
|| !preg_match('/^([a-zA-Z\d.-]*|\[[a-fA-F\d:]+\])$/', $host)
) {
return false;
}
@ -4079,11 +4137,11 @@ class PHPMailer
list($name, $value) = explode(':', $name, 2);
}
$name = trim($name);
$value = trim($value);
$value = (null === $value) ? '' : trim($value);
//Ensure name is not empty, and that neither name nor value contain line breaks
if (empty($name) || strpbrk($name . $value, "\r\n") !== false) {
if ($this->exceptions) {
throw new Exception('Invalid header name or value');
throw new Exception($this->lang('invalid_header'));
}
return false;
@ -4237,7 +4295,8 @@ class PHPMailer
*
* @param string $html The HTML text to convert
* @param bool|callable $advanced Any boolean value to use the internal converter,
* or provide your own callable for custom conversion
* or provide your own callable for custom conversion.
* *Never* pass user-supplied data into this parameter
*
* @return string
*/

View File

@ -46,7 +46,7 @@ class POP3
*
* @var string
*/
const VERSION = '6.5.0';
const VERSION = '6.5.1';
/**
* Default POP3 port number.

View File

@ -35,7 +35,7 @@ class SMTP
*
* @var string
*/
const VERSION = '6.5.0';
const VERSION = '6.5.1';
/**
* SMTP line break constant.

10
vendor/services.php vendored
View File

@ -1,9 +1,9 @@
<?php
// This file is automatically generated at:2021-08-04 18:41:10
// This file is automatically generated at:2021-11-02 14:10:33
declare (strict_types = 1);
return array (
0 => 'think\\captcha\\CaptchaService',
1 => 'think\\app\\Service',
2 => 'think\\trace\\Service',
3 => 'think\\addons\\Service',
0 => 'taoser\\addons\\Service',
1 => 'think\\captcha\\CaptchaService',
2 => 'think\\app\\Service',
3 => 'think\\trace\\Service',
);

View File

@ -214,18 +214,24 @@ class ExceptionCaster
if (file_exists($f['file']) && 0 <= self::$srcContext) {
if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) {
$template = $f['object'] ?? unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class']));
$ellipsis = 0;
$templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');
$templateInfo = $template->getDebugInfo();
if (isset($templateInfo[$f['line']])) {
if (!method_exists($template, 'getSourceContext') || !file_exists($templatePath = $template->getSourceContext()->getPath())) {
$templatePath = null;
}
if ($templateSrc) {
$src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f);
$srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']];
$template = null;
if (isset($f['object'])) {
$template = $f['object'];
} elseif ((new \ReflectionClass($f['class']))->isInstantiable()) {
$template = unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class']));
}
if (null !== $template) {
$ellipsis = 0;
$templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : '');
$templateInfo = $template->getDebugInfo();
if (isset($templateInfo[$f['line']])) {
if (!method_exists($template, 'getSourceContext') || !file_exists($templatePath = $template->getSourceContext()->getPath())) {
$templatePath = null;
}
if ($templateSrc) {
$src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f);
$srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']];
}
}
}
}

View File

@ -356,6 +356,8 @@ class ReflectionCaster
$signature .= 10 > \strlen($v) && !str_contains($v, '\\') ? "'{$v}'" : "'…".\strlen($v)."'";
} elseif (\is_bool($v)) {
$signature .= $v ? 'true' : 'false';
} elseif (\is_object($v)) {
$signature .= 'new '.substr(strrchr('\\'.get_debug_type($v), '\\'), 1);
} else {
$signature .= $v;
}

View File

@ -44,6 +44,22 @@ class XmlReaderCaster
public static function castXmlReader(\XMLReader $reader, array $a, Stub $stub, $isNested)
{
try {
$properties = [
'LOADDTD' => @$reader->getParserProperty(\XMLReader::LOADDTD),
'DEFAULTATTRS' => @$reader->getParserProperty(\XMLReader::DEFAULTATTRS),
'VALIDATE' => @$reader->getParserProperty(\XMLReader::VALIDATE),
'SUBST_ENTITIES' => @$reader->getParserProperty(\XMLReader::SUBST_ENTITIES),
];
} catch (\Error $e) {
$properties = [
'LOADDTD' => false,
'DEFAULTATTRS' => false,
'VALIDATE' => false,
'SUBST_ENTITIES' => false,
];
}
$props = Caster::PREFIX_VIRTUAL.'parserProperties';
$info = [
'localName' => $reader->localName,
@ -57,12 +73,7 @@ class XmlReaderCaster
'value' => $reader->value,
'namespaceURI' => $reader->namespaceURI,
'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI,
$props => [
'LOADDTD' => $reader->getParserProperty(\XMLReader::LOADDTD),
'DEFAULTATTRS' => $reader->getParserProperty(\XMLReader::DEFAULTATTRS),
'VALIDATE' => $reader->getParserProperty(\XMLReader::VALIDATE),
'SUBST_ENTITIES' => $reader->getParserProperty(\XMLReader::SUBST_ENTITIES),
],
$props => $properties,
];
if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, [], $count)) {

View File

@ -111,6 +111,7 @@ class Data implements \ArrayAccess, \Countable, \IteratorAggregate
/**
* @return int
*/
#[\ReturnTypeWillChange]
public function count()
{
return \count($this->getValue());
@ -119,6 +120,7 @@ class Data implements \ArrayAccess, \Countable, \IteratorAggregate
/**
* @return \Traversable
*/
#[\ReturnTypeWillChange]
public function getIterator()
{
if (!\is_array($value = $this->getValue())) {
@ -150,6 +152,7 @@ class Data implements \ArrayAccess, \Countable, \IteratorAggregate
/**
* @return bool
*/
#[\ReturnTypeWillChange]
public function offsetExists($key)
{
return $this->__isset($key);
@ -158,6 +161,7 @@ class Data implements \ArrayAccess, \Countable, \IteratorAggregate
/**
* @return mixed
*/
#[\ReturnTypeWillChange]
public function offsetGet($key)
{
return $this->__get($key);
@ -166,6 +170,7 @@ class Data implements \ArrayAccess, \Countable, \IteratorAggregate
/**
* @return void
*/
#[\ReturnTypeWillChange]
public function offsetSet($key, $value)
{
throw new \BadMethodCallException(self::class.' objects are immutable.');
@ -174,6 +179,7 @@ class Data implements \ArrayAccess, \Countable, \IteratorAggregate
/**
* @return void
*/
#[\ReturnTypeWillChange]
public function offsetUnset($key)
{
throw new \BadMethodCallException(self::class.' objects are immutable.');

View File

@ -82,29 +82,39 @@ class VarCloner extends AbstractCloner
// $v is the original value or a stub object in case of hard references
if (\PHP_VERSION_ID >= 70400) {
$zvalIsRef = null !== \ReflectionReference::fromArrayElement($vals, $k);
$zvalRef = ($r = \ReflectionReference::fromArrayElement($vals, $k)) ? $r->getId() : null;
} else {
$refs[$k] = $cookie;
$zvalIsRef = $vals[$k] === $cookie;
$zvalRef = $vals[$k] === $cookie;
}
if ($zvalIsRef) {
if ($zvalRef) {
$vals[$k] = &$stub; // Break hard references to make $queue completely
unset($stub); // independent from the original structure
if ($v instanceof Stub && isset($hardRefs[spl_object_id($v)])) {
$vals[$k] = $refs[$k] = $v;
if (\PHP_VERSION_ID >= 70400 ? null !== $vals[$k] = $hardRefs[$zvalRef] ?? null : $v instanceof Stub && isset($hardRefs[spl_object_id($v)])) {
if (\PHP_VERSION_ID >= 70400) {
$v = $vals[$k];
} else {
$refs[$k] = $vals[$k] = $v;
}
if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {
++$v->value->refCount;
}
++$v->refCount;
continue;
}
$refs[$k] = $vals[$k] = new Stub();
$refs[$k]->value = $v;
$h = spl_object_id($refs[$k]);
$hardRefs[$h] = &$refs[$k];
$values[$h] = $v;
$vals[$k] = new Stub();
$vals[$k]->value = $v;
$vals[$k]->handle = ++$refsCounter;
if (\PHP_VERSION_ID >= 70400) {
$hardRefs[$zvalRef] = $vals[$k];
} else {
$refs[$k] = $vals[$k];
$h = spl_object_id($refs[$k]);
$hardRefs[$h] = &$refs[$k];
$values[$h] = $v;
}
}
// Create $stub when the original value $v can not be used directly
// If $v is a nested structure, put that structure in array $a
@ -163,12 +173,17 @@ class VarCloner extends AbstractCloner
unset($v[$gid]);
$a = [];
foreach ($v as $gk => &$gv) {
if ($v === $gv) {
if ($v === $gv && (\PHP_VERSION_ID < 70400 || !isset($hardRefs[\ReflectionReference::fromArrayElement($v, $gk)->getId()]))) {
unset($v);
$v = new Stub();
$v->value = [$v->cut = \count($gv), Stub::TYPE_ARRAY => 0];
$v->handle = -1;
$gv = &$hardRefs[spl_object_id($v)];
if (\PHP_VERSION_ID >= 70400) {
$gv = &$a[$gk];
$hardRefs[\ReflectionReference::fromArrayElement($a, $gk)->getId()] = &$gv;
} else {
$gv = &$hardRefs[spl_object_id($v)];
}
$gv = $v;
}
@ -270,10 +285,12 @@ class VarCloner extends AbstractCloner
}
}
if ($zvalIsRef) {
$refs[$k]->value = $stub;
} else {
if (!$zvalRef) {
$vals[$k] = $stub;
} elseif (\PHP_VERSION_ID >= 70400) {
$hardRefs[$zvalRef]->value = $stub;
} else {
$refs[$k]->value = $stub;
}
}

View File

@ -3,7 +3,7 @@ VarDumper Component
The VarDumper component provides mechanisms for walking through any arbitrary
PHP variable. It provides a better `dump()` function that you can use instead
of `var_dump`.
of `var_dump()`.
Resources
---------

View File

@ -2,7 +2,7 @@
The ThinkPHP 6 Addons Package
## 安装
> composer require zzstudio/think-addons
> composer require taoser/think-addons
## 配置
@ -272,3 +272,8 @@ www WEB部署目录或者子目录
├─README.md README 文件
├─think 命令行入口文件
```
基于zzstudio修改版think-addons
The ThinkPHP 6 Addons Package
感谢 zzstudio/think-addons

View File

@ -1,11 +1,11 @@
{
"name": "zz-studio/think-addons",
"name": "taoser/think-addons",
"description": "The ThinkPHP6 Addons Package",
"license": "Apache-2.0",
"license": "mit",
"authors": [
{
"name": "byron",
"email": "xiaobo.sun@qq.com"
"name": "taoler",
"email": "changlin_zhao@qq.com"
}
],
"require": {
@ -16,7 +16,7 @@
},
"autoload": {
"psr-4": {
"think\\": "src/"
"taoser\\": "src/"
},
"files": [
"src/helper.php"
@ -25,7 +25,7 @@
"extra": {
"think": {
"services": [
"think\\addons\\Service"
"taoser\\addons\\Service"
],
"config":{
"addons": "src/config.php"

View File

@ -1,26 +1,8 @@
<?php
/**
* +----------------------------------------------------------------------
* | think-addons [thinkphp6]
* +----------------------------------------------------------------------
* .--, .--, | FILE: Addons.php
* ( ( \.---./ ) ) | AUTHOR: byron
* '.__/o o\__.' | EMAIL: xiaobo.sun@qq.com
* {= ^ =} | QQ: 150093589
* / \ | DATETIME: 2019/11/5 14:47
* // \\ |
* //| . |\\ |
* "'\ /'"_.-~^`'-. |
* \ _ /--' ` |
* ___)( )(___ |-----------------------------------------
* (((__) (__))) | 高山仰止,景行行止.虽不能至,心向往之。
* +----------------------------------------------------------------------
* | Copyright (c) 2019 http://www.zzstudio.net All rights reserved.
* +----------------------------------------------------------------------
*/
declare(strict_types=1);
namespace think;
namespace taoser;
use think\App;
use think\helper\Str;
@ -185,6 +167,23 @@ abstract class Addons
return $config;
}
/**
* 设置插件信息数据
* @param $name
* @param array $value
* @return array
*/
final public function setInfo($name = '', $value = [])
{
if (empty($name)) {
$name = $this->getName();
}
$info = $this->getInfo($name);
$info = array_merge($info, $value);
Config::set($info,$name);
return $info;
}
//必须实现安装
abstract public function install();

View File

@ -1,26 +1,8 @@
<?php
/**
* +----------------------------------------------------------------------
* | think-addons [thinkphp6]
* +----------------------------------------------------------------------
* .--, .--, | FILE: Route.php
* ( ( \.---./ ) ) | AUTHOR: byron
* '.__/o o\__.' | EMAIL: xiaobo.sun@qq.com
* {= ^ =} | QQ: 150093589
* / \ | DATETIME: 2019/11/5 09:57
* // \\ |
* //| . |\\ |
* "'\ /'"_.-~^`'-. |
* \ _ /--' ` |
* ___)( )(___ |-----------------------------------------
* (((__) (__))) | 高山仰止,景行行止.虽不能至,心向往之。
* +----------------------------------------------------------------------
* | Copyright (c) 2019 http://www.zzstudio.net All rights reserved.
* +----------------------------------------------------------------------
*/
declare(strict_types=1);
namespace think\addons;
namespace taoser\addons;
use think\helper\Str;
use think\facade\Event;

View File

@ -1,7 +1,7 @@
<?php
declare(strict_types=1);
namespace think\addons;
namespace taoser\addons;
use think\Route;
use think\helper\Str;
@ -9,7 +9,7 @@ use think\facade\Config;
use think\facade\Lang;
use think\facade\Cache;
use think\facade\Event;
use think\addons\middleware\Addons;
use taoser\addons\middleware\Addons;
/**
* 插件服务
@ -25,7 +25,7 @@ class Service extends \think\Service
$this->addons_path = $this->getAddonsPath();
// 加载系统语言包
Lang::load([
$this->app->getRootPath() . '/vendor/zzstudio/think-addons/src/lang/zh-cn.php'
$this->app->getRootPath() . '/vendor/taoser/think-addons/src/lang/zh-cn.php'
]);
// 自动载入插件
$this->autoload();
@ -41,7 +41,7 @@ class Service extends \think\Service
{
$this->registerRoutes(function (Route $route) {
// 路由脚本
$execute = '\\think\\addons\\Route::execute';
$execute = '\\taoser\\addons\\Route::execute';
// 注册插件公共中间件
if (is_file($this->app->addons->getAddonsPath() . 'middleware.php')) {
@ -167,7 +167,7 @@ class Service extends \think\Service
}
$config = Config::get('addons');
// 读取插件目录及钩子列表
$base = get_class_methods("\\think\\Addons");
$base = get_class_methods("\\taoser\\Addons");
// 读取插件目录中的php文件
foreach (glob($this->getAddonsPath() . '*/*.php') as $addons_file) {
// 格式化路径信息

View File

@ -0,0 +1,47 @@
<?php
namespace taoser\addons\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Env;
class SendConfig extends Command
{
public function configure()
{
$this->setName('addons:config')
->setDescription('send config to config folder');
}
public function execute(Input $input, Output $output)
{
//获取默认配置文件
$content = file_get_contents(root_path() . 'vendor/taoser/think-addons/src/config.php');
$configPath = config_path() . '/';
$configFile = $configPath . 'addons.php';
//判断目录是否存在
if (!file_exists($configPath)) {
mkdir($configPath, 0755, true);
}
//判断文件是否存在
if (is_file($configFile)) {
throw new \InvalidArgumentException(sprintf('The config file "%s" already exists', $configFile));
}
if (false === file_put_contents($configFile, $content)) {
throw new \RuntimeException(sprintf('The config file "%s" could not be written to "%s"', $configFile,$configPath));
}
$output->writeln('create addons config ok');
}
}

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace taoser\addons\middleware;
use think\App;
class Addons
{
protected $app;
public function __construct(App $app)
{
$this->app = $app;
}
/**
* 插件中间件
* @param $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, \Closure $next)
{
hook('addon_middleware', $request);
return $next($request);
}
}

View File

@ -3,13 +3,17 @@ declare(strict_types=1);
use think\facade\Event;
use think\facade\Route;
use taoser\addons\Service;
use think\facade\App;
use think\facade\Config;
use think\facade\Cache;
use think\helper\{
Str, Arr
};
\think\Console::starting(function (\think\Console $console) {
$console->addCommands([
'addons:config' => '\\think\\addons\\command\\SendConfig'
'addons:config' => '\\taoser\\addons\\command\\SendConfig'
]);
});
@ -76,6 +80,50 @@ if (!function_exists('get_addons_info')) {
}
}
/**
* 设置基础配置信息
* @param string $name 插件名
* @param array $array 配置数据
* @return boolean
* @throws Exception
*/
if (!function_exists('set_addons_info')) {
function set_addons_info($name, $array)
{
$service = new Service(App::instance()); // 获取service 服务
$addons_path = $service->getAddonsPath();
// 插件列表
$file = $addons_path . $name . DIRECTORY_SEPARATOR . 'info.ini';
$addon = get_addons_instance($name);
$array = $addon->setInfo($name, $array);
$array['status'] ? $addon->enabled() : $addon->disabled();
if (!isset($array['name']) || !isset($array['title']) || !isset($array['version'])) {
throw new Exception("Failed to write plugin config");
}
$res = array();
foreach ($array as $key => $val) {
if (is_array($val)) {
$res[] = "[$key]";
foreach ($val as $k => $v)
$res[] = "$k = " . (is_numeric($v) ? $v : $v);
} else
$res[] = "$key = " . (is_numeric($val) ? $val : $val);
}
if ($handle = fopen($file, 'w')) {
fwrite($handle, implode("\n", $res) . "\n");
fclose($handle);
//清空当前配置缓存
Config::set($array, "addon_{$name}_info");
Cache::delete('addonslist');
} else {
throw new Exception("File does not have write permission");
}
return true;
}
}
if (!function_exists('get_addons_instance')) {
/**
* 获取插件的单例
@ -131,6 +179,45 @@ if (!function_exists('get_addons_class')) {
}
}
if (!function_exists('get_addons_config')) {
/**
* 获取插件的配置
* @param string $name 插件名
* @return mixed|null
*/
function get_addons_config($name)
{
$addon = get_addons_instance($name);
if (!$addon) {
return [];
}
return $addon->getConfig($name);
}
}
if (!function_exists('set_addons_config')) {
function set_addons_config($name, $array)
{
$service = new Service(App::instance()); // 获取service 服务
$addons_path = $service->getAddonsPath();
// 插件列表
$file = $addons_path . $name . DIRECTORY_SEPARATOR . 'config.php';
if (!is_writable($file)) {
throw new \Exception(lang("addons.php File does not have write permission"));
}
if ($handle = fopen($file, 'w')) {
fwrite($handle, "<?php\n\n" . "return " . var_export($array, TRUE) . ";");
fclose($handle);
} else {
throw new Exception(lang("File does not have write permission"));
}
return true;
}
}
if (!function_exists('addons_url')) {
/**
* 插件显示内容里生成访问插件的url

View File

@ -1,67 +0,0 @@
<?php
/**
* +----------------------------------------------------------------------
* | think-addons [基于 thinkphp6]
* +----------------------------------------------------------------------
* .--, .--, | FILE: config.php
* ( ( \.---./ ) ) | AUTHOR: byron sampson
* '.__/o o\__.' | EMAIL: xiaobo.sun@qq.com
* {= ^ =} | QQ: 150093589
* > - < | WECHAT: wx5ini99
* / \ | DATETIME: 2019/10/29
* // \\ |
* //| . |\\ |
* "'\ /'"_.-~^`'-. |
* \ _ /--' ` |
* ___)( )(___ |-----------------------------------------
* (((__) (__))) | 高山仰止,景行行止.虽不能至,心向往之。
* +----------------------------------------------------------------------
* | Copyright (c) 2019 http://www.zzstudio.net All rights reserved.
* +----------------------------------------------------------------------
*/
namespace think\addons\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Env;
class SendConfig extends Command
{
public function configure()
{
$this->setName('addons:config')
->setDescription('send config to config folder');
}
public function execute(Input $input, Output $output)
{
//获取默认配置文件
$content = file_get_contents(root_path() . 'vendor/zzstudio/think-addons/src/config.php');
$configPath = config_path() . '/';
$configFile = $configPath . 'addons.php';
//判断目录是否存在
if (!file_exists($configPath)) {
mkdir($configPath, 0755, true);
}
//判断文件是否存在
if (is_file($configFile)) {
throw new \InvalidArgumentException(sprintf('The config file "%s" already exists', $configFile));
}
if (false === file_put_contents($configFile, $content)) {
throw new \RuntimeException(sprintf('The config file "%s" could not be written to "%s"', $configFile,$configPath));
}
$output->writeln('create addons config ok');
}
}

View File

@ -1,48 +0,0 @@
<?php
/**
* +----------------------------------------------------------------------
* | think-addons [thinkphp6]
* +----------------------------------------------------------------------
* .--, .--, | FILE: Addons.php
* ( ( \.---./ ) ) | AUTHOR: byron
* '.__/o o\__.' | EMAIL: xiaobo.sun@qq.com
* {= ^ =} | QQ: 150093589
* / \ | DATETIME: 2019/11/5 09:55
* // \\ |
* //| . |\\ |
* "'\ /'"_.-~^`'-. |
* \ _ /--' ` |
* ___)( )(___ |-----------------------------------------
* (((__) (__))) | 高山仰止,景行行止.虽不能至,心向往之。
* +----------------------------------------------------------------------
* | Copyright (c) 2019 http://www.zzstudio.net All rights reserved.
* +----------------------------------------------------------------------
*/
declare(strict_types=1);
namespace think\addons\middleware;
use think\App;
class Addons
{
protected $app;
public function __construct(App $app)
{
$this->app = $app;
}
/**
* 插件中间件
* @param $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, \Closure $next)
{
hook('addon_middleware', $request);
return $next($request);
}
}

View File

@ -20,7 +20,7 @@
{/if}
<span id="LAY_jieAdmin" data-id="{$article['id']}"></span>
</div>
<div onclick="PhoneDown();" style="" class="detail_qrcode" id="mobile"></div>
<div class="detail_qrcode layui-hide-xs" onclick="PhoneDown();" id="mobile"></div>
{//图标}
<div class="user-questions">
@ -294,10 +294,10 @@ layui.use(['fly', 'face','colorpicker','plyr'], function(){
});
//如果你是采用模版自带的编辑器,你需要开启以下语句来解析。
// $('.detail-body-wenda').each(function(){
// var othis = $(this), html = othis.html();
// othis.html(fly.content(html));
// });
$('.detail-body-wenda').each(function(){
var othis = $(this), html = othis.html();
othis.html(fly.content(html));
});
$('.detail-body').each(function(){
var othis = $(this), html = othis.html();

View File

@ -0,0 +1,325 @@
{extend name="public/base" /}
{block name="title"}{$article.title}-{$sysInfo.webname}{/block}
{block name="keywords"}{$article.title},{$article.tags}{/block}
{block name="description"}{$article.title},{:getArtContent($article.content)}{/block}
{block name="link"}<link rel="stylesheet" href="/static/res/css/plyr.css" charset="utf-8">{/block}
{block name="column"}<div class="layui-hide-xs">{include file="/public/column" /}</div>{/block}
{block name="content"}
<div class="layui-container">
<div class="layui-row layui-col-space15">
<div class="layui-col-md8 content detail">
<div class="fly-panel detail-box">
{//标题}
<h1 style="color:{$article.title_color};">{$article.title}
<span class="layui-hide-xs"><div onclick="PhoneDown();" style="" class="detail_qrcode" id="mobile"></div></span>
</h1>
{//图标}
<div class="fly-detail-info">
<span class="layui-badge layui-bg-green fly-detail-column">{:cookie('think_lang') == 'en-us' ? $article.cate.ename : $article.cate.catename}</span>
{if ($article.jie == 0)}
<span class="layui-badge" style="background-color: #999;">{:lang('no finished')}</span>
{else /}
<span class="layui-badge" style="background-color: #5FB878;">{:lang('finished')}</span>
{/if}
{if ($article.is_top == 1)}<span class="layui-badge layui-bg-black">{:lang('top')}</span>{/if}
{if ($article.is_hot == 1)}<span class="layui-badge layui-bg-red">{:lang('hot')}</span>{/if}
<span id="LAY_jieAdmin" data-id="{$article['id']}"></span>
<span class="fly-list-nums">
<a href="#comment"><i class="iconfont" title="{:lang('reply')}">&#xe60c;</i>{$comments->count()}</a><i class="iconfont" title="浏览">&#xe60b;</i>{$pv}
</span>
</div>
{//作者}
<div class="detail-about">
<a class="fly-avatar" href="{:url('user/home',['id'=>$article.user.id])}">
<img src="{$article.user.user_img}" alt="{$article.user.name}">
<i class="iconfont icon-renzheng" title="认证信息"></i>
</a>
<div class="fly-detail-user">
<a href="{:url('user/home',['id'=>$article.user.id])}" class="fly-link">
{if config('taoler.config.area_show') == 1}<i class="layui-badge layui-bg-green " title="">{:getAsing($article.user.area_id) ?: '无'}</i>{/if}
<cite>{$article.user.nickname ?: $article.user.name}</cite>
</a>
<span class="layui-btn layui-btn-xs guanzhu" >关注</span>
</div>
<div class="detail-hits">
<!--span style="padding-right: 10px; color: #FF7200">悬赏60飞吻</span-->
<span class="post-time" data="{$article.create_time}" style="padding-top: 5px;"></span>
</div>
</div>
<div class="detail-body photos">{$article.content|raw}</div>
{//管理}
{if (($article.upzip !== '') || session('?user_name'))}
<div class="detail-assist">
{notempty name="$article.upzip"}
<button type="button" class="layui-btn layui-btn-xs" id="zip-download"><i class="layui-icon layui-icon-download-circle"></i>{:lang('download files')}: {$article.downloads}次</button>
{/notempty}
<div class="fly-admin-box" data-id="{$article.id}">
{if ($user.auth ?? '')}
<span class="layui-btn layui-btn-xs jie-admin" type="del"><i class="layui-icon layui-icon-delete"></i></span>
{if($article.is_top == 0)}<span class="layui-btn layui-btn-xs jie-admin" type="set" field="top" rank="1"><i class="layui-icon layui-icon-top"></i></span>
{else /}<span class="layui-btn layui-btn-xs jie-admin" type="set" field="top" rank="0" style="background-color:#ccc;">{:lang('cancel topping')}</span>{/if}
{if($article.is_hot == 0)}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="hot" rank="1"><i class="layui-icon layui-icon-fire"></i></span>
{else /}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="hot" rank="0" style="background-color:#ccc;">{:lang('cancel hoting')}</span>
{/if}
{if($article.is_reply == 1)}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="reply" rank="0"><i class="layui-icon layui-icon-face-cry"></i></span>
{else /}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="reply" rank="1" style="background-color:#ccc;">{:lang('enable reply')}</span>
{/if}
<span id="color">{:lang('title color')}</span>
{/if}
{if(session('user_name')==$article.user.name || ($user.auth ?? ''))}
<span class="layui-btn layui-btn-xs jie-admin" type="edit"><a href="{:url('article/edit',['id'=>$article.id])}">{:lang('edit')}</a></span>
{/if}
</div>
</div>
{/if}
</div>
{//评论}
<div class="fly-panel detail-box" id="flyReply">
<span style="font-size:18px;">评论 {$comments->count()}</span>
<ul class="jieda" id="jieda">
{volist name="comments" id="vo" empty= ""}
<li data-id="{$vo.id}" class="jieda-daan">
<a name="item-1111111111"></a>
<div class="detail-about detail-about-reply">
<a class="fly-avatar" href="{:url('user/home',['id'=>$vo.user.id])}">
<img src="{$vo.user.user_img}" alt=" "><i class="iconfont icon-renzheng" title="认证信息"></i>
</a>
<div class="fly-detail-user">
<a href="{:url('user/home',['id'=>$vo.user.id])}" class="fly-link">
{if config('taoler.config.area_show') == 1}<i class="layui-badge layui-bg-green " title="">{:getAsing($vo.user.area_id) ?: '无'}</i>{/if}
<cite>{$vo.user.nickname ?: $vo.user.name}</cite>
</a>
{if condition="$article.user.id eq $vo.user.id"}<span>({:lang('poster')})</span>{/if}
</div>
<div class="detail-hits"><span class="post-time" data="{$vo.create_time}"></span></div>
{if $vo.cai == 1}<i class="iconfont icon-caina" title="最佳答案"></i>{/if}
</div>
<div class="detail-body jieda-body photos">{$vo.content|raw}</div>
<div class="jieda-reply">
<span class="jieda-zan {if($vo.zan != 0)}zanok{/if}" type="zan">
<i class="iconfont icon-zan"></i><em>{$vo.zan}</em>
</span>
<span type="reply"><i class="iconfont icon-svgmoban53"></i>{:lang('reply')}</span>
{//评论编辑删除采纳权限}
<div class="jieda-admin">
{if ((session('user_id') == $vo.user.id) && (getLimtTime($vo.create_time) < 2)) OR ($user.auth ?? '')}
<span type="edit">{:lang('edit')}</span>
<span type="del">{:lang('delete')}</span>
{/if}
{if ($vo.cai == 0) && ((session('user_id') == $article.user_id) OR ($user.auth ?? '')) /}<span class="jieda-accept" type="accept">{:lang('accept')}</span>{/if}
</div>
</div>
</li>
{/volist}
</ul>
<div style="text-align: center">{$comments|raw}</div>
{if condition="$article.is_reply == 1"}
<div class="layui-form layui-form-pane">
<div class="layui-form-item layui-form-text">
<a name="comment"></a>
<div class="layui-input-block">
<textarea id="L_content" name="content" required lay-verify="required" placeholder="{:lang('please input the content')}" class="layui-textarea fly-editor" style="height: 150px;"></textarea>
</div>
</div>
<div class="layui-form-item">
<input type="hidden" name="article_id" value="{$article.id}">
<input type="hidden" name="user_id" value="{:session('user_id')}">
<button class="layui-btn" lay-filter="user-comment" lay-submit>{:lang('submit comments')}</button>
</div>
</div>
{else /}
<blockquote class="layui-elem-quote layui-quote-nm layui-disabled" style="margin: 100px 0 20px; padding: 50px 20px; text-align: center; color: #999!important;">本帖已设置禁止回复</blockquote>
{/if}
</div>
</div>
<div class="layui-col-md4">
<div class="fly-panel">
<div class="fly-panel-title">{:lang('sponsor')}<span style="padding: 0 3px;">-</span>
<a href="" class="fly-link fly-joinad">{:lang('i want to join')}</a>
</div>
<div class="fly-panel-main">
{volist name="ad_comm" id="vo"}
<a href="{$vo.slid_href}" target="_blank" rel="nofollow" class="fly-zanzhu" style="background-color: {$vo.slid_color};">{$vo.slid_name}</a>
{/volist}
</div>
</div>
<dl class="fly-panel fly-list-one">
<dt class="fly-panel-title">{:lang('hot post list')}</dt>
{volist name="artHot" id="vo"}
<dd>
<a href="{:url('article/detail',['id' => $vo.id])}">{$vo.title}</a>
<span><i class="iconfont icon-pinglun1"></i> {$vo.comments_count}</span>
</dd>
{/volist}
</dl>
<div class="fly-panel" style="padding: 5px 0; text-align: center;">
{volist name="ad_art" id="vo"}
<a href="{$vo.slid_href}" target="_blank"><img src="{$vo.slid_img}" style="max-width: 100%;"></a>
{/volist}
</div>
</div>
</div>
<!--底部栏-->
<div class="site-tree-mobile-detail-bottom layui-hide-md">
<div id="LAY_jieAdmin1" data-id="{$article['id']}"></div>
</div>
</div>
{include file="public/menu" /}
{/block}
{block name="script"}
<script>
var collectionFind = "{:url('Collection/find')}",
articleJieset = "{:url('Article/jieset')}",
articleDelete = "{:url('Article/delete')}",
commentJiedaZan = "{:url('Comment/jiedaZan')}",
commentJiedaCai = "{:url('Comment/jiedaCai')}",
commentGetDa = "{:url('Comment/getDa')}",
commentUpdateDa = "{:url('Comment/updateDa')}",
commentJiedaDelete = "{:url('Comment/jiedaDelete')}",
langCollection = "{:lang('collection')}",
langCancelCollection = "{:lang('cancel collection')}";
var collection = "{:url('collection/')}";
layui.use(['fly', 'face','colorpicker','plyr'], function(){
var $ = layui.jquery
,form = layui.form
,fly = layui.fly
,colorpicker = layui.colorpicker
,plyr = layui.plyr;
var laytpl = layui.laytpl;
var uid = layui.cache.user.uid;
//tpl模板给发布时间赋值
$('div.detail-hits').children('span.post-time').each(function(){
var othis = $(this), html = othis.html();
var string = laytpl('{{ d.time }}').render({
//time: html
time: othis.attr('data')
});
var posttime = layui.util.timeAgo(string, 1);
othis.text(posttime);
//console.log(othis.attr('data'));
});
//预定义颜色项
colorpicker.render({
elem: '#color'
,color: '#393d49'
,predefine: true // 开启预定义颜色
,size: 'xs'
,done: function(color){
//改变标题颜色
$('h1').css("color", color);
var id = {$article.id};
$.ajax({
type:'post',
url:"{:url('Article/titleColor')}",
data:{id: id,title_color: color},
dataType:'json',
success:function(data){
if(data.code == 0){
layer.msg(data.msg,{icon:6,time:2000
});
} else {
layer.open({content:data.msg,icon:5,adim:6});
}
}
});
}
});
//评论需要登陆
form.on('submit(user-comment)',function (data){
var filed = data.field;
if (uid == -1) {
layer.msg('请先登陆',{icon:5,time:2000},function(){
location.href = "{:url('login/index')}";
});
} else {
$.ajax({
type: "post",
url: "{:url('article/comment')}",
data: filed,
dataType: "json",
success:function (data) {
if (data.code == 0) {
layer.msg(data.msg,{icon:6,time:2000},function () {
location.reload(true);
});
}else {
layer.open({title:'评论失败',content:data.msg,icon:5,anim:6});
}
}
});
}
return false;
});
//下载
$('#zip-download').click(function (){
var id = "{$article.id}";
$.ajax({
type:"post",
url:"{:url('article/download')}",
data:{id:id},
success:function (data) {
location.href = "{:url('article/download',['id'=>$article.id])}";
}
});
});
//如果你是采用模版自带的编辑器,你需要开启以下语句来解析。
$('.detail-body').each(function(){
var othis = $(this), html = othis.html();
othis.html(fly.content(html));
});
//加载播放器
plyr.setup();
});
//扫码阅读
$("#rdown").hover(function(){
$("#phonedl").show().stop();
},function(){
$("#phonedl").hide().stop();
});
$("#phonedl").hover(function(){
$("#phonedl").show().stop();
},function(){
$("#phonedl").hide().stop();
});
function PhoneDown(){
layer.open({
title: "扫码查阅",
skin: 'layui-layer',
content: "<img src='/qrcode/?text={$Request.domain}{:url('article/detail',['id' => $article.id])}&size=230'>"
});
}
//推送百度收录服务
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
if (curProtocol === 'https') {
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
}
else {
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
}
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
</script>
{/block}

View File

@ -0,0 +1,318 @@
{extend name="public/base" /}
{block name="title"}{$article.title}-{$sysInfo.webname}{/block}
{block name="keywords"}{$article.title},{$article.tags}{/block}
{block name="description"}{$article.title},{:getArtContent($article.content)}{/block}
{block name="link"}<link rel="stylesheet" href="/static/res/css/plyr.css" charset="utf-8">{/block}
{block name="column"}<div class="layui-hide-xs">{include file="/public/column" /}</div>{/block}
{block name="content"}
<div class="layui-container">
<div class="layui-row layui-col-space15">
<div class="layui-col-md8 content detail">
<div class="fly-panel detail-box">
{//标题}
<h1 style="color:{$article.title_color};">{$article.title}
<span class="layui-hide-xs"><div onclick="PhoneDown();" style="" class="detail_qrcode" id="mobile"></div></span>
</h1>
{//图标}
<div class="fly-detail-info">
<span class="layui-badge layui-bg-green fly-detail-column">{:cookie('think_lang') == 'en-us' ? $article.cate.ename : $article.cate.catename}</span>
{if ($article.is_top == 1)}<span class="layui-badge layui-bg-black">{:lang('top')}</span>{/if}
{if ($article.is_hot == 1)}<span class="layui-badge layui-bg-red">{:lang('hot')}</span>{/if}
<span id="LAY_jieAdmin" data-id="{$article['id']}"></span>
<span class="fly-list-nums">
<a href="#comment"><i class="iconfont" title="{:lang('reply')}">&#xe60c;</i>{$comments->count()}</a><i class="iconfont" title="浏览">&#xe60b;</i>{$pv}
</span>
</div>
{//作者}
<div class="detail-about">
<a class="fly-avatar" href="{:url('user/home',['id'=>$article.user.id])}">
<img src="{$article.user.user_img}" alt="{$article.user.name}">
<i class="iconfont icon-renzheng" title="认证信息"></i>
</a>
<div class="fly-detail-user">
<a href="{:url('user/home',['id'=>$article.user.id])}" class="fly-link">
{if config('taoler.config.area_show') == 1}<i class="layui-badge layui-bg-green " title="">{:getAsing($article.user.area_id) ?: '无'}</i>{/if}
<cite>{$article.user.nickname ?: $article.user.name}</cite>
</a>
<span class="layui-btn layui-btn-xs guanzhu" >关注</span>
</div>
<div class="detail-hits">
<!--span style="padding-right: 10px; color: #FF7200">悬赏60飞吻</span-->
<span class="post-time" data="{$article.create_time}" style="padding-top: 5px;"></span>
</div>
</div>
<div class="detail-body photos">{$article.content|raw}</div>
{//管理}
{if (($article.upzip !== '') || session('?user_name'))}
<div class="detail-assist">
{notempty name="$article.upzip"}
<button type="button" class="layui-btn layui-btn-xs" id="zip-download"><i class="layui-icon layui-icon-download-circle"></i>{:lang('download files')}: {$article.downloads}次</button>
{/notempty}
<div class="fly-admin-box" data-id="{$article.id}">
{if ($user.auth ?? '')}
<span class="layui-btn layui-btn-xs jie-admin" type="del"><i class="layui-icon layui-icon-delete"></i></span>
{if($article.is_top == 0)}<span class="layui-btn layui-btn-xs jie-admin" type="set" field="top" rank="1"><i class="layui-icon layui-icon-top"></i></span>
{else /}<span class="layui-btn layui-btn-xs jie-admin" type="set" field="top" rank="0" style="background-color:#ccc;">{:lang('cancel topping')}</span>{/if}
{if($article.is_hot == 0)}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="hot" rank="1"><i class="layui-icon layui-icon-fire"></i></span>
{else /}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="hot" rank="0" style="background-color:#ccc;">{:lang('cancel hoting')}</span>
{/if}
{if($article.is_reply == 1)}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="reply" rank="0"><i class="layui-icon layui-icon-face-cry"></i></span>
{else /}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="reply" rank="1" style="background-color:#ccc;">{:lang('enable reply')}</span>
{/if}
<span id="color">{:lang('title color')}</span>
{/if}
{if(session('user_name')==$article.user.name || ($user.auth ?? ''))}
<span class="layui-btn layui-btn-xs jie-admin" type="edit"><a href="{:url('article/edit',['id'=>$article.id])}">{:lang('edit')}</a></span>
{/if}
</div>
</div>
{/if}
</div>
{//评论}
<div class="fly-panel detail-box" id="flyReply">
<span style="font-size:18px;">评论 {$comments->count()}</span>
<ul class="jieda" id="jieda">
{volist name="comments" id="vo" empty= ""}
<li data-id="{$vo.id}" class="jieda-daan">
<a name="item-1111111111"></a>
<div class="detail-about detail-about-reply">
<a class="fly-avatar" href="{:url('user/home',['id'=>$vo.user.id])}">
<img src="{$vo.user.user_img}" alt=" "><i class="iconfont icon-renzheng" title="认证信息"></i>
</a>
<div class="fly-detail-user">
<a href="{:url('user/home',['id'=>$vo.user.id])}" class="fly-link">
{if config('taoler.config.area_show') == 1}<i class="layui-badge layui-bg-green " title="">{:getAsing($vo.user.area_id) ?: '无'}</i>{/if}
<cite>{$vo.user.nickname ?: $vo.user.name}</cite>
</a>
{if condition="$article.user.id eq $vo.user.id"}<span>({:lang('poster')})</span>{/if}
</div>
<div class="detail-hits"><span class="post-time" data="{$vo.create_time}"></span></div>
{if $vo.cai == 1}<i class="iconfont icon-caina" title="最佳答案"></i>{/if}
</div>
<div class="detail-body jieda-body photos">{$vo.content|raw}</div>
<div class="jieda-reply">
<span class="jieda-zan {if($vo.zan != 0)}zanok{/if}" type="zan">
<i class="iconfont icon-zan"></i><em>{$vo.zan}</em>
</span>
<span type="reply"><i class="iconfont icon-svgmoban53"></i>{:lang('reply')}</span>
{//评论编辑删除采纳权限}
<div class="jieda-admin">
{if ((session('user_id') == $vo.user.id) && (getLimtTime($vo.create_time) < 2)) OR ($user.auth ?? '')}
<span type="edit">{:lang('edit')}</span>
<span type="del">{:lang('delete')}</span>
{/if}
{if ($vo.cai == 0) && ((session('user_id') == $article.user_id) OR ($user.auth ?? '')) /}<span class="jieda-accept" type="accept">{:lang('accept')}</span>{/if}
</div>
</div>
</li>
{/volist}
</ul>
<div style="text-align: center">{$comments|raw}</div>
{if condition="$article.is_reply == 1"}
<div class="layui-form layui-form-pane">
<div class="layui-form-item layui-form-text">
<a name="comment"></a>
<div class="layui-input-block">
<textarea id="L_content" name="content" required lay-verify="required" placeholder="{:lang('please input the content')}" class="layui-textarea fly-editor" style="height: 150px;"></textarea>
</div>
</div>
<div class="layui-form-item">
<input type="hidden" name="article_id" value="{$article.id}">
<input type="hidden" name="user_id" value="{:session('user_id')}">
<button class="layui-btn" lay-filter="user-comment" lay-submit>{:lang('submit comments')}</button>
</div>
</div>
{else /}
<blockquote class="layui-elem-quote layui-quote-nm layui-disabled" style="margin: 100px 0 20px; padding: 50px 20px; text-align: center; color: #999!important;">本帖已设置禁止回复</blockquote>
{/if}
</div>
</div>
<div class="layui-col-md4">
<div class="fly-panel">
<div class="fly-panel-title">{:lang('sponsor')}<span style="padding: 0 3px;">-</span>
<a href="" class="fly-link fly-joinad">{:lang('i want to join')}</a>
</div>
<div class="fly-panel-main">
{volist name="ad_comm" id="vo"}
<a href="{$vo.slid_href}" target="_blank" rel="nofollow" class="fly-zanzhu" style="background-color: {$vo.slid_color};">{$vo.slid_name}</a>
{/volist}
</div>
</div>
<dl class="fly-panel fly-list-one">
<dt class="fly-panel-title">{:lang('hot post list')}</dt>
{volist name="artHot" id="vo"}
<dd>
<a href="{:url('article/detail',['id' => $vo.id])}">{$vo.title}</a>
<span><i class="iconfont icon-pinglun1"></i> {$vo.comments_count}</span>
</dd>
{/volist}
</dl>
<div class="fly-panel" style="padding: 5px 0; text-align: center;">
{volist name="ad_art" id="vo"}
<a href="{$vo.slid_href}" target="_blank"><img src="{$vo.slid_img}" style="max-width: 100%;"></a>
{/volist}
</div>
</div>
</div>
<!--底部栏-->
<div class="site-tree-mobile-detail-bottom layui-hide-md">
<div id="LAY_jieAdmin1" data-id="{$article['id']}"></div>
</div>
</div>
{include file="public/menu" /}
{/block}
{block name="script"}
<script>
var collectionFind = "{:url('Collection/find')}",
articleJieset = "{:url('Article/jieset')}",
articleDelete = "{:url('Article/delete')}",
commentJiedaZan = "{:url('Comment/jiedaZan')}",
commentJiedaCai = "{:url('Comment/jiedaCai')}",
commentGetDa = "{:url('Comment/getDa')}",
commentUpdateDa = "{:url('Comment/updateDa')}",
commentJiedaDelete = "{:url('Comment/jiedaDelete')}",
langCollection = "{:lang('collection')}",
langCancelCollection = "{:lang('cancel collection')}";
var collection = "{:url('collection/')}";
layui.use(['fly', 'face','colorpicker','plyr'], function(){
var $ = layui.jquery
,form = layui.form
,fly = layui.fly
,colorpicker = layui.colorpicker
,plyr = layui.plyr;
var laytpl = layui.laytpl;
var uid = layui.cache.user.uid;
//tpl模板给发布时间赋值
$('div.detail-hits').children('span.post-time').each(function(){
var othis = $(this), html = othis.html();
var string = laytpl('{{ d.time }}').render({
//time: html
time: othis.attr('data')
});
var posttime = layui.util.timeAgo(string, 1);
othis.text(posttime);
//console.log(othis.attr('data'));
});
//预定义颜色项
colorpicker.render({
elem: '#color'
,color: '#393d49'
,predefine: true // 开启预定义颜色
,size: 'xs'
,done: function(color){
//改变标题颜色
$('h1').css("color", color);
var id = {$article.id};
$.ajax({
type:'post',
url:"{:url('Article/titleColor')}",
data:{id: id,title_color: color},
dataType:'json',
success:function(data){
if(data.code == 0){
layer.msg(data.msg,{icon:6,time:2000
});
} else {
layer.open({content:data.msg,icon:5,adim:6});
}
}
});
}
});
//评论需要登陆
form.on('submit(user-comment)',function (data){
var filed = data.field;
if (uid == -1) {
layer.msg('请先登陆',{icon:5,time:2000},function(){
location.href = "{:url('login/index')}";
});
} else {
$.ajax({
type: "post",
url: "{:url('article/comment')}",
data: filed,
dataType: "json",
success:function (data) {
if (data.code == 0) {
layer.msg(data.msg,{icon:6,time:2000},function () {
location.reload(true);
});
}else {
layer.open({title:'评论失败',content:data.msg,icon:5,anim:6});
}
}
});
}
return false;
});
//下载
$('#zip-download').click(function (){
var id = "{$article.id}";
$.ajax({
type:"post",
url:"{:url('article/download')}",
data:{id:id},
success:function (data) {
location.href = "{:url('article/download',['id'=>$article.id])}";
}
});
});
//如果你是采用模版自带的编辑器,你需要开启以下语句来解析。
$('.detail-body').each(function(){
var othis = $(this), html = othis.html();
othis.html(fly.content(html));
});
//加载播放器
plyr.setup();
});
//扫码阅读
$("#rdown").hover(function(){
$("#phonedl").show().stop();
},function(){
$("#phonedl").hide().stop();
});
$("#phonedl").hover(function(){
$("#phonedl").show().stop();
},function(){
$("#phonedl").hide().stop();
});
function PhoneDown(){
layer.open({
title: "扫码查阅",
skin: 'layui-layer',
content: "<img src='/qrcode/?text={$Request.domain}{:url('article/detail',['id' => $article.id])}&size=230'>"
});
}
//推送百度收录服务
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
if (curProtocol === 'https') {
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
}
else {
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
}
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
</script>
{/block}

View File

@ -73,7 +73,7 @@
</div>
<div class="layui-form-item layui-form-text">
<div class="layui-input-block">
<textarea id="L_content" name="content" required lay-verify="required" placeholder="详细描述" class="layui-textarea fly-editor" style="height: 260px;">{$article.content}</textarea>
<textarea id="L_content" name="content" required lay-verify="required" placeholder="详细描述" class="layui-textarea fly-editor" style="height: 260px;">{$article.content|raw|htmlspecialchars_decode}</textarea>
</div>
</div>
<div class="layui-form-item">

View File

@ -11,9 +11,8 @@
<div class="layui-col-md8 content detail">
<div class="fly-panel detail-box">
{//标题}
<h1 style="color:{$article.title_color};">{$article.title}
<span class="layui-hide-xs"><div onclick="PhoneDown();" style="" class="detail_qrcode" id="mobile"></div></span>
</h1>
<h1 style="color:{$article.title_color};">{$article.title}</h1>
<div class="detail_qrcode layui-hide-xs" onclick="PhoneDown();" id="mobile"></div>
{//图标}
<div class="fly-detail-info">
<span class="layui-badge layui-bg-green fly-detail-column">{:cookie('think_lang') == 'en-us' ? $article.cate.ename : $article.cate.catename}</span>
@ -43,7 +42,7 @@
</div>
</div>
<div class="detail-body photos">{$article.content}</div>
<div class="detail-body photos" id="content">{$article.content}</div>
{//管理}
{if (($article.upzip !== '') || session('?user_name'))}
<div class="detail-assist">
@ -280,7 +279,11 @@ layui.use(['fly', 'face','colorpicker','plyr'], function(){
plyr.setup();
});
</script>
{:hook('markdownhook')}
<script>
//扫码阅读
$("#rdown").hover(function(){
$("#phonedl").show().stop();
@ -315,4 +318,5 @@ $("#rdown").hover(function(){
s.parentNode.insertBefore(bp, s);
})();
</script>
{/block}

View File

@ -0,0 +1,315 @@
{extend name="public/base" /}
{block name="title"}{$article.title}-{$sysInfo.webname}{/block}
{block name="keywords"}{$article.title},{$article.tags}{/block}
{block name="description"}{$article.title},{:getArtContent($article.content)}{/block}
{block name="link"}<link rel="stylesheet" href="/static/res/css/plyr.css" charset="utf-8">{/block}
{block name="column"}<div class="layui-hide-xs">{include file="/public/column" /}</div>{/block}
{block name="content"}
<div class="layui-container">
<div class="layui-row layui-col-space15">
<div class="layui-col-md8 content detail">
<div class="fly-panel detail-box">
{//标题}
<h1 style="color:{$article.title_color};">{$article.title}
<span class="layui-hide-xs"><div onclick="PhoneDown();" style="" class="detail_qrcode" id="mobile"></div></span>
</h1>
{//图标}
<div class="fly-detail-info">
<span class="layui-badge layui-bg-green fly-detail-column">{:cookie('think_lang') == 'en-us' ? $article.cate.ename : $article.cate.catename}</span>
{if ($article.is_top == 1)}<span class="layui-badge layui-bg-black">{:lang('top')}</span>{/if}
{if ($article.is_hot == 1)}<span class="layui-badge layui-bg-red">{:lang('hot')}</span>{/if}
<span id="LAY_jieAdmin" data-id="{$article['id']}"></span>
<span class="fly-list-nums">
<a href="#comment"><i class="iconfont" title="{:lang('reply')}">&#xe60c;</i>{$comments->count()}</a><i class="iconfont" title="浏览">&#xe60b;</i>{$pv}
</span>
</div>
{//作者}
<div class="detail-about">
<a class="fly-avatar" href="{:url('user/home',['id'=>$article.user.id])}">
<img src="{$article.user.user_img}" alt="{$article.user.name}">
<i class="iconfont icon-renzheng" title="认证信息"></i>
</a>
<div class="fly-detail-user">
<a href="{:url('user/home',['id'=>$article.user.id])}" class="fly-link">
{if config('taoler.config.area_show') == 1}<i class="layui-badge layui-bg-green " title="">{:getAsing($article.user.area_id) ?: '无'}</i>{/if}
<cite>{$article.user.nickname ?: $article.user.name}</cite>
</a>
<span class="layui-btn layui-btn-xs guanzhu" >关注</span>
</div>
<div class="detail-hits">
<!--span style="padding-right: 10px; color: #FF7200">悬赏60飞吻</span-->
<span class="post-time" data="{$article.create_time}" style="padding-top: 5px;"></span>
</div>
</div>
<div class="detail-body photos">{$article.content|raw}</div>
{//管理}
{if (($article.upzip !== '') || (session('user_id')==$article.user_id) OR ($user.auth ?? ''))}
<div class="detail-assist">
{notempty name="$article.upzip"}
<button type="button" class="layui-btn layui-btn-xs" id="zip-download"><i class="layui-icon layui-icon-download-circle"></i>{:lang('download files')}: {$article.downloads}次</button>
{/notempty}
<div class="fly-admin-box" data-id="{$article.id}">
{if ($user.auth ?? '')}
<span class="layui-btn layui-btn-xs jie-admin" type="del"><i class="layui-icon layui-icon-delete"></i></span>
{if($article.is_top == 0)}<span class="layui-btn layui-btn-xs jie-admin" type="set" field="top" rank="1"><i class="layui-icon layui-icon-top"></i></span>
{else /}<span class="layui-btn layui-btn-xs jie-admin" type="set" field="top" rank="0" style="background-color:#ccc;">{:lang('cancel topping')}</span>{/if}
{if($article.is_hot == 0)}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="hot" rank="1"><i class="layui-icon layui-icon-fire"></i></span>
{else /}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="hot" rank="0" style="background-color:#ccc;">{:lang('cancel hoting')}</span>
{/if}
{if($article.is_reply == 1)}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="reply" rank="0"><i class="layui-icon layui-icon-face-cry"></i></span>
{else /}
<span class="layui-btn layui-btn-xs jie-admin" type="set" field="reply" rank="1" style="background-color:#ccc;">{:lang('enable reply')}</span>
{/if}
<span id="color">{:lang('title color')}</span>
{/if}
{if(session('user_name')==$article.user.name || ($user.auth ?? ''))}
<span class="layui-btn layui-btn-xs jie-admin" type="edit"><a href="{:url('article/edit',['id'=>$article.id])}">{:lang('edit')}</a></span>
{/if}
</div>
</div>
{/if}
</div>
{//评论}
<div class="fly-panel detail-box" id="flyReply">
<span style="font-size:18px;">评论 {$comments->count()}</span>
<ul class="jieda" id="jieda">
{volist name="comments" id="vo" empty= ""}
<li data-id="{$vo.id}" class="jieda-daan">
<a name="item-1111111111"></a>
<div class="detail-about detail-about-reply">
<a class="fly-avatar" href="{:url('user/home',['id'=>$vo.user.id])}">
<img src="{$vo.user.user_img}" alt=" "><i class="iconfont icon-renzheng" title="认证信息"></i>
</a>
<div class="fly-detail-user">
<a href="{:url('user/home',['id'=>$vo.user.id])}" class="fly-link">
{if config('taoler.config.area_show') == 1}<i class="layui-badge layui-bg-green " title="">{:getAsing($vo.user.area_id) ?: '无'}</i>{/if}
<cite>{$vo.user.nickname ?: $vo.user.name}</cite>
</a>
{if condition="$article.user.id eq $vo.user.id"}<span>({:lang('poster')})</span>{/if}
</div>
<div class="detail-hits"><span class="post-time" data="{$vo.create_time}"></span></div>
</div>
<div class="detail-body jieda-body photos">{$vo.content|raw|htmlspecialchars_decode}</div>
<div class="jieda-reply">
<span class="jieda-zan {if($vo.zan != 0)}zanok{/if}" type="zan">
<i class="iconfont icon-zan"></i><em>{$vo.zan}</em>
</span>
<span type="reply"><i class="iconfont icon-svgmoban53"></i>{:lang('reply')}</span>
{//评论编辑删除采纳权限}
<div class="jieda-admin">
{if ((session('user_id') == $vo.user.id) && (getLimtTime($vo.create_time) < 2)) OR ($user.auth ?? '')}
<span type="edit">{:lang('edit')}</span>
<span type="del">{:lang('delete')}</span>
{/if}
</div>
</div>
</li>
{/volist}
</ul>
<div style="text-align: center">{$comments|raw}</div>
{if condition="$article.is_reply == 1"}
<div class="layui-form layui-form-pane">
<div class="layui-form-item layui-form-text">
<a name="comment"></a>
<div class="layui-input-block">
<textarea id="L_content" name="content" required lay-verify="required" placeholder="{:lang('please input the content')}" class="layui-textarea fly-editor" style="height: 150px;"></textarea>
</div>
</div>
<div class="layui-form-item">
<input type="hidden" name="article_id" value="{$article.id}">
<input type="hidden" name="user_id" value="{:session('user_id')}">
<button class="layui-btn" lay-filter="user-comment" lay-submit>{:lang('submit comments')}</button>
</div>
</div>
{else /}
<blockquote class="layui-elem-quote layui-quote-nm layui-disabled" style="margin: 100px 0 20px; padding: 50px 20px; text-align: center; color: #999!important;">本帖已设置禁止回复</blockquote>
{/if}
</div>
</div>
<div class="layui-col-md4">
<div class="fly-panel">
<div class="fly-panel-title">{:lang('sponsor')}<span style="padding: 0 3px;">-</span>
<a href="" class="fly-link fly-joinad">{:lang('i want to join')}</a>
</div>
<div class="fly-panel-main">
{volist name="ad_comm" id="vo"}
<a href="{$vo.slid_href}" target="_blank" rel="nofollow" class="fly-zanzhu" style="background-color: {$vo.slid_color};">{$vo.slid_name}</a>
{/volist}
</div>
</div>
<dl class="fly-panel fly-list-one">
<dt class="fly-panel-title">{:lang('hot post list')}</dt>
{volist name="artHot" id="vo"}
<dd>
<a href="{:url('article/detail',['id' => $vo.id])}">{$vo.title}</a>
<span><i class="iconfont icon-pinglun1"></i> {$vo.comments_count}</span>
</dd>
{/volist}
</dl>
<div class="fly-panel" style="padding: 5px 0; text-align: center;">
{volist name="ad_art" id="vo"}
<a href="{$vo.slid_href}" target="_blank"><img src="{$vo.slid_img}" style="max-width: 100%;"></a>
{/volist}
</div>
</div>
</div>
<!--底部栏-->
<div class="site-tree-mobile-detail-bottom layui-hide-md">
<div id="LAY_jieAdmin1" data-id="{$article['id']}"></div>
</div>
</div>
{include file="public/menu" /}
{/block}
{block name="script"}
<script>
var collectionFind = "{:url('Collection/find')}",
articleJieset = "{:url('Article/jieset')}",
articleDelete = "{:url('Article/delete')}",
commentJiedaZan = "{:url('Comment/jiedaZan')}",
commentJiedaCai = "{:url('Comment/jiedaCai')}",
commentGetDa = "{:url('Comment/getDa')}",
commentUpdateDa = "{:url('Comment/updateDa')}",
commentJiedaDelete = "{:url('Comment/jiedaDelete')}",
langCollection = "{:lang('collection')}",
langCancelCollection = "{:lang('cancel collection')}";
var collection = "{:url('collection/')}";
layui.use(['fly', 'face','colorpicker','plyr'], function(){
var $ = layui.jquery
,form = layui.form
,fly = layui.fly
,colorpicker = layui.colorpicker
,plyr = layui.plyr;
var laytpl = layui.laytpl;
var uid = layui.cache.user.uid;
//tpl模板给发布时间赋值
$('div.detail-hits').children('span.post-time').each(function(){
var othis = $(this), html = othis.html();
var string = laytpl('{{ d.time }}').render({
//time: html
time: othis.attr('data')
});
var posttime = layui.util.timeAgo(string, 1);
othis.text(posttime);
//console.log(othis.attr('data'));
});
//预定义颜色项
colorpicker.render({
elem: '#color'
,color: '#393d49'
,predefine: true // 开启预定义颜色
,size: 'xs'
,done: function(color){
//改变标题颜色
$('h1').css("color", color);
var id = {$article.id};
$.ajax({
type:'post',
url:"{:url('Article/titleColor')}",
data:{id: id,title_color: color},
dataType:'json',
success:function(data){
if(data.code == 0){
layer.msg(data.msg,{icon:6,time:2000
});
} else {
layer.open({content:data.msg,icon:5,adim:6});
}
}
});
}
});
//评论需要登陆
form.on('submit(user-comment)',function (data){
var filed = data.field;
if (uid == -1) {
layer.msg('请先登陆',{icon:5,time:2000},function(){
location.href = "{:url('login/index')}";
});
} else {
$.ajax({
type: "post",
url: "{:url('article/comment')}",
data: filed,
dataType: "json",
success:function (data) {
if (data.code == 0) {
layer.msg(data.msg,{icon:6,time:2000},function () {
location.reload(true);
});
}else {
layer.open({title:'评论失败',content:data.msg,icon:5,anim:6});
}
}
});
}
return false;
});
//下载
$('#zip-download').click(function (){
var id = "{$article.id}";
$.ajax({
type:"post",
url:"{:url('article/download')}",
data:{id:id},
success:function (data) {
location.href = "{:url('article/download',['id'=>$article.id])}";
}
});
});
//如果你是采用模版自带的编辑器,你需要开启以下语句来解析。
$('.detail-body').each(function(){
var othis = $(this), html = othis.html();
othis.html(fly.content(html));
});
//加载播放器
plyr.setup();
});
//扫码阅读
$("#rdown").hover(function(){
$("#phonedl").show().stop();
},function(){
$("#phonedl").hide().stop();
});
$("#phonedl").hover(function(){
$("#phonedl").show().stop();
},function(){
$("#phonedl").hide().stop();
});
function PhoneDown(){
layer.open({
title: "扫码查阅",
skin: 'layui-layer',
content: "<img src='/qrcode/?text={$Request.domain}{:url('article/detail',['id' => $article.id])}&size=230'>"
});
}
//推送百度收录服务
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
if (curProtocol === 'https') {
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
}
else {
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
}
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
</script>
{/block}

View File

@ -0,0 +1,46 @@
{extend name="public/base" /}
{block name="title"}404 - {$sysInfo.webname}{/block}
{block name="keywords"}{$sysInfo.keywords}{/block}
{block name="description"}{$sysInfo.descript}{/block}
{block name="column"}{include file="public/column" /}{/block}
{block name="content"}
<div class="layui-container fly-marginTop">
<div class="fly-panel">
<div class="fly-none">
<h2><i class="iconfont icon-404"></i></h2>
<p>页面或者数据被<a href="http://www.aieok.com"> 纸飞机 </a>运到火星了,啥都看不到了…</p>
</div>
</div>
</div>
{/block}
{block name="script"}
<script>
layui.cache.page = 'user';
layui.cache.user = {
username: '{$user.name??'游客'}'
,uid: '{$user.id ?? -1}'
,avatar: '{$user['user_img'] ?? '/static/res/images/avatar/00.jpg'}'
,experience: '{$user.point ?? ''}'
,sex: '{$user.sex ? '女':'男'}'
};
layui.config({
version: "3.0.0"
,base: '/static/res/mods/'
}).extend({
fly: 'index'
}).use('fly');
</script>
{/block}

View File

@ -41,11 +41,8 @@
</div>
</div>
<div class="layui-col-md4">
<!--签到-->
<a name="signin"> </a>
<div class="fly-panel fly-signin layui-hide-xs">
{include file="public/sign" /}
</div>
{:hook('signhook', ['id'=>1])}
<!--温馨通道-->
<div class="fly-panel layui-hide-xs">
<h3 class="fly-panel-title">{:lang('links list')}</h3>

View File

@ -44,11 +44,7 @@
<a href="{:url('login/forget')}">{:lang('forget password')}</a>
</span>
</div>
<!--div class="layui-form-item fly-form-app">
<span>或者使用社交账号登入</span>
<a href="" onclick="layer.msg('正在通过QQ登入', {icon:16, shade: 0.1, time:0})" class="iconfont icon-qq" title="QQ登入"></a>
<a href="" onclick="layer.msg('正在通过微博登入', {icon:16, shade: 0.1, time:0})" class="iconfont icon-weibo" title="微博登入"></a>
</div-->
{:hook('socialhook')}
</form>
</div>
</div>

1
view/taoler/index/public/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
user-nav.html

View File

@ -1,5 +1,5 @@
<div class="fly-footer html5plus-hide layui-hide-xs">
<p> Copyright &copy; {:date('Y')}{$sysInfo.copyright|raw}</p>
<div class="fly-footer html5plus-hide">
<p> Copyright &copy; {:date('Y')}{$sysInfo.copyright|raw}v{:config('taoler.version')}</p>
<p>
{$sysInfo.showlist|raw}
{volist name="footlinks" id="vo"}

View File

@ -1,13 +1,13 @@
<div class="fly-header layui-bg-black">
<div class="layui-container">
<a class="fly-logo layui-hide-xs" href="/"><img src="{$sysInfo.logo}" alt="layui" width="135" height="37"></a>
<a class="fly-logo layui-hide-xs" href="/"><img src="{$sysInfo.logo}" alt="taoler" width="135" height="37"></a>
<!--头部伸缩侧边栏-->
<div class="site-tree-mobile-top layui-hide">
<i class="layui-icon layui-icon-spread-left"></i>
</div>
<div class="site-mobile-shade-top"></div>
{//移动端LOGO}
<a class="fly-logo layui-hide-md" href="/" style="padding-left:50%; margin-left:-65px;"><img src="{$sysInfo.logo}" alt="layui" width="135" height="37"></a>
<a class="fly-logo layui-hide-md" href="/" style="padding-left:50%; margin-left:-60px;"><img src="/static/res/images/logo-m.png"></a>
<ul class="layui-nav fly-nav layui-hide-xs">
{volist name="headlinks" id="vo"}
<li class="layui-nav-item">

View File

@ -1,12 +0,0 @@
<script>
var messageNums = "{:url('Message/nums')}",
messageRead = "{:url('Message/read')}",
userMessage = "{:url('index/User/message')}",
login = "{:url('Login/index')}",
articleAdd = "{:url('Article/add')}",
websearch = "{:url('index/search')}",
textImgUpload = "{:url('article/textImgUpload')}",
searchUrl = "{:url('index/search')}";
</script>
<script src="/static/layui/jquery.min.js" charset="utf-8"></script>
<script src="/static/layui/layui.js" charset="utf-8"></script>

View File

@ -1,5 +1,4 @@
<div class="layui-hide-md">
<div class="layui-panel site-menu" style="width: auto;">
<div class="layui-panel site-menu layui-hide-md">
<ul class="layui-menu layui-menu-lg">
<li class="search" style="padding-left:5px;padding-top:2px;padding-right:5px;">
<form action="{:url('index/search',['keywords'=>$Request.param.keywords])}">
@ -68,8 +67,8 @@
</ul>
</li>
</ul>
</div>
</div>
<!--
<div class="site-tree-mobile layui-hide">
<i class="layui-icon layui-icon-spread-left"></i>

View File

@ -1,42 +1,43 @@
<ul class="layui-nav layui-nav-tree layui-inline" lay-filter="user">
<li class="layui-nav-item {if($Request.action=='index')}layui-this{/if}">
<a href="{:url('user/index')}">
<i class="layui-icon">&#xe612;</i>
用户中心
<i class="layui-icon layui-icon-user"></i>
{:lang('user center')}
</a>
</li>
<li class="layui-nav-item {if($Request.action=='set')}layui-this{/if}">
<a href="{:url('user/set')}">
<i class="layui-icon">&#xe620;</i>
基本设置
<i class="layui-icon layui-icon-set"></i>
{:lang('set info')}
</a>
</li>
<li class="layui-nav-item {if($Request.action=='post')}layui-this{/if}">
<a href="{:url('user/post')}">
<i class="layui-icon">&#xe705;</i>
我的帖子
<i class="layui-icon layui-icon-read"></i>
{:lang('my post')}
</a>
</li>
<li class="layui-nav-item {if($Request.action=='message')}layui-this{/if}">
<a href="{:url('user/message')}">
<i class="layui-icon">&#xe611;</i>
我的消息
<i class="layui-icon layui-icon-notice"></i>
{:lang('my message')}
</a>
</li>
<li class="layui-nav-item {if($Request.action=='key')}layui-this{/if}" >
<a href="{:url('Api/key')}">
<i class="layui-icon layui-icon-vercode"></i>
{:lang('my auth')}
</a>
</li>
<li class="layui-nav-item " >
<a href="{:url('user/home',['id'=>session('user_id')])}">
<i class="layui-icon">&#xe609;</i>
我的主页
<i class="layui-icon layui-icon-home"></i>
{:lang('my page')}
</a>
</li>
</ul>
<div class="site-tree-mobile-user layui-hide">
<i class="layui-icon">&#xe602;</i>
<i class="layui-icon layui-icon-right"></i>
</div>
<div class="site-mobile-shade-user"></div>
<div class="site-tree-mobile-user layui-hide">
<i class="layui-icon">&#xe602;</i>
</div>
<div class="site-mobile-shade-user"></div>