mirror of https://gitee.com/karson/fastadmin.git
Compare commits
273 Commits
v1.2.1.202
...
master
| Author | SHA1 | Date |
|---|---|---|
|
|
c74b9dc24a | |
|
|
5188621e9c | |
|
|
7238632f14 | |
|
|
4329b47c56 | |
|
|
418d93f448 | |
|
|
8e88e1c9dc | |
|
|
592a42fcc5 | |
|
|
a532001e7b | |
|
|
9876dc22db | |
|
|
37c18d4e92 | |
|
|
5c9c6ef89c | |
|
|
03ccce86f0 | |
|
|
18a661fb22 | |
|
|
c01628a914 | |
|
|
996fa27d62 | |
|
|
b13a1ca7b5 | |
|
|
c78b3aecc5 | |
|
|
54d6e0904b | |
|
|
6d4aaf5ea8 | |
|
|
4a97bdaf19 | |
|
|
028a0b5f22 | |
|
|
7f54960449 | |
|
|
e7c1922cf3 | |
|
|
c5285b8fdd | |
|
|
5400c6ff2a | |
|
|
090381a1a2 | |
|
|
8f7a55928c | |
|
|
e8a804afad | |
|
|
26a5ca4a2c | |
|
|
f932156c8e | |
|
|
77c386ed47 | |
|
|
57da65acd0 | |
|
|
6dd941e168 | |
|
|
b7eef593a3 | |
|
|
2b14bc4e2b | |
|
|
5e7d398b49 | |
|
|
58035763ea | |
|
|
7c9841cee9 | |
|
|
a5e1fe9cb6 | |
|
|
1a31ac2dc9 | |
|
|
56b33f1514 | |
|
|
c5d26b7f3a | |
|
|
de002debd7 | |
|
|
d1c240bd91 | |
|
|
e45b435b48 | |
|
|
aec4efe9e0 | |
|
|
0a5484b738 | |
|
|
9f2c08414a | |
|
|
448eaad5f5 | |
|
|
578044505a | |
|
|
36bf77df6c | |
|
|
bac6606786 | |
|
|
131ef803d1 | |
|
|
17eb182063 | |
|
|
f7e47d90f1 | |
|
|
a9a6065fde | |
|
|
6a94a07903 | |
|
|
5bf63c557b | |
|
|
5d3d667143 | |
|
|
8a0e8b1d3b | |
|
|
ee0be09841 | |
|
|
c8c1573c27 | |
|
|
76abb2dcd7 | |
|
|
787334972e | |
|
|
1c7d0b710e | |
|
|
b0a3851d93 | |
|
|
2e4fe16f44 | |
|
|
e3779a1f05 | |
|
|
d8acbf8abe | |
|
|
e76eba0c21 | |
|
|
7b66d0bf58 | |
|
|
bb68eb4254 | |
|
|
879554d5a8 | |
|
|
403c6a2a7d | |
|
|
42e91e10e6 | |
|
|
22628fca0e | |
|
|
709424da7f | |
|
|
ae57feebb6 | |
|
|
cdb41c5334 | |
|
|
2fe68b4c27 | |
|
|
31b307a4a1 | |
|
|
7fffba8963 | |
|
|
4aa2666c98 | |
|
|
940e9a0814 | |
|
|
901bea7d59 | |
|
|
faff9fc96f | |
|
|
cc9802877a | |
|
|
681558500c | |
|
|
033af96e1a | |
|
|
ad166f07eb | |
|
|
b76b99f3a0 | |
|
|
b4dc742fed | |
|
|
37e844181e | |
|
|
1a660364af | |
|
|
65068c9a29 | |
|
|
4845b08077 | |
|
|
b0387e668b | |
|
|
aca4e9221c | |
|
|
7a4d05bbd9 | |
|
|
a9003ecce4 | |
|
|
7f28eaa570 | |
|
|
31528c8951 | |
|
|
e4094e24e2 | |
|
|
80ad9e307a | |
|
|
e6f2894af7 | |
|
|
c170985264 | |
|
|
9d9c8dcf52 | |
|
|
4eaae6ac4e | |
|
|
7e6314a701 | |
|
|
a40420b8cd | |
|
|
31a6a47dc3 | |
|
|
2c66c67d71 | |
|
|
42fdea065a | |
|
|
0fb7924420 | |
|
|
7cd9281c74 | |
|
|
dc466cb1c9 | |
|
|
d2c275e20a | |
|
|
3549e95ea1 | |
|
|
a34c5fbdb8 | |
|
|
9fe7a6f9a0 | |
|
|
94b61ab7dc | |
|
|
6ebde793bd | |
|
|
faca2e0be0 | |
|
|
7c8d1a6683 | |
|
|
76c48c00fd | |
|
|
bc6bcb84f9 | |
|
|
5f35be92b5 | |
|
|
9cadda6c3f | |
|
|
152ac2cdcb | |
|
|
cd5fafde38 | |
|
|
3d4a02160c | |
|
|
1004bdedad | |
|
|
8ce9f1f884 | |
|
|
bfd3737b28 | |
|
|
4b4d4493aa | |
|
|
164a4f6664 | |
|
|
e59668c0f2 | |
|
|
afe0fdce73 | |
|
|
03f46a637d | |
|
|
0a062a8d63 | |
|
|
db5574582e | |
|
|
e4ef9f1db0 | |
|
|
2c02ed019b | |
|
|
eee98aad11 | |
|
|
6d8f98a554 | |
|
|
9e9d729c62 | |
|
|
91549dbfea | |
|
|
85f0e4f041 | |
|
|
17256db17a | |
|
|
2b81652072 | |
|
|
e846244791 | |
|
|
f8292a8813 | |
|
|
89ed50d790 | |
|
|
776a4fedb5 | |
|
|
6b190fe111 | |
|
|
d562f3d17c | |
|
|
445f0c94d8 | |
|
|
6e4321d5cf | |
|
|
6d4d564ae8 | |
|
|
b1af836710 | |
|
|
7f0e4eb25c | |
|
|
eaa1832852 | |
|
|
aa9fa16451 | |
|
|
f02121cfcc | |
|
|
4fb1379afa | |
|
|
ae935d260c | |
|
|
44887b8aec | |
|
|
1dbafec12f | |
|
|
9a90cbe329 | |
|
|
ae11381309 | |
|
|
c3bdbbf779 | |
|
|
3ba1192555 | |
|
|
80d928d872 | |
|
|
b9877c10ff | |
|
|
a7983055fc | |
|
|
3fd25c3de0 | |
|
|
85e0f4bacc | |
|
|
b3c4692164 | |
|
|
dfeff713bd | |
|
|
f639cecf73 | |
|
|
466aa4233f | |
|
|
378aad4409 | |
|
|
1a07280f79 | |
|
|
b3e172ddce | |
|
|
079f6df9dd | |
|
|
9400aa6e4e | |
|
|
0b4eceea54 | |
|
|
ce811fa904 | |
|
|
06ccca81c9 | |
|
|
be2f342044 | |
|
|
1898e481e0 | |
|
|
e59d2df641 | |
|
|
f4795e90da | |
|
|
9eeb35a79b | |
|
|
12e7bbf5f2 | |
|
|
940d4f0410 | |
|
|
5022da9cea | |
|
|
8e48aa7edd | |
|
|
036c2dcc25 | |
|
|
9116b86a36 | |
|
|
a4617c7f28 | |
|
|
a9a5696f58 | |
|
|
e67f9a20c5 | |
|
|
ff51380686 | |
|
|
2a97c21c0c | |
|
|
6470a8ed74 | |
|
|
d7ffc690c2 | |
|
|
41682bd850 | |
|
|
2401cd3ba1 | |
|
|
8b55020b3a | |
|
|
3dd4276ca1 | |
|
|
02cc257faf | |
|
|
cd60f5f381 | |
|
|
d4531c7df0 | |
|
|
d2d6648d9c | |
|
|
f700dbcdc7 | |
|
|
9ed5fbd2e3 | |
|
|
6569dfbb3c | |
|
|
c87a7f9f3c | |
|
|
077bba602d | |
|
|
edec9f7fe1 | |
|
|
0c950a93cf | |
|
|
96cb06f825 | |
|
|
65073c30b9 | |
|
|
d785d321f7 | |
|
|
ff85bb3b21 | |
|
|
c65e3b23e2 | |
|
|
c00584a5b5 | |
|
|
017970a2e3 | |
|
|
5673ce72fd | |
|
|
4fa13dca39 | |
|
|
8366745875 | |
|
|
a176508bb9 | |
|
|
5ea57836c8 | |
|
|
82ea7fcd15 | |
|
|
03bfe24893 | |
|
|
acca6a0584 | |
|
|
12ea49d937 | |
|
|
41fc1d1b3a | |
|
|
b52df110ee | |
|
|
e3169bcaf4 | |
|
|
d1cdc51798 | |
|
|
cd9d2e6516 | |
|
|
bc99cfddd8 | |
|
|
a7317ec08c | |
|
|
824f337481 | |
|
|
fce5b8e374 | |
|
|
093d60b719 | |
|
|
a7b7b772fd | |
|
|
48066342da | |
|
|
ecdaa81a8d | |
|
|
a87cfefd50 | |
|
|
e7f8b75ecf | |
|
|
9a239de4b1 | |
|
|
db69a36d28 | |
|
|
70b9c8affe | |
|
|
9d1d1248e9 | |
|
|
84eef812f3 | |
|
|
0266534d95 | |
|
|
e7ae8fb4d1 | |
|
|
c12f9bca84 | |
|
|
69ad41a3e9 | |
|
|
3a0352e183 | |
|
|
ab53e00a75 | |
|
|
ac2b3ffbff | |
|
|
9cf930a932 | |
|
|
343ad6055d | |
|
|
2ab8d7fa81 | |
|
|
f3b841c456 | |
|
|
683d837d20 | |
|
|
3f1cac43e4 | |
|
|
75141e192d | |
|
|
bbf728b5e6 |
5
.bowerrc
5
.bowerrc
|
|
@ -5,6 +5,7 @@
|
|||
"file-saver",
|
||||
"html2canvas",
|
||||
"jspdf",
|
||||
"jspdf-autotable"
|
||||
"jspdf-autotable",
|
||||
"pdfmake"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
### 类型
|
||||
类型(问题/建议/其他):?
|
||||
|
||||
|
||||
### 现象
|
||||
现象(请详细描述一下复现过程):?
|
||||
|
||||
|
||||
### 期望结果
|
||||
期望结果(请详细描述一下你说期望的结果):?
|
||||
|
||||
|
||||
### 环境
|
||||
(请详细说明一下你的运行环境)
|
||||
- 操作系统(Linux/Windows/Other):?
|
||||
- Web Server(NGINX/Apache/Other):?
|
||||
- PHP 版本(7.2/7.3/7.4/8.0/8.1/8.2/Other):?
|
||||
- MySQL 版本(5.6/5.7/8.0/Other):?
|
||||
- 服务器面板(BT/phpStudy/XAMPP/其他/无):?
|
||||
- FastAdmin 版本:?
|
||||
- 浏览器(Chrome/IE/Edge/其他):?
|
||||
- 报错信息:?
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
/vendor/
|
||||
/runtime/*
|
||||
/addons/*
|
||||
/application/admin/command/Install/*.lock
|
||||
/public/assets/libs/
|
||||
/public/assets/addons/*
|
||||
/public/uploads/*
|
||||
|
|
@ -16,3 +15,4 @@ composer.lock
|
|||
.svn
|
||||
.vscode
|
||||
node_modules
|
||||
.user.ini
|
||||
|
|
|
|||
16
README.md
16
README.md
|
|
@ -24,12 +24,10 @@ FastAdmin是一款基于ThinkPHP+Bootstrap的极速后台开发框架。
|
|||
* 多语言支持,服务端及客户端支持
|
||||
* 支持大文件分片上传、剪切板粘贴上传、拖拽上传,进度条显示,图片上传前压缩
|
||||
* 支持表格固定列、固定表头、跨页选择、Excel导出、模板渲染等功能
|
||||
* 强大的第三方应用模块支持([CMS](https://www.fastadmin.net/store/cms.html)、[博客](https://www.fastadmin.net/store/blog.html)、[知识付费问答](https://www.fastadmin.net/store/ask.html)、[在线投票系统](https://www.fastadmin.net/store/vote.html)、[B2C商城](https://www.fastadmin.net/store/shopro.html)、[B2B2C商城](https://www.fastadmin.net/store/wanlshop.html))
|
||||
* 支持CMS、博客、知识付费问答无缝整合[Xunsearch全文搜索](https://www.fastadmin.net/store/xunsearch.html)
|
||||
* 第三方小程序支持([CMS小程序](https://www.fastadmin.net/store/cms.html)、[预订小程序](https://www.fastadmin.net/store/ball.html)、[问答小程序](https://www.fastadmin.net/store/ask.html)、[点餐小程序](https://www.fastadmin.net/store/unidrink.html)、[B2C小程序](https://www.fastadmin.net/store/shopro.html)、[B2B2C小程序](https://www.fastadmin.net/store/wanlshop.html)、[博客小程序](https://www.fastadmin.net/store/blog.html))
|
||||
* 强大的第三方应用模块支持([CMS](https://www.fastadmin.net/store/cms.html)、[CRM](https://www.fastadmin.net/store/facrm.html)、[企业网站管理系统](https://www.fastadmin.net/store/ldcms.html)、[知识库文档系统](https://www.fastadmin.net/store/knowbase.html)、[在线投票系统](https://www.fastadmin.net/store/vote.html)、[B2C商城](https://www.fastadmin.net/store/shopro.html)、[B2B2C商城](https://www.fastadmin.net/store/wanlshop.html))
|
||||
* 整合第三方短信接口(阿里云、腾讯云短信)
|
||||
* 无缝整合第三方云存储(七牛云、阿里云OSS、又拍云)功能,支持云储存分片上传
|
||||
* 第三方富文本编辑器支持(Summernote、Kindeditor、百度编辑器)
|
||||
* 无缝整合第三方云存储(七牛云、阿里云OSS、腾讯云存储、又拍云)功能,支持云储存分片上传
|
||||
* 第三方富文本编辑器支持(Summernote、百度编辑器)
|
||||
* 第三方登录(QQ、微信、微博)整合
|
||||
* 第三方支付(微信、支付宝)无缝整合,微信支持PC端扫码支付
|
||||
* 丰富的插件应用市场
|
||||
|
|
@ -55,9 +53,7 @@ https://demo.fastadmin.net
|
|||
|
||||
在使用中有任何问题,请使用以下联系方式联系我们
|
||||
|
||||
交流社区: https://ask.fastadmin.net
|
||||
|
||||
QQ群: [636393962](https://jq.qq.com/?_wv=1027&k=487PNBb)(满) [708784003](https://jq.qq.com/?_wv=1027&k=5ObjtwM)(满) [964776039](https://jq.qq.com/?_wv=1027&k=59qjU2P)(3群) [749803490](https://jq.qq.com/?_wv=1027&k=5tczi88)(满) [767103006](https://jq.qq.com/?_wv=1027&k=5Z1U751)(满) [675115483](https://jq.qq.com/?_wv=1027&k=54I6mts)(6群)
|
||||
问答社区: https://ask.fastadmin.net
|
||||
|
||||
Github: https://github.com/karsonzhang/fastadmin
|
||||
|
||||
|
|
@ -81,7 +77,7 @@ Nice-validator: https://validator.niceue.com
|
|||
|
||||
SelectPage: https://github.com/TerryZ/SelectPage
|
||||
|
||||
Layer: https://layer.layui.com
|
||||
Layer: https://layuion.com/layer/
|
||||
|
||||
DropzoneJS: https://www.dropzonejs.com
|
||||
|
||||
|
|
@ -92,6 +88,6 @@ FastAdmin遵循Apache2开源协议发布,并提供免费使用。
|
|||
|
||||
本项目包含的第三方源码和二进制文件之版权信息另行标注。
|
||||
|
||||
版权所有Copyright © 2017-2020 by FastAdmin (https://www.fastadmin.net)
|
||||
版权所有Copyright © 2017-2024 by FastAdmin (https://www.fastadmin.net)
|
||||
|
||||
All rights reserved。
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace app\admin\behavior;
|
|||
|
||||
class AdminLog
|
||||
{
|
||||
public function run(&$params)
|
||||
public function run(&$response)
|
||||
{
|
||||
//只记录POST请求的日志
|
||||
if (request()->isPost() && config('fastadmin.auto_record_log')) {
|
||||
|
|
|
|||
|
|
@ -15,23 +15,24 @@ use think\exception\PDOException;
|
|||
|
||||
class Addon extends Command
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('addon')
|
||||
->addOption('name', 'a', Option::VALUE_REQUIRED, 'addon name', null)
|
||||
->addOption('action', 'c', Option::VALUE_REQUIRED, 'action(create/enable/disable/install/uninstall/refresh/upgrade/package/move)', 'create')
|
||||
->addOption('action', 'c', Option::VALUE_REQUIRED, 'action(create/enable/disable/uninstall/refresh/package/move)', 'create')
|
||||
->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override', null)
|
||||
->addOption('release', 'r', Option::VALUE_OPTIONAL, 'addon release version', null)
|
||||
->addOption('uid', 'u', Option::VALUE_OPTIONAL, 'fastadmin uid', null)
|
||||
->addOption('token', 't', Option::VALUE_OPTIONAL, 'fastadmin token', null)
|
||||
->addOption('domain', 'd', Option::VALUE_OPTIONAL, 'domain', null)
|
||||
->addOption('local', 'l', Option::VALUE_OPTIONAL, 'local package', null)
|
||||
->setDescription('Addon manager');
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
\think\Config::load(dirname(dirname(__FILE__)) . DS . 'config.php');
|
||||
$name = $input->getOption('name') ?: '';
|
||||
$action = $input->getOption('action') ?: '';
|
||||
if (stripos($name, 'addons' . DS) !== false) {
|
||||
|
|
@ -48,7 +49,7 @@ class Addon extends Command
|
|||
|
||||
include dirname(__DIR__) . DS . 'common.php';
|
||||
|
||||
if (!$name) {
|
||||
if (!$name && !in_array($action, ['refresh'])) {
|
||||
throw new Exception('Addon name could not be empty');
|
||||
}
|
||||
if (!$action || !in_array($action, ['create', 'disable', 'enable', 'install', 'uninstall', 'refresh', 'upgrade', 'package', 'move'])) {
|
||||
|
|
@ -81,7 +82,6 @@ class Addon extends Command
|
|||
$createTableSql = $result[0]['Create Table'];
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
|
||||
}
|
||||
|
||||
$data = [
|
||||
|
|
@ -132,42 +132,6 @@ class Addon extends Command
|
|||
}
|
||||
$output->info(ucfirst($action) . " Successed!");
|
||||
break;
|
||||
case 'install':
|
||||
//非覆盖模式时如果存在则报错
|
||||
if (is_dir($addonDir) && !$force) {
|
||||
throw new Exception("addon already exists!\nIf you need to install again, use the parameter --force=true ");
|
||||
}
|
||||
//如果存在先移除
|
||||
if (is_dir($addonDir)) {
|
||||
rmdirs($addonDir);
|
||||
}
|
||||
// 获取本地路径
|
||||
$local = $input->getOption('local');
|
||||
try {
|
||||
Service::install($name, 0, ['version' => $release], $local);
|
||||
} catch (AddonException $e) {
|
||||
if ($e->getCode() != -3) {
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
if (!$force) {
|
||||
//如果有冲突文件则提醒
|
||||
$data = $e->getData();
|
||||
foreach ($data['conflictlist'] as $k => $v) {
|
||||
$output->warning($v);
|
||||
}
|
||||
$output->info("Are you sure you want to override all those files? Type 'yes' to continue: ");
|
||||
$line = fgets(defined('STDIN') ? STDIN : fopen('php://stdin', 'r'));
|
||||
if (trim($line) != 'yes') {
|
||||
throw new Exception("Operation is aborted!");
|
||||
}
|
||||
}
|
||||
Service::install($name, 1, ['version' => $release, 'uid' => $uid, 'token' => $token], $local);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
|
||||
$output->info("Install Successed!");
|
||||
break;
|
||||
case 'uninstall':
|
||||
//非覆盖模式时如果存在则报错
|
||||
if (!$force) {
|
||||
|
|
@ -202,10 +166,6 @@ class Addon extends Command
|
|||
Service::refresh();
|
||||
$output->info("Refresh Successed!");
|
||||
break;
|
||||
case 'upgrade':
|
||||
Service::upgrade($name, ['version' => $release, 'uid' => $uid, 'token' => $token]);
|
||||
$output->info("Upgrade Successed!");
|
||||
break;
|
||||
case 'package':
|
||||
$infoFile = $addonDir . 'info.ini';
|
||||
if (!is_file($infoFile)) {
|
||||
|
|
@ -216,12 +176,12 @@ class Addon extends Command
|
|||
if (!$info) {
|
||||
throw new Exception(__('Addon info file data incorrect'));
|
||||
}
|
||||
$infoname = isset($info['name']) ? $info['name'] : '';
|
||||
$infoname = $info['name'] ?? '';
|
||||
if (!$infoname || !preg_match("/^[a-z]+$/i", $infoname) || $infoname != $name) {
|
||||
throw new Exception(__('Addon info name incorrect'));
|
||||
}
|
||||
|
||||
$infoversion = isset($info['version']) ? $info['version'] : '';
|
||||
$infoversion = $info['version'] ?? '';
|
||||
if (!$infoversion || !preg_match("/^\d+\.\d+\.\d+$/i", $infoversion)) {
|
||||
throw new Exception(__('Addon info version incorrect'));
|
||||
}
|
||||
|
|
@ -256,8 +216,8 @@ class Addon extends Command
|
|||
case 'move':
|
||||
$movePath = [
|
||||
'adminOnlySelfDir' => ['admin/behavior', 'admin/controller', 'admin/library', 'admin/model', 'admin/validate', 'admin/view'],
|
||||
'adminAllSubDir' => ['admin/lang'],
|
||||
'publicDir' => ['public/assets/addons', 'public/assets/js/backend']
|
||||
'adminAllSubDir' => ['admin/lang'],
|
||||
'publicDir' => ['public/assets/addons', 'public/assets/js/backend']
|
||||
];
|
||||
$paths = [];
|
||||
$appPath = str_replace('/', DS, APP_PATH);
|
||||
|
|
@ -350,7 +310,7 @@ class Addon extends Command
|
|||
/**
|
||||
* 写入到文件
|
||||
* @param string $name
|
||||
* @param array $data
|
||||
* @param array $data
|
||||
* @param string $pathname
|
||||
* @return mixed
|
||||
*/
|
||||
|
|
@ -379,5 +339,4 @@ class Addon extends Command
|
|||
{
|
||||
return __DIR__ . '/Addon/stubs/' . $name . '.stub';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,18 +51,4 @@ class {%addonClassName%} extends Addons
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现钩子方法
|
||||
* @return mixed
|
||||
*/
|
||||
public function testhook($param)
|
||||
{
|
||||
// 调用钩子时候的参数信息
|
||||
print_r($param);
|
||||
// 当前插件的配置信息,配置信息存在当前目录的config.php文件中,见下方
|
||||
print_r($this->getConfig());
|
||||
// 可以返回模板,模板文件默认读取的为插件目录中的文件。模板名不能为空!
|
||||
//return $this->fetch('view/info');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,17 +3,21 @@
|
|||
return [
|
||||
[
|
||||
//配置唯一标识
|
||||
'name' => 'usernmae',
|
||||
'name' => 'username',
|
||||
//显示的标题
|
||||
'title' => '用户名',
|
||||
//类型
|
||||
'type' => 'string',
|
||||
//分组
|
||||
'group' => '',
|
||||
//动态显示
|
||||
'visible' => '',
|
||||
//数据字典
|
||||
'content' => [
|
||||
],
|
||||
//值
|
||||
'value' => '',
|
||||
//验证规则
|
||||
//验证规则
|
||||
'rule' => 'required',
|
||||
//错误消息
|
||||
'msg' => '',
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
name = {%name%}
|
||||
title = 插件名称{%name%}
|
||||
intro = FastAdmin插件
|
||||
intro = 插件介绍
|
||||
author = yourname
|
||||
website = https://www.fastadmin.net
|
||||
version = 1.0.0
|
||||
state = 1
|
||||
state = 1
|
||||
|
|
|
|||
|
|
@ -98,13 +98,13 @@ class Api extends Command
|
|||
foreach ($files as $name => $file) {
|
||||
if (!$file->isDir() && $file->getExtension() == 'php') {
|
||||
$filePath = $file->getRealPath();
|
||||
$classes[] = $this->get_class_from_file($filePath);
|
||||
$classes[] = $this->getClassFromFile($filePath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($controller as $index => $item) {
|
||||
$filePath = $moduleDir . Config::get('url_controller_layer') . DS . $item . '.php';
|
||||
$classes[] = $this->get_class_from_file($filePath);
|
||||
$classes[] = $this->getClassFromFile($filePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -129,67 +129,61 @@ class Api extends Command
|
|||
}
|
||||
|
||||
/**
|
||||
* get full qualified class name
|
||||
* 从文件获取命名空间和类名
|
||||
*
|
||||
* @param string $path_to_file
|
||||
* @param string $filename
|
||||
* @return string
|
||||
* @author JBYRNE http://jarretbyrne.com/2015/06/197/
|
||||
*/
|
||||
protected function get_class_from_file($path_to_file)
|
||||
protected function getClassFromFile($filename)
|
||||
{
|
||||
//Grab the contents of the file
|
||||
$contents = file_get_contents($path_to_file);
|
||||
|
||||
//Start with a blank namespace and class
|
||||
$namespace = $class = "";
|
||||
|
||||
//Set helper values to know that we have found the namespace/class token and need to collect the string values after them
|
||||
$getting_namespace = $getting_class = false;
|
||||
|
||||
//Go through each token and evaluate it as necessary
|
||||
foreach (token_get_all($contents) as $token) {
|
||||
|
||||
//If this token is the namespace declaring, then flag that the next tokens will be the namespace name
|
||||
if (is_array($token) && $token[0] == T_NAMESPACE) {
|
||||
$getting_namespace = true;
|
||||
}
|
||||
|
||||
//If this token is the class declaring, then flag that the next tokens will be the class name
|
||||
if (is_array($token) && $token[0] == T_CLASS) {
|
||||
$getting_class = true;
|
||||
}
|
||||
|
||||
//While we're grabbing the namespace name...
|
||||
if ($getting_namespace === true) {
|
||||
|
||||
//If the token is a string or the namespace separator...
|
||||
if (is_array($token) && in_array($token[0], [T_STRING, T_NS_SEPARATOR])) {
|
||||
|
||||
//Append the token's value to the name of the namespace
|
||||
$namespace .= $token[1];
|
||||
} elseif ($token === ';') {
|
||||
|
||||
//If the token is the semicolon, then we're done with the namespace declaration
|
||||
$getting_namespace = false;
|
||||
}
|
||||
}
|
||||
|
||||
//While we're grabbing the class name...
|
||||
if ($getting_class === true) {
|
||||
|
||||
//If the token is a string, it's the name of the class
|
||||
if (is_array($token) && $token[0] == T_STRING) {
|
||||
|
||||
//Store the token's value as the class name
|
||||
$class = $token[1];
|
||||
|
||||
//Got what we need, stope here
|
||||
break;
|
||||
$getNext = null;
|
||||
$isNamespace = false;
|
||||
$skipNext = false;
|
||||
$namespace = '';
|
||||
$class = '';
|
||||
foreach (\PhpToken::tokenize(file_get_contents($filename)) as $token) {
|
||||
if (!$token->isIgnorable()) {
|
||||
$name = $token->getTokenName();
|
||||
switch ($name) {
|
||||
case 'T_NAMESPACE':
|
||||
$isNamespace = true;
|
||||
break;
|
||||
case 'T_EXTENDS':
|
||||
case 'T_USE':
|
||||
case 'T_IMPLEMENTS':
|
||||
$skipNext = true;
|
||||
break;
|
||||
case 'T_CLASS':
|
||||
if ($skipNext) {
|
||||
$skipNext = false;
|
||||
} else {
|
||||
$getNext = strtolower(substr($name, 2));
|
||||
}
|
||||
break;
|
||||
case 'T_NAME_QUALIFIED':
|
||||
case 'T_NS_SEPARATOR':
|
||||
case 'T_STRING':
|
||||
case ';':
|
||||
if ($isNamespace) {
|
||||
if ($name == ';') {
|
||||
$isNamespace = false;
|
||||
} else {
|
||||
$namespace .= $token->text;
|
||||
}
|
||||
} elseif ($skipNext) {
|
||||
$skipNext = false;
|
||||
} elseif ($getNext == 'class') {
|
||||
$class = $token->text;
|
||||
$getNext = null;
|
||||
break 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$getNext = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Build the fully-qualified class name and return it
|
||||
return $namespace ? $namespace . '\\' . $class : $class;
|
||||
return $namespace . '\\' . $class;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use think\Config;
|
|||
/**
|
||||
* @website https://github.com/calinrada/php-apidoc
|
||||
* @author Calin Rada <rada.calin@gmail.com>
|
||||
* @author Karson <karsonzhang@163.com>
|
||||
* @author Karson <karson@fastadmin.net>
|
||||
*/
|
||||
class Builder
|
||||
{
|
||||
|
|
@ -88,11 +88,17 @@ class Builder
|
|||
return [];
|
||||
}
|
||||
|
||||
$typeArr = [
|
||||
'integer' => 'number',
|
||||
'file' => 'file',
|
||||
];
|
||||
$paramslist = array();
|
||||
foreach ($docs['ApiParams'] as $params) {
|
||||
$inputtype = $params['type'] && isset($typeArr[$params['type']]) ? $typeArr[$params['type']] : ($params['name'] == 'password' ? 'password' : 'text');
|
||||
$tr = array(
|
||||
'name' => $params['name'],
|
||||
'type' => $params['type'] ?? 'string',
|
||||
'inputtype' => $inputtype,
|
||||
'sample' => $params['sample'] ?? '',
|
||||
'required' => $params['required'] ?? true,
|
||||
'description' => $params['description'] ?? '',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{$config.language}">
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
|
@ -8,15 +8,15 @@
|
|||
<title>{$config.title}</title>
|
||||
|
||||
<!-- Bootstrap Core CSS -->
|
||||
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Plugin CSS -->
|
||||
<link href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<link href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
|
||||
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://cdn.staticfile.org/html5shiv/3.7.3/html5shiv.min.js"></script>
|
||||
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
|
||||
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/html5shiv/3.7.3/html5shiv.min.js"></script>
|
||||
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<style type="text/css">
|
||||
|
|
@ -137,7 +137,7 @@
|
|||
Apiurl:
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input id="apiUrl" type="text" class="form-control input-sm" data-toggle="tooltip" title="{$lang.Apiurltips}" placeholder="https://api.mydomain.com" value="{$config.apiurl}" />
|
||||
<input id="apiUrl" type="text" class="form-control input-sm" data-toggle="tooltip" title="{$lang.Apiurltips}" placeholder="https://api.example.com" value="{$config.apiurl}" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn btn-success btn-sm" data-toggle="tooltip" title="{$lang.Savetips}" id="save_data">
|
||||
|
|
@ -295,7 +295,7 @@
|
|||
{foreach name="api['headersList']" id="param"}
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="{$param.name}">{$param.name}</label>
|
||||
<input type="{$param.type}" class="form-control input-sm" id="{$param.name}" {if $param.required}required{/if} placeholder="{$param.description} - Ex: {$param.sample}" name="{$param.name}">
|
||||
<input type="{$param.inputtype|default='text'}" class="form-control input-sm" id="{$param.name}" {if $param.required}required{/if} placeholder="{$param.description} - Ex: {$param.sample}" name="{$param.name}">
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
|
|
@ -314,7 +314,7 @@
|
|||
{foreach name="api['paramsList']" id="param"}
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="{$param.name}">{$param.name}</label>
|
||||
<input type="{$param.type}" class="form-control input-sm" id="{$param.name}" {if $param.required}required{/if} placeholder="{$param.description}{if $param.sample} - 例: {$param.sample}{/if}" name="{$param.name}">
|
||||
<input type="{$param.inputtype|default='text'}" class="form-control input-sm" id="{$param.name}" {if $param.required}required{/if} placeholder="{$param.description}{if $param.sample} - 例: {$param.sample}{/if}" name="{$param.name}">
|
||||
</div>
|
||||
{/foreach}
|
||||
{else /}
|
||||
|
|
@ -401,10 +401,10 @@
|
|||
</div> <!-- /container -->
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="https://cdn.staticfile.org/jquery/2.1.4/jquery.min.js"></script>
|
||||
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js"></script>
|
||||
|
||||
<!-- Bootstrap Core JavaScript -->
|
||||
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
function syntaxHighlight(json) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use think\console\Output;
|
|||
use think\Db;
|
||||
use think\Exception;
|
||||
use think\exception\ErrorException;
|
||||
use think\exception\PDOException;
|
||||
use think\Lang;
|
||||
use think\Loader;
|
||||
|
||||
|
|
@ -19,16 +20,91 @@ class Crud extends Command
|
|||
protected $stubList = [];
|
||||
|
||||
protected $internalKeywords = [
|
||||
'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor'
|
||||
'abstract',
|
||||
'and',
|
||||
'array',
|
||||
'as',
|
||||
'break',
|
||||
'callable',
|
||||
'case',
|
||||
'catch',
|
||||
'class',
|
||||
'clone',
|
||||
'const',
|
||||
'continue',
|
||||
'declare',
|
||||
'default',
|
||||
'die',
|
||||
'do',
|
||||
'echo',
|
||||
'else',
|
||||
'elseif',
|
||||
'empty',
|
||||
'enddeclare',
|
||||
'endfor',
|
||||
'endforeach',
|
||||
'endif',
|
||||
'endswitch',
|
||||
'endwhile',
|
||||
'eval',
|
||||
'exit',
|
||||
'extends',
|
||||
'final',
|
||||
'for',
|
||||
'foreach',
|
||||
'function',
|
||||
'global',
|
||||
'goto',
|
||||
'if',
|
||||
'implements',
|
||||
'include',
|
||||
'include_once',
|
||||
'instanceof',
|
||||
'insteadof',
|
||||
'interface',
|
||||
'isset',
|
||||
'list',
|
||||
'namespace',
|
||||
'new',
|
||||
'or',
|
||||
'print',
|
||||
'private',
|
||||
'protected',
|
||||
'public',
|
||||
'require',
|
||||
'require_once',
|
||||
'return',
|
||||
'static',
|
||||
'switch',
|
||||
'throw',
|
||||
'trait',
|
||||
'try',
|
||||
'unset',
|
||||
'use',
|
||||
'var',
|
||||
'while',
|
||||
'xor'
|
||||
];
|
||||
|
||||
/**
|
||||
* 受保护的系统表, crud不会生效
|
||||
*/
|
||||
protected $systemTables = [
|
||||
'admin', 'admin_log', 'auth_group', 'auth_group_access', 'auth_rule',
|
||||
'attachment', 'config', 'category', 'ems', 'sms',
|
||||
'user', 'user_group', 'user_rule', 'user_score_log', 'user_token',
|
||||
'admin',
|
||||
'admin_log',
|
||||
'auth_group',
|
||||
'auth_group_access',
|
||||
'auth_rule',
|
||||
'attachment',
|
||||
'config',
|
||||
'category',
|
||||
'ems',
|
||||
'sms',
|
||||
'user',
|
||||
'user_group',
|
||||
'user_rule',
|
||||
'user_score_log',
|
||||
'user_token',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -68,10 +144,20 @@ class Crud extends Command
|
|||
*/
|
||||
protected $citySuffix = ['city'];
|
||||
|
||||
/**
|
||||
* 时间区间后缀
|
||||
*/
|
||||
protected $rangeSuffix = ['range'];
|
||||
|
||||
/**
|
||||
* JSON后缀
|
||||
*/
|
||||
protected $jsonSuffix = ['json'];
|
||||
protected $jsonSuffix = ['json', 'array'];
|
||||
|
||||
/**
|
||||
* 标签后缀
|
||||
*/
|
||||
protected $tagSuffix = ['tag', 'tags'];
|
||||
|
||||
/**
|
||||
* Selectpage对应的后缀
|
||||
|
|
@ -93,9 +179,13 @@ class Crud extends Command
|
|||
'url' => 'url',
|
||||
'image' => 'image',
|
||||
'images' => 'images',
|
||||
'file' => 'file',
|
||||
'files' => 'files',
|
||||
'avatar' => 'image',
|
||||
'switch' => 'toggle',
|
||||
'time' => ['type' => ['int', 'timestamp'], 'name' => 'datetime']
|
||||
'tag' => 'flag',
|
||||
'tags' => 'flag',
|
||||
'time' => ['type' => ['int', 'bigint', 'timestamp'], 'name' => 'datetime'],
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -167,12 +257,14 @@ class Crud extends Command
|
|||
->addOption('fields', 'i', Option::VALUE_OPTIONAL, 'model visible fields', null)
|
||||
->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override or force delete,without tips', null)
|
||||
->addOption('local', 'l', Option::VALUE_OPTIONAL, 'local model', 1)
|
||||
->addOption('import', 'a', Option::VALUE_OPTIONAL, 'enable import function', 0)
|
||||
->addOption('relation', 'r', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation table name without prefix', null)
|
||||
->addOption('relationmodel', 'e', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation model name', null)
|
||||
->addOption('relationforeignkey', 'k', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation foreign key', null)
|
||||
->addOption('relationprimarykey', 'p', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation primary key', null)
|
||||
->addOption('relationfields', 's', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation table fields', null)
|
||||
->addOption('relationmode', 'o', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation table mode,hasone or belongsto', null)
|
||||
->addOption('relationmode', 'o', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation table mode,hasone/belongsto/hasmany', null)
|
||||
->addOption('relationcontroller', 'w', Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'relation table controller,only work at hasmany mode', null)
|
||||
->addOption('delete', 'd', Option::VALUE_OPTIONAL, 'delete all files generated by CRUD', null)
|
||||
->addOption('menu', 'u', Option::VALUE_OPTIONAL, 'create menu when CRUD completed', null)
|
||||
->addOption('setcheckboxsuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate checkbox component with suffix', null)
|
||||
|
|
@ -183,12 +275,14 @@ class Crud extends Command
|
|||
->addOption('switchsuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate switch component with suffix', null)
|
||||
->addOption('citysuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate citypicker component with suffix', null)
|
||||
->addOption('jsonsuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate fieldlist component with suffix', null)
|
||||
->addOption('tagsuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate tag component with suffix', null)
|
||||
->addOption('editorsuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate editor component with suffix', null)
|
||||
->addOption('selectpagesuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate selectpage component with suffix', null)
|
||||
->addOption('selectpagessuffix', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'automatically generate multiple selectpage component with suffix', null)
|
||||
->addOption('ignorefields', null, Option::VALUE_OPTIONAL | Option::VALUE_IS_ARRAY, 'ignore fields', null)
|
||||
->addOption('sortfield', null, Option::VALUE_OPTIONAL, 'sort field', null)
|
||||
->addOption('headingfilterfield', null, Option::VALUE_OPTIONAL, 'heading filter field', null)
|
||||
->addOption('fixedcolumns', null, Option::VALUE_OPTIONAL, 'fixed columns', null)
|
||||
->addOption('editorclass', null, Option::VALUE_OPTIONAL, 'automatically generate editor class', null)
|
||||
->addOption('db', null, Option::VALUE_OPTIONAL, 'database config name', 'database')
|
||||
->setDescription('Build CRUD controller and model from table');
|
||||
|
|
@ -214,12 +308,14 @@ class Crud extends Command
|
|||
$force = $input->getOption('force');
|
||||
//是否为本地model,为0时表示为全局model将会把model放在app/common/model中
|
||||
$local = $input->getOption('local');
|
||||
|
||||
//是否启用导入功能
|
||||
$import = $input->getOption('import');
|
||||
|
||||
if (!$table) {
|
||||
throw new Exception('table name can\'t empty');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//是否生成菜单
|
||||
$menu = $input->getOption("menu");
|
||||
//关联表
|
||||
|
|
@ -234,6 +330,8 @@ class Crud extends Command
|
|||
$relationPrimaryKey = $input->getOption('relationprimarykey');
|
||||
//关联表显示字段
|
||||
$relationFields = $input->getOption('relationfields');
|
||||
//关联表显示字段
|
||||
$relationController = $input->getOption('relationcontroller');
|
||||
//复选框后缀
|
||||
$setcheckboxsuffix = $input->getOption('setcheckboxsuffix');
|
||||
//单选框后缀
|
||||
|
|
@ -242,10 +340,14 @@ class Crud extends Command
|
|||
$imagefield = $input->getOption('imagefield');
|
||||
//文件后缀
|
||||
$filefield = $input->getOption('filefield');
|
||||
//标签后缀
|
||||
$tagsuffix = $input->getOption('tagsuffix');
|
||||
//日期后缀
|
||||
$intdatesuffix = $input->getOption('intdatesuffix');
|
||||
//开关后缀
|
||||
$switchsuffix = $input->getOption('switchsuffix');
|
||||
//富文本编辑器
|
||||
$editorsuffix = $input->getOption('editorsuffix');
|
||||
//城市后缀
|
||||
$citysuffix = $input->getOption('citysuffix');
|
||||
//JSON配置后缀
|
||||
|
|
@ -260,6 +362,8 @@ class Crud extends Command
|
|||
$sortfield = $input->getOption('sortfield');
|
||||
//顶部筛选过滤字段
|
||||
$headingfilterfield = $input->getOption('headingfilterfield');
|
||||
//固定列数量
|
||||
$fixedcolumns = $input->getOption('fixedcolumns');
|
||||
//编辑器Class
|
||||
$editorclass = $input->getOption('editorclass');
|
||||
if ($setcheckboxsuffix) {
|
||||
|
|
@ -274,12 +378,18 @@ class Crud extends Command
|
|||
if ($filefield) {
|
||||
$this->fileField = $filefield;
|
||||
}
|
||||
if ($tagsuffix) {
|
||||
$this->tagSuffix = $tagsuffix;
|
||||
}
|
||||
if ($intdatesuffix) {
|
||||
$this->intDateSuffix = $intdatesuffix;
|
||||
}
|
||||
if ($switchsuffix) {
|
||||
$this->switchSuffix = $switchsuffix;
|
||||
}
|
||||
if ($editorsuffix) {
|
||||
$this->editorSuffix = $editorsuffix;
|
||||
}
|
||||
if ($citysuffix) {
|
||||
$this->citySuffix = $citysuffix;
|
||||
}
|
||||
|
|
@ -312,7 +422,7 @@ class Crud extends Command
|
|||
$prefix = Config::get($db . '.prefix');
|
||||
|
||||
//系统表无法生成,防止后台错乱
|
||||
if(in_array(str_replace($prefix,"",$table),$this->systemTables)){
|
||||
if (in_array(str_replace($prefix, "", $table), $this->systemTables)) {
|
||||
throw new Exception('system table can\'t be crud');
|
||||
}
|
||||
|
||||
|
|
@ -325,16 +435,19 @@ class Crud extends Command
|
|||
$modelName = $table = stripos($table, $prefix) === 0 ? substr($table, strlen($prefix)) : $table;
|
||||
$modelTableType = 'table';
|
||||
$modelTableTypeName = $modelTableName = $modelName;
|
||||
$modelTableInfo = $dbconnect->query("SHOW TABLE STATUS LIKE '{$modelTableName}'", [], true);
|
||||
if (!$modelTableInfo) {
|
||||
$modelTableType = 'name';
|
||||
$modelTableName = $prefix . $modelName;
|
||||
$modelTableInfo = null;
|
||||
if (!$input->getOption('delete')) {
|
||||
$modelTableInfo = $dbconnect->query("SHOW TABLE STATUS LIKE '{$modelTableName}'", [], true);
|
||||
if (!$modelTableInfo) {
|
||||
throw new Exception("table not found");
|
||||
$modelTableType = 'name';
|
||||
$modelTableName = $prefix . $modelName;
|
||||
$modelTableInfo = $dbconnect->query("SHOW TABLE STATUS LIKE '{$modelTableName}'", [], true);
|
||||
if (!$modelTableInfo) {
|
||||
throw new Exception("table not found");
|
||||
}
|
||||
}
|
||||
$modelTableInfo = $modelTableInfo[0];
|
||||
}
|
||||
$modelTableInfo = $modelTableInfo[0];
|
||||
|
||||
$relations = [];
|
||||
//检查关联表
|
||||
|
|
@ -356,7 +469,7 @@ class Crud extends Command
|
|||
}
|
||||
}
|
||||
$relationTableInfo = $relationTableInfo[0];
|
||||
$relationModel = isset($relationModels[$index]) ? $relationModels[$index] : '';
|
||||
$relationModel = $relationModels[$index] ?? '';
|
||||
|
||||
list($relationNamespace, $relationName, $relationFile) = $this->getModelData($modelModuleName, $relationModel, $relationName);
|
||||
|
||||
|
|
@ -381,8 +494,10 @@ class Crud extends Command
|
|||
'relationFields' => isset($relationFields[$index]) ? explode(',', $relationFields[$index]) : [],
|
||||
//关联模式
|
||||
'relationMode' => isset($relationMode[$index]) ? $relationMode[$index] : 'belongsto',
|
||||
//关联模型控制器
|
||||
'relationController' => isset($relationController[$index]) ? $relationController[$index] : '',
|
||||
//关联表外键
|
||||
'relationForeignKey' => isset($relationForeignKey[$index]) ? $relationForeignKey[$index] : Loader::parseName($relationName) . '_id',
|
||||
'relationForeignKey' => isset($relationForeignKey[$index]) ? $relationForeignKey[$index] : '',
|
||||
//关联表主键
|
||||
'relationPrimaryKey' => isset($relationPrimaryKey[$index]) ? $relationPrimaryKey[$index] : '',
|
||||
];
|
||||
|
|
@ -405,7 +520,8 @@ class Crud extends Command
|
|||
$baseFileName = Loader::parseName(array_pop($baseNameArr), 0);
|
||||
array_push($baseNameArr, $baseFileName);
|
||||
$controllerBaseName = strtolower(implode(DS, $baseNameArr));
|
||||
$controllerUrl = strtolower(implode('/', $baseNameArr));
|
||||
//$controllerUrl = strtolower(implode('/', $baseNameArr));
|
||||
$controllerUrl = $this->getControllerUrl($moduleName, $baseNameArr);
|
||||
|
||||
//视图文件
|
||||
$viewArr = $controllerArr;
|
||||
|
|
@ -529,28 +645,32 @@ class Crud extends Command
|
|||
$editList = [];
|
||||
$javascriptList = [];
|
||||
$langList = [];
|
||||
$operateButtonList = [];
|
||||
$field = 'id';
|
||||
$order = 'id';
|
||||
$priDefined = false;
|
||||
$priKey = '';
|
||||
$priKeyArr = [];
|
||||
$relationPrimaryKey = '';
|
||||
foreach ($columnList as $k => $v) {
|
||||
if ($v['COLUMN_KEY'] == 'PRI') {
|
||||
$priKey = $v['COLUMN_NAME'];
|
||||
break;
|
||||
$priKeyArr[] = $v['COLUMN_NAME'];
|
||||
}
|
||||
}
|
||||
if (!$priKey) {
|
||||
if (!$priKeyArr) {
|
||||
throw new Exception('Primary key not found!');
|
||||
}
|
||||
if (count($priKeyArr) > 1) {
|
||||
throw new Exception('Multiple primary key not support!');
|
||||
}
|
||||
$priKey = reset($priKeyArr);
|
||||
|
||||
$order = $priKey;
|
||||
|
||||
//如果是关联模型
|
||||
foreach ($relations as $index => &$relation) {
|
||||
if ($relation['relationMode'] == 'hasone') {
|
||||
$relationForeignKey = $relation['relationForeignKey'] ? $relation['relationForeignKey'] : $table . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ? $relation['relationPrimaryKey'] : $priKey;
|
||||
$relationForeignKey = $relation['relationForeignKey'] ?: $table . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ?: $priKey;
|
||||
|
||||
if (!in_array($relationForeignKey, $relation['relationFieldList'])) {
|
||||
throw new Exception('relation table [' . $relation['relationTableName'] . '] must be contain field [' . $relationForeignKey . ']');
|
||||
|
|
@ -558,15 +678,26 @@ class Crud extends Command
|
|||
if (!in_array($relationPrimaryKey, $fieldArr)) {
|
||||
throw new Exception('table [' . $modelTableName . '] must be contain field [' . $relationPrimaryKey . ']');
|
||||
}
|
||||
} else {
|
||||
$relationForeignKey = $relation['relationForeignKey'] ? $relation['relationForeignKey'] : Loader::parseName($relation['relationName']) . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ? $relation['relationPrimaryKey'] : $relation['relationPriKey'];
|
||||
} elseif ($relation['relationMode'] == 'belongsto') {
|
||||
$relationForeignKey = $relation['relationForeignKey'] ?: Loader::parseName($relation['relationName']) . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ?: $relation['relationPriKey'];
|
||||
if (!in_array($relationForeignKey, $fieldArr)) {
|
||||
throw new Exception('table [' . $modelTableName . '] must be contain field [' . $relationForeignKey . ']');
|
||||
}
|
||||
if (!in_array($relationPrimaryKey, $relation['relationFieldList'])) {
|
||||
throw new Exception('relation table [' . $relation['relationTableName'] . '] must be contain field [' . $relationPrimaryKey . ']');
|
||||
}
|
||||
} elseif ($relation['relationMode'] == 'hasmany') {
|
||||
$relationForeignKey = $relation['relationForeignKey'] ?: $table . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ?: $priKey;
|
||||
if (!in_array($relationForeignKey, $relation['relationFieldList'])) {
|
||||
throw new Exception('relation table [' . $relation['relationTableName'] . '] must be contain field [' . $relationForeignKey . ']');
|
||||
}
|
||||
if (!in_array($relationPrimaryKey, $fieldArr)) {
|
||||
throw new Exception('table [' . $modelTableName . '] must be contain field [' . $relationPrimaryKey . ']');
|
||||
}
|
||||
$relation['relationColumnList'] = [];
|
||||
$relation['relationFieldList'] = [];
|
||||
}
|
||||
$relation['relationForeignKey'] = $relationForeignKey;
|
||||
$relation['relationPrimaryKey'] = $relationPrimaryKey;
|
||||
|
|
@ -582,21 +713,29 @@ class Crud extends Command
|
|||
$appendAttrList = [];
|
||||
$controllerAssignList = [];
|
||||
$headingHtml = '{:build_heading()}';
|
||||
$controllerImport = '';
|
||||
$importHtml = '';
|
||||
$multipleHtml = '';
|
||||
$recyclebinHtml = '';
|
||||
|
||||
if ($import) {
|
||||
$controllerImport = $this->getReplacedStub('mixins/import', []);
|
||||
$importHtml = '<a href="javascript:;" class="btn btn-danger btn-import {:$auth->check(\'' . $controllerUrl . '/import\')?\'\':\'hide\'}" title="{:__(\'Import\')}" id="btn-import-file" data-url="ajax/upload" data-mimetype="csv,xls,xlsx" data-multiple="false"><i class="fa fa-upload"></i> {:__(\'Import\')}</a>';
|
||||
}
|
||||
|
||||
//循环所有字段,开始构造视图的HTML和JS信息
|
||||
foreach ($columnList as $k => $v) {
|
||||
$field = $v['COLUMN_NAME'];
|
||||
$itemArr = [];
|
||||
// 这里构建Enum和Set类型的列表数据
|
||||
if (in_array($v['DATA_TYPE'], ['enum', 'set', 'tinyint'])) {
|
||||
if (in_array($v['DATA_TYPE'], ['enum', 'set', 'tinyint']) || $this->headingFilterField == $field) {
|
||||
if ($v['DATA_TYPE'] !== 'tinyint') {
|
||||
$itemArr = substr($v['COLUMN_TYPE'], strlen($v['DATA_TYPE']) + 1, -1);
|
||||
$itemArr = explode(',', str_replace("'", '', $itemArr));
|
||||
}
|
||||
$itemArr = $this->getItemArray($itemArr, $field, $v['COLUMN_COMMENT']);
|
||||
//如果类型为tinyint且有使用备注数据
|
||||
if ($itemArr && $v['DATA_TYPE'] == 'tinyint') {
|
||||
if ($itemArr && !in_array($v['DATA_TYPE'], ['enum', 'set'])) {
|
||||
$v['DATA_TYPE'] = 'enum';
|
||||
}
|
||||
}
|
||||
|
|
@ -685,6 +824,14 @@ class Crud extends Command
|
|||
$attrArr['data-use-current'] = "true";
|
||||
$formAddElement = Form::text($fieldName, $defaultDateTime, $attrArr);
|
||||
$formEditElement = Form::text($fieldName, ($fieldFunc ? "{:\$row.{$field}?{$fieldFunc}(\$row.{$field}):''}" : "{\$row.{$field}{$fieldFunc}}"), $attrArr);
|
||||
} elseif ($inputType == 'datetimerange') {
|
||||
$cssClassArr[] = 'datetimerange';
|
||||
$attrArr['class'] = implode(' ', $cssClassArr);
|
||||
$attrArr['data-locale'] = '{"format":"YYYY-MM-DD HH:mm:ss"}';
|
||||
$fieldFunc = '';
|
||||
$defaultDateTime = "";
|
||||
$formAddElement = Form::text($fieldName, $defaultDateTime, $attrArr);
|
||||
$formEditElement = Form::text($fieldName, $editValue, $attrArr);
|
||||
} elseif ($inputType == 'checkbox' || $inputType == 'radio') {
|
||||
unset($attrArr['data-rule']);
|
||||
$fieldName = $inputType == 'checkbox' ? $fieldName .= "[]" : $fieldName;
|
||||
|
|
@ -728,12 +875,25 @@ class Crud extends Command
|
|||
$attrArr['data-toggle'] = "city-picker";
|
||||
$formAddElement = sprintf("<div class='control-relative'>%s</div>", Form::input('text', $fieldName, $defaultValue, $attrArr));
|
||||
$formEditElement = sprintf("<div class='control-relative'>%s</div>", Form::input('text', $fieldName, $editValue, $attrArr));
|
||||
} elseif ($inputType == 'tagsinput') {
|
||||
$attrArr['class'] = implode(' ', $cssClassArr);
|
||||
$attrArr['data-role'] = "tagsinput";
|
||||
$formAddElement = Form::input('text', $fieldName, $defaultValue, $attrArr);
|
||||
$formEditElement = Form::input('text', $fieldName, $editValue, $attrArr);
|
||||
} elseif ($inputType == 'fieldlist') {
|
||||
$itemArr = $this->getItemArray($itemArr, $field, $v['COLUMN_COMMENT']);
|
||||
$templateName = !isset($itemArr['key']) && count($itemArr) > 0 ? (isset($itemArr['value']) && count($itemArr) === 1 ? 'fieldlist-array' : 'fieldlist-template') : 'fieldlist';
|
||||
$itemKey = isset($itemArr['key']) ? ucfirst($itemArr['key']) : 'Key';
|
||||
$itemValue = isset($itemArr['value']) ? ucfirst($itemArr['value']) : 'Value';
|
||||
$formAddElement = $this->getReplacedStub('html/' . $inputType, ['field' => $field, 'fieldName' => $fieldName, 'itemKey' => $itemKey, 'itemValue' => $itemValue, 'fieldValue' => $defaultValue]);
|
||||
$formEditElement = $this->getReplacedStub('html/' . $inputType, ['field' => $field, 'fieldName' => $fieldName, 'itemKey' => $itemKey, 'itemValue' => $itemValue, 'fieldValue' => $editValue]);
|
||||
$theadListArr = $tbodyListArr = [];
|
||||
foreach ($itemArr as $index => $item) {
|
||||
$theadListArr[] = "<td>{:__('" . $item . "')}</td>";
|
||||
$tbodyListArr[] = '<td><input type="text" name="<%=name%>[<%=index%>][' . $index . ']" class="form-control" value="<%=row.' . $index . '%>"/></td>';
|
||||
}
|
||||
$colspan = count($theadListArr) + 1;
|
||||
$commonFields = ['field' => $field, 'fieldName' => $fieldName, 'itemKey' => $itemKey, 'itemValue' => $itemValue, 'theadList' => implode("\n", $theadListArr), 'tbodyList' => implode("\n", $tbodyListArr), 'colspan' => $colspan];
|
||||
$formAddElement = $this->getReplacedStub('html/' . $templateName, array_merge($commonFields, ['fieldValue' => $defaultValue]));
|
||||
$formEditElement = $this->getReplacedStub('html/' . $templateName, array_merge($commonFields, ['fieldValue' => $editValue]));
|
||||
} else {
|
||||
$search = $replace = '';
|
||||
//特殊字段为关联搜索
|
||||
|
|
@ -742,7 +902,15 @@ class Crud extends Command
|
|||
$defaultValue = '';
|
||||
$attrArr['data-rule'] = 'required';
|
||||
$cssClassArr[] = 'selectpage';
|
||||
$selectpageController = str_replace('_', '/', substr($field, 0, strripos($field, '_')));
|
||||
$selectpageTable = substr($field, 0, strripos($field, '_'));
|
||||
$selectpageField = '';
|
||||
foreach ($relations as $index => $relation) {
|
||||
if ($relation['relationForeignKey'] === $field) {
|
||||
$selectpageTable = substr($relation['relationTableName'], strlen($prefix));
|
||||
break;
|
||||
}
|
||||
}
|
||||
$selectpageController = str_replace('_', '/', $selectpageTable);
|
||||
$attrArr['data-source'] = $selectpageController . "/index";
|
||||
//如果是类型表需要特殊处理下
|
||||
if ($selectpageController == 'category') {
|
||||
|
|
@ -754,14 +922,31 @@ class Crud extends Command
|
|||
$attrArr['data-source'] = 'auth/admin/selectpage';
|
||||
} elseif ($selectpageController == 'user') {
|
||||
$attrArr['data-source'] = 'user/user/index';
|
||||
$attrArr['data-field'] = 'nickname';
|
||||
}
|
||||
if ($this->isMatchSuffix($field, $this->selectpagesSuffix)) {
|
||||
$attrArr['data-multiple'] = 'true';
|
||||
}
|
||||
foreach ($this->fieldSelectpageMap as $m => $n) {
|
||||
if (in_array($field, $n)) {
|
||||
$attrArr['data-field'] = $m;
|
||||
break;
|
||||
|
||||
$tableInfo = null;
|
||||
try {
|
||||
$tableInfo = \think\Db::name($selectpageTable)->getTableInfo();
|
||||
if (isset($tableInfo['fields'])) {
|
||||
foreach ($tableInfo['fields'] as $m => $n) {
|
||||
if (in_array($n, ['nickname', 'title', 'name'])) {
|
||||
$selectpageField = $n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
if (!$selectpageField) {
|
||||
foreach ($this->fieldSelectpageMap as $m => $n) {
|
||||
if (in_array($field, $n)) {
|
||||
$attrArr['data-field'] = $m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -781,6 +966,11 @@ class Crud extends Command
|
|||
$attrArr['size'] = 50;
|
||||
}
|
||||
|
||||
//字段默认值判断
|
||||
if ('NULL' == $defaultValue || "''" == $defaultValue) {
|
||||
$defaultValue = '';
|
||||
}
|
||||
|
||||
$formAddElement = Form::input($inputType, $fieldName, $defaultValue, $attrArr);
|
||||
$formEditElement = Form::input($inputType, $fieldName, $editValue, $attrArr);
|
||||
if ($search && $replace) {
|
||||
|
|
@ -811,10 +1001,11 @@ class Crud extends Command
|
|||
}
|
||||
if (!$fields || in_array($field, explode(',', $fields))) {
|
||||
//构造JS列信息
|
||||
$javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], $inputType && in_array($inputType, ['select', 'checkbox', 'radio']) ? '_text' : '', $itemArr);
|
||||
$javascriptList[] = $this->getJsColumn($field, $v['DATA_TYPE'], $inputType && in_array($inputType, ['select', 'checkbox', 'radio']) ? '_text' : '', $itemArr, $v);
|
||||
}
|
||||
if ($this->headingFilterField && $this->headingFilterField == $field && $itemArr) {
|
||||
$headingHtml = $this->getReplacedStub('html/heading-html', ['field' => $field, 'fieldName' => Loader::parseName($field, 1, false)]);
|
||||
$multipleHtml = $this->getReplacedStub('html/multiple-html', ['field' => $field, 'fieldName' => Loader::parseName($field, 1, false), 'controllerUrl' => $controllerUrl]);
|
||||
}
|
||||
//排序方式,如果有指定排序字段,否则按主键排序
|
||||
$order = $field == $this->sortField ? $this->sortField : $order;
|
||||
|
|
@ -823,6 +1014,33 @@ class Crud extends Command
|
|||
|
||||
//循环关联表,追加语言包和JS列
|
||||
foreach ($relations as $index => $relation) {
|
||||
if ($relation['relationMode'] == 'hasmany') {
|
||||
$relationFieldText = ucfirst(strtolower($relation['relationName'])) . ' List';
|
||||
// 语言列表
|
||||
if ($relation['relationTableInfo']['Comment']) {
|
||||
$langList[] = $this->getLangItem($relationFieldText, rtrim($relation['relationTableInfo']['Comment'], "表") . "列表");
|
||||
}
|
||||
|
||||
$relationTableName = $relation['relationTableName'];
|
||||
$relationTableName = stripos($relationTableName, $prefix) === 0 ? substr($relationTableName, strlen($prefix)) : $relationTableName;
|
||||
|
||||
list($realtionControllerNamespace, $realtionControllerName, $realtionControllerFile, $realtionControllerArr) = $this->getControllerData($moduleName, $relation['relationController'], $relationTableName);
|
||||
$realtionControllerArr = array_map("strtolower", $realtionControllerArr);
|
||||
if (count($realtionControllerArr) > 1) {
|
||||
$realtionControllerArr = [implode('.', $realtionControllerArr)];
|
||||
}
|
||||
$realtionControllerArr[] = 'index';
|
||||
$realtionControllerArr[] = $relation['relationForeignKey'] . '/{ids}';
|
||||
$relationControllerUrl = implode('/', $realtionControllerArr);
|
||||
|
||||
//构造JS列信息
|
||||
$operateButtonList[] = "{name: 'addtabs',title: __('{$relationFieldText}'),text: __('{$relationFieldText}'),classname: 'btn btn-xs btn-info btn-dialog',icon: 'fa fa-list',url: '" . $relationControllerUrl . "'}";
|
||||
//echo "php think crud -t {$relation['relationTableName']} -c {$relation['relationController']} -m {$relation['relationModel']} -i " . implode(',', $relation['relationFields']);
|
||||
//不存在关联表控制器的情况下才进行生成
|
||||
if (!is_file($realtionControllerFile)) {
|
||||
exec("php think crud -t {$relation['relationTableName']} -c {$relation['relationController']} -m {$relation['relationModel']} -i " . implode(',', $relation['relationFields']));
|
||||
}
|
||||
}
|
||||
foreach ($relation['relationColumnList'] as $k => $v) {
|
||||
// 不显示的字段直接过滤掉
|
||||
if ($relation['relationFields'] && !in_array($v['COLUMN_NAME'], $relation['relationFields'])) {
|
||||
|
|
@ -838,13 +1056,13 @@ class Crud extends Command
|
|||
//过滤text类型字段
|
||||
if ($v['DATA_TYPE'] != 'text') {
|
||||
//构造JS列信息
|
||||
$javascriptList[] = $this->getJsColumn($relationField, $v['DATA_TYPE']);
|
||||
$javascriptList[] = $this->getJsColumn($relationField, $v['DATA_TYPE'], '', [], $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//JS最后一列加上操作列
|
||||
$javascriptList[] = str_repeat(" ", 24) . "{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}";
|
||||
$javascriptList[] = str_repeat(" ", 24) . "{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, " . ($operateButtonList ? "buttons: [" . implode(',', $operateButtonList) . "], " : "") . "formatter: Table.api.formatter.operate}";
|
||||
$addList = implode("\n", array_filter($addList));
|
||||
$editList = implode("\n", array_filter($editList));
|
||||
$javascriptList = implode(",\n", array_filter($javascriptList));
|
||||
|
|
@ -858,9 +1076,15 @@ class Crud extends Command
|
|||
}
|
||||
unset($line);
|
||||
$langList = implode(",\n", array_filter($langList));
|
||||
$fixedcolumns = count($columnList) >= 10 ? 1 : $fixedcolumns;
|
||||
|
||||
$fixedColumnsJs = '';
|
||||
if (is_numeric($fixedcolumns) && $fixedcolumns) {
|
||||
$fixedColumnsJs = "\n" . str_repeat(" ", 16) . "fixedColumns: true,\n" . str_repeat(" ", 16) . ($fixedcolumns < 0 ? "fixedNumber" : "fixedRightNumber") . ": " . $fixedcolumns . ",";
|
||||
}
|
||||
|
||||
//表注释
|
||||
$tableComment = $modelTableInfo['Comment'];
|
||||
$tableComment = $modelTableInfo ? $modelTableInfo['Comment'] : '';
|
||||
$tableComment = mb_substr($tableComment, -1) == '表' ? mb_substr($tableComment, 0, -1) . '管理' : $tableComment;
|
||||
|
||||
$modelInit = '';
|
||||
|
|
@ -885,6 +1109,7 @@ class Crud extends Command
|
|||
'iconName' => $iconName,
|
||||
'pk' => $priKey,
|
||||
'order' => $order,
|
||||
'fixedColumnsJs' => $fixedColumnsJs,
|
||||
'table' => $table,
|
||||
'tableName' => $modelTableName,
|
||||
'addList' => $addList,
|
||||
|
|
@ -893,18 +1118,21 @@ class Crud extends Command
|
|||
'langList' => $langList,
|
||||
'softDeleteClassPath' => in_array($this->deleteTimeField, $fieldArr) ? "use traits\model\SoftDelete;" : '',
|
||||
'softDelete' => in_array($this->deleteTimeField, $fieldArr) ? "use SoftDelete;" : '',
|
||||
'modelAutoWriteTimestamp' => in_array($this->createTimeField, $fieldArr) || in_array($this->updateTimeField, $fieldArr) ? "'int'" : 'false',
|
||||
'modelAutoWriteTimestamp' => in_array($this->createTimeField, $fieldArr) || in_array($this->updateTimeField, $fieldArr) ? "'integer'" : 'false',
|
||||
'createTime' => in_array($this->createTimeField, $fieldArr) ? "'{$this->createTimeField}'" : 'false',
|
||||
'updateTime' => in_array($this->updateTimeField, $fieldArr) ? "'{$this->updateTimeField}'" : 'false',
|
||||
'deleteTime' => in_array($this->deleteTimeField, $fieldArr) ? "'{$this->deleteTimeField}'" : 'false',
|
||||
'relationSearch' => $relations ? 'true' : 'false',
|
||||
'relationWithList' => '',
|
||||
'relationMethodList' => '',
|
||||
'controllerImport' => $controllerImport,
|
||||
'controllerIndex' => '',
|
||||
'recyclebinJs' => '',
|
||||
'headingHtml' => $headingHtml,
|
||||
'multipleHtml' => $multipleHtml,
|
||||
'importHtml' => $importHtml,
|
||||
'recyclebinHtml' => $recyclebinHtml,
|
||||
'visibleFieldList' => $fields ? "\$row->visible(['" . implode("','", array_filter(in_array($priKey,explode(',', $fields))?explode(',', $fields):explode(',',$priKey.','.$fields))) . "']);" : '',
|
||||
'visibleFieldList' => $fields ? "\$row->visible(['" . implode("','", array_filter(in_array($priKey, explode(',', $fields)) ? explode(',', $fields) : explode(',', $priKey . ',' . $fields))) . "']);" : '',
|
||||
'appendAttrList' => implode(",\n", $appendAttrList),
|
||||
'getEnumList' => implode("\n\n", $getEnumArr),
|
||||
'getAttrList' => implode("\n\n", $getAttrArr),
|
||||
|
|
@ -915,24 +1143,30 @@ class Crud extends Command
|
|||
//如果使用关联模型
|
||||
if ($relations) {
|
||||
$relationWithList = $relationMethodList = $relationVisibleFieldList = [];
|
||||
$relationKeyArr = ['hasone' => 'hasOne', 'belongsto' => 'belongsTo', 'hasmany' => 'hasMany'];
|
||||
foreach ($relations as $index => $relation) {
|
||||
//需要构造关联的方法
|
||||
$relation['relationMethod'] = strtolower($relation['relationName']);
|
||||
|
||||
//关联的模式
|
||||
$relation['relationMode'] = $relation['relationMode'] == 'hasone' ? 'hasOne' : 'belongsTo';
|
||||
$relation['relationMode'] = strtolower($relation['relationMode']);
|
||||
$relation['relationMode'] = array_key_exists($relation['relationMode'], $relationKeyArr) ? $relationKeyArr[$relation['relationMode']] : '';
|
||||
|
||||
//关联字段
|
||||
$relation['relationPrimaryKey'] = $relation['relationPrimaryKey'] ? $relation['relationPrimaryKey'] : $priKey;
|
||||
|
||||
//构造关联模型的方法
|
||||
$relationMethodList[] = $this->getReplacedStub('mixins' . DS . 'modelrelationmethod' . ($relation['relationMode'] == 'hasMany' ? '-hasmany' : ''), $relation);
|
||||
|
||||
if ($relation['relationMode'] == 'hasMany') {
|
||||
continue;
|
||||
}
|
||||
|
||||
//预载入的方法
|
||||
$relationWithList[] = $relation['relationMethod'];
|
||||
|
||||
unset($relation['relationColumnList'], $relation['relationFieldList'], $relation['relationTableInfo']);
|
||||
|
||||
//构造关联模型的方法
|
||||
$relationMethodList[] = $this->getReplacedStub('mixins' . DS . 'modelrelationmethod', $relation);
|
||||
|
||||
//如果设置了显示主表字段,则必须显式将关联表字段显示
|
||||
if ($fields) {
|
||||
$relationVisibleFieldList[] = "\$row->visible(['{$relation['relationMethod']}']);";
|
||||
|
|
@ -948,8 +1182,10 @@ class Crud extends Command
|
|||
$data['relationMethodList'] = implode("\n\n", $relationMethodList);
|
||||
$data['relationVisibleFieldList'] = implode("\n\t\t\t\t", $relationVisibleFieldList);
|
||||
|
||||
//需要重写index方法
|
||||
$data['controllerIndex'] = $this->getReplacedStub('controllerindex', $data);
|
||||
if ($relationWithList) {
|
||||
//需要重写index方法
|
||||
$data['controllerIndex'] = $this->getReplacedStub('controllerindex', $data);
|
||||
}
|
||||
} elseif ($fields) {
|
||||
$data = array_merge($data, ['relationWithList' => '', 'relationMethodList' => '', 'relationVisibleFieldList' => '']);
|
||||
//需要重写index方法
|
||||
|
|
@ -963,7 +1199,7 @@ class Crud extends Command
|
|||
|
||||
if ($relations) {
|
||||
foreach ($relations as $i => $relation) {
|
||||
$relation['modelNamespace'] = $data['modelNamespace'];
|
||||
$relation['modelNamespace'] = $relation['relationNamespace'];
|
||||
if (!is_file($relation['relationFile'])) {
|
||||
// 生成关联模型文件
|
||||
$this->writeToFile('relationmodel', $relation, $relation['relationFile']);
|
||||
|
|
@ -1088,6 +1324,28 @@ EOD;
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取控制器URL
|
||||
* @param string $moduleName
|
||||
* @param array $baseNameArr
|
||||
* @return string
|
||||
*/
|
||||
protected function getControllerUrl($moduleName, $baseNameArr)
|
||||
{
|
||||
for ($i = 0; $i < count($baseNameArr) - 1; $i++) {
|
||||
$temp = array_slice($baseNameArr, 0, $i + 1);
|
||||
$temp[$i] = ucfirst($temp[$i]);
|
||||
$controllerFile = APP_PATH . $moduleName . DS . 'controller' . DS . implode(DS, $temp) . '.php';
|
||||
//检测父级目录同名控制器是否存在,存在则变更URL格式
|
||||
if (is_file($controllerFile)) {
|
||||
$baseNameArr = [implode('.', $baseNameArr)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
$controllerUrl = strtolower(implode('/', $baseNameArr));
|
||||
return $controllerUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取控制器相关信息
|
||||
* @param $module
|
||||
|
|
@ -1137,14 +1395,14 @@ EOD;
|
|||
$arr = [];
|
||||
if (!$name) {
|
||||
$parseName = Loader::parseName($table, 1);
|
||||
$parseArr = [$table];
|
||||
} else {
|
||||
$name = str_replace(['.', '/', '\\'], '/', $name);
|
||||
$arr = explode('/', $name);
|
||||
$parseName = ucfirst(array_pop($arr));
|
||||
$parseArr = $arr;
|
||||
array_push($parseArr, $parseName);
|
||||
$name = str_replace('_', '/', $table);
|
||||
}
|
||||
|
||||
$name = str_replace(['.', '/', '\\'], '/', $name);
|
||||
$arr = explode('/', $name);
|
||||
$parseName = ucfirst(array_pop($arr));
|
||||
$parseArr = $arr;
|
||||
array_push($parseArr, $parseName);
|
||||
//类名不能为内部关键字
|
||||
if (in_array(strtolower($parseName), $this->internalKeywords)) {
|
||||
throw new Exception('Unable to use internal variable:' . $parseName);
|
||||
|
|
@ -1219,7 +1477,7 @@ EOD;
|
|||
if ($content || !Lang::has($field)) {
|
||||
$this->fieldMaxLen = strlen($field) > $this->fieldMaxLen ? strlen($field) : $this->fieldMaxLen;
|
||||
$content = str_replace(',', ',', $content);
|
||||
if (stripos($content, ':') !== false && stripos($content, ',') && stripos($content, '=') !== false) {
|
||||
if (stripos($content, ':') !== false && stripos($content, '=') !== false) {
|
||||
list($fieldLang, $item) = explode(':', $content);
|
||||
$itemArr = [$field => $fieldLang];
|
||||
foreach (explode(',', $item) as $k => $v) {
|
||||
|
|
@ -1227,6 +1485,9 @@ EOD;
|
|||
if (count($valArr) == 2) {
|
||||
list($key, $value) = $valArr;
|
||||
$itemArr[$field . ' ' . $key] = $value;
|
||||
if ($this->headingFilterField == $field) {
|
||||
$itemArr['Set ' . $field . ' to ' . $key] = '设为' . $value;
|
||||
}
|
||||
$this->fieldMaxLen = strlen($field . ' ' . $key) > $this->fieldMaxLen ? strlen($field . ' ' . $key) : $this->fieldMaxLen;
|
||||
}
|
||||
}
|
||||
|
|
@ -1284,7 +1545,7 @@ EOD;
|
|||
{
|
||||
$itemArr = [];
|
||||
$comment = str_replace(',', ',', $comment);
|
||||
if (stripos($comment, ':') !== false && stripos($comment, ',') && stripos($comment, '=') !== false) {
|
||||
if (stripos($comment, ':') !== false && stripos($comment, '=') !== false) {
|
||||
list($fieldLang, $item) = explode(':', $comment);
|
||||
$itemArr = [];
|
||||
foreach (explode(',', $item) as $k => $v) {
|
||||
|
|
@ -1302,7 +1563,7 @@ EOD;
|
|||
return $itemArr;
|
||||
}
|
||||
|
||||
protected function getFieldType(& $v)
|
||||
protected function getFieldType(&$v)
|
||||
{
|
||||
$inputType = 'text';
|
||||
switch ($v['DATA_TYPE']) {
|
||||
|
|
@ -1360,10 +1621,18 @@ EOD;
|
|||
if ($this->isMatchSuffix($fieldsName, $this->citySuffix) && ($v['DATA_TYPE'] == 'varchar' || $v['DATA_TYPE'] == 'char')) {
|
||||
$inputType = "citypicker";
|
||||
}
|
||||
// 指定后缀结尾城市选择框
|
||||
if ($this->isMatchSuffix($fieldsName, $this->rangeSuffix) && ($v['DATA_TYPE'] == 'varchar' || $v['DATA_TYPE'] == 'char')) {
|
||||
$inputType = "datetimerange";
|
||||
}
|
||||
// 指定后缀结尾JSON配置
|
||||
if ($this->isMatchSuffix($fieldsName, $this->jsonSuffix) && ($v['DATA_TYPE'] == 'varchar' || $v['DATA_TYPE'] == 'text')) {
|
||||
$inputType = "fieldlist";
|
||||
}
|
||||
// 指定后缀结尾标签配置
|
||||
if ($this->isMatchSuffix($fieldsName, $this->tagSuffix) && ($v['DATA_TYPE'] == 'varchar' || $v['DATA_TYPE'] == 'text')) {
|
||||
$inputType = "tagsinput";
|
||||
}
|
||||
return $inputType;
|
||||
}
|
||||
|
||||
|
|
@ -1413,7 +1682,7 @@ EOD;
|
|||
{
|
||||
$uploadfilter = $selectfilter = '';
|
||||
if ($this->isMatchSuffix($field, $this->imageField)) {
|
||||
$uploadfilter = ' data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp"';
|
||||
$uploadfilter = ' data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp"';
|
||||
$selectfilter = ' data-mimetype="image/*"';
|
||||
}
|
||||
$multiple = substr($field, -1) == 's' ? ' data-multiple="true"' : ' data-multiple="false"';
|
||||
|
|
@ -1438,9 +1707,10 @@ EOD;
|
|||
* @param string $datatype
|
||||
* @param string $extend
|
||||
* @param array $itemArr
|
||||
* @param array $fieldConfig
|
||||
* @return string
|
||||
*/
|
||||
protected function getJsColumn($field, $datatype = '', $extend = '', $itemArr = [])
|
||||
protected function getJsColumn($field, $datatype = '', $extend = '', $itemArr = [], $fieldConfig = [])
|
||||
{
|
||||
$lang = mb_ucfirst($field);
|
||||
$formatter = '';
|
||||
|
|
@ -1478,7 +1748,7 @@ EOD;
|
|||
$noSearchFiles = ['file$', 'files$', 'image$', 'images$', '^weigh$'];
|
||||
if (preg_match("/" . implode('|', $noSearchFiles) . "/i", $field)) {
|
||||
$html .= ", operate: false";
|
||||
} else if (in_array($datatype, ['varchar'])) {
|
||||
} elseif (in_array($datatype, ['varchar'])) {
|
||||
$html .= ", operate: 'LIKE'";
|
||||
}
|
||||
|
||||
|
|
@ -1490,6 +1760,10 @@ EOD;
|
|||
if (in_array($datatype, ['set'])) {
|
||||
$html .= ", operate:'FIND_IN_SET'";
|
||||
}
|
||||
if (isset($fieldConfig['CHARACTER_MAXIMUM_LENGTH']) && $fieldConfig['CHARACTER_MAXIMUM_LENGTH'] >= 255 && in_array($datatype, ['varchar']) && !$formatter) {
|
||||
$formatter = 'content';
|
||||
$html .= ", table: table, class: 'autocontent'";
|
||||
}
|
||||
if (in_array($formatter, ['image', 'images'])) {
|
||||
$html .= ", events: Table.api.events.image";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use app\common\controller\Backend;
|
|||
*/
|
||||
class {%controllerName%} extends Backend
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* {%modelName%}模型对象
|
||||
* @var \{%modelNamespace%}\{%modelName%}
|
||||
|
|
@ -25,16 +25,13 @@ class {%controllerName%} extends Backend
|
|||
{%controllerAssignList%}
|
||||
}
|
||||
|
||||
public function import()
|
||||
{
|
||||
parent::import();
|
||||
}
|
||||
{%controllerImport%}
|
||||
|
||||
/**
|
||||
* 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
|
||||
* 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
|
||||
* 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
|
||||
*/
|
||||
|
||||
|
||||
{%controllerIndex%}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
<dl class="list-unstyled fieldlist" data-name="{%fieldName%}" data-template="{%fieldName%}tpl">
|
||||
<dd>
|
||||
<ins>{:__('{%itemValue%}')}</ins>
|
||||
</dd>
|
||||
<dd>
|
||||
<ins><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></ins>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<textarea name="{%fieldName%}" class="form-control hide" cols="30" rows="5">{%fieldValue%}</textarea>
|
||||
<script id="{%fieldName%}tpl" type="text/html">
|
||||
<dd class="form-inline">
|
||||
<ins><input type="text" name="<%=name%>[<%=index%>][value]" class="form-control" size="15" value="<%=row%>"/></ins>
|
||||
<ins>
|
||||
<span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span>
|
||||
<span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
|
||||
</ins>
|
||||
</dd>
|
||||
</script>
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
<table class="table fieldlist" data-name="{%fieldName%}" data-template="{%fieldName%}tpl">
|
||||
<tr>
|
||||
{%theadList%}
|
||||
<td width="90">{:__('Operate')}</td>
|
||||
</tr>
|
||||
<tr><td colspan="{%colspan%}">
|
||||
<a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a>
|
||||
<textarea name="{%fieldName%}" class="form-control hide" cols="30" rows="5">{%fieldValue%}</textarea>
|
||||
</td></tr>
|
||||
</table>
|
||||
<script type="text/html" id="{%fieldName%}tpl">
|
||||
<tr>
|
||||
{%tbodyList%}
|
||||
<td width="90">
|
||||
<span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span>
|
||||
<span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<div class="dropdown btn-group {:$auth->check('{%controllerUrl%}/multi')?'':'hide'}">
|
||||
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
|
||||
<ul class="dropdown-menu text-left" role="menu">
|
||||
{foreach name="{%fieldName%}List" item="vo"}
|
||||
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:" data-params="{%field%}={$key}">{:__('Set {%field%} to ' . $key)}</a></li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -10,21 +10,15 @@
|
|||
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('{%controllerUrl%}/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
|
||||
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('{%controllerUrl%}/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
|
||||
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('{%controllerUrl%}/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
|
||||
<a href="javascript:;" class="btn btn-danger btn-import {:$auth->check('{%controllerUrl%}/import')?'':'hide'}" title="{:__('Import')}" id="btn-import-file" data-url="ajax/upload" data-mimetype="csv,xls,xlsx" data-multiple="false"><i class="fa fa-upload"></i> {:__('Import')}</a>
|
||||
{%importHtml%}
|
||||
|
||||
<div class="dropdown btn-group {:$auth->check('{%controllerUrl%}/multi')?'':'hide'}">
|
||||
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
|
||||
<ul class="dropdown-menu text-left" role="menu">
|
||||
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>
|
||||
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{%multipleHtml%}
|
||||
|
||||
{%recyclebinHtml%}
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('{%controllerUrl%}/edit')}"
|
||||
data-operate-del="{:$auth->check('{%controllerUrl%}/del')}"
|
||||
data-operate-edit="{:$auth->check('{%controllerUrl%}/edit')}"
|
||||
data-operate-del="{:$auth->check('{%controllerUrl%}/del')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
|||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: '{%pk%}',
|
||||
sortName: '{%order%}',
|
||||
sortName: '{%order%}',{%fixedColumnsJs%}
|
||||
columns: [
|
||||
[
|
||||
{%javascriptList%}
|
||||
|
|
@ -45,4 +45,4 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
|||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
public function import()
|
||||
{
|
||||
parent::import();
|
||||
}
|
||||
|
|
@ -2,7 +2,9 @@
|
|||
protected static function init()
|
||||
{
|
||||
self::afterInsert(function ($row) {
|
||||
$pk = $row->getPk();
|
||||
$row->getQuery()->where($pk, $row[$pk])->update(['{%order%}' => $row[$pk]]);
|
||||
if (!$row['{%order%}']) {
|
||||
$pk = $row->getPk();
|
||||
$row->getQuery()->where($pk, $row[$pk])->update(['{%order%}' => $row[$pk]]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
public function {%relationMethod%}s()
|
||||
{
|
||||
return $this->{%relationMode%}('{%relationClassName%}', '{%relationForeignKey%}', '{%relationPrimaryKey%}');
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
public function {%methodName%}($value, $data)
|
||||
{
|
||||
$value = $value ? $value : (isset($data['{%field%}']) ? $data['{%field%}'] : '');
|
||||
$value = $value ?: ($data['{%field%}'] ?? '');
|
||||
$valueArr = explode(',', $value);
|
||||
$list = $this->{%listMethodName%}();
|
||||
return implode(',', array_intersect_key($list, array_flip($valueArr)));
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
},
|
||||
{
|
||||
field: 'operate',
|
||||
width: '130px',
|
||||
width: '140px',
|
||||
title: __('Operate'),
|
||||
table: table,
|
||||
events: Table.api.events.operate,
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class Install extends Command
|
|||
|
||||
$adminName = $this->installation($hostname, $hostport, $database, $username, $password, $prefix, $adminUsername, $adminPassword, $adminEmail, $siteName);
|
||||
if ($adminName) {
|
||||
$output->highlight("Admin url:http://www.yoursite.com/{$adminName}");
|
||||
$output->highlight("Admin url:http://www.example.com/{$adminName}");
|
||||
}
|
||||
|
||||
$output->highlight("Admin username:{$adminUsername}");
|
||||
|
|
@ -86,12 +86,15 @@ class Install extends Command
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->view = View::instance(Config::get('template'), Config::get('view_replace_str'));
|
||||
$this->view = View::instance(array_merge(Config::get('template'), ['tpl_cache' => false]));
|
||||
$this->request = Request::instance();
|
||||
|
||||
define('INSTALL_PATH', APP_PATH . 'admin' . DS . 'command' . DS . 'Install' . DS);
|
||||
$langSet = strtolower($this->request->langset());
|
||||
if (!$langSet || in_array($langSet, ['zh-cn', 'zh-hans-cn'])) {
|
||||
|
||||
$lang = $this->request->langset();
|
||||
$lang = preg_match("/^([a-zA-Z\-_]{2,10})\$/i", $lang) ? $lang : 'zh-cn';
|
||||
|
||||
if (!$lang || in_array($lang, ['zh-cn', 'zh-hans-cn'])) {
|
||||
Lang::load(INSTALL_PATH . 'zh-cn.php');
|
||||
}
|
||||
|
||||
|
|
@ -162,6 +165,10 @@ class Install extends Command
|
|||
if (!preg_match("/^[\S]{6,16}$/", $adminPassword)) {
|
||||
throw new Exception(__('Please input correct password'));
|
||||
}
|
||||
$weakPasswordArr = ['123456', '12345678', '123456789', '654321', '111111', '000000', 'password', 'qwerty', 'abc123', '1qaz2wsx'];
|
||||
if (in_array($adminPassword, $weakPasswordArr)) {
|
||||
throw new Exception(__('Password is too weak'));
|
||||
}
|
||||
if ($siteName == '' || preg_match("/fast" . "admin/i", $siteName)) {
|
||||
throw new Exception(__('Please input correct website'));
|
||||
}
|
||||
|
|
@ -175,7 +182,7 @@ class Install extends Command
|
|||
try {
|
||||
$pdo = new PDO("{$config['type']}:host={$mysqlHostname}" . ($mysqlHostport ? ";port={$mysqlHostport}" : ''), $mysqlUsername, $mysqlPassword);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$pdo->query("CREATE DATABASE IF NOT EXISTS `{$mysqlDatabase}` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;");
|
||||
$pdo->query("CREATE DATABASE IF NOT EXISTS `{$mysqlDatabase}` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;");
|
||||
|
||||
// 连接install命令中指定的数据库
|
||||
$instance = Db::connect([
|
||||
|
|
@ -230,18 +237,19 @@ class Install extends Command
|
|||
throw new Exception(__('The current permissions are insufficient to write the file %s', 'application/config.php'));
|
||||
}
|
||||
|
||||
$avatar = request()->domain() . '/assets/img/avatar.png';
|
||||
// 变更默认管理员密码
|
||||
$adminPassword = $adminPassword ? $adminPassword : Random::alnum(8);
|
||||
$adminEmail = $adminEmail ? $adminEmail : "admin@admin.com";
|
||||
$newSalt = substr(md5(uniqid(true)), 0, 6);
|
||||
$newPassword = md5(md5($adminPassword) . $newSalt);
|
||||
$data = ['username' => $adminUsername, 'email' => $adminEmail, 'password' => $newPassword, 'salt' => $newSalt];
|
||||
$data = ['username' => $adminUsername, 'email' => $adminEmail, 'avatar' => $avatar, 'password' => $newPassword, 'salt' => $newSalt];
|
||||
$instance->name('admin')->where('username', 'admin')->update($data);
|
||||
|
||||
// 变更前台默认用户的密码,随机生成
|
||||
$newSalt = substr(md5(uniqid(true)), 0, 6);
|
||||
$newPassword = md5(md5(Random::alnum(8)) . $newSalt);
|
||||
$instance->name('user')->where('username', 'admin')->update(['password' => $newPassword, 'salt' => $newSalt]);
|
||||
$instance->name('user')->where('username', 'admin')->update(['avatar' => $avatar, 'password' => $newPassword, 'salt' => $newSalt]);
|
||||
|
||||
// 修改后台入口
|
||||
$adminName = '';
|
||||
|
|
@ -258,7 +266,7 @@ class Install extends Command
|
|||
$configList = $instance->name("config")->select();
|
||||
foreach ($configList as $k => $value) {
|
||||
if (in_array($value['type'], ['selects', 'checkbox', 'images', 'files'])) {
|
||||
$value['value'] = explode(',', $value['value']);
|
||||
$value['value'] = is_array($value['value']) ? $value['value'] : explode(',', $value['value']);
|
||||
}
|
||||
if ($value['type'] == 'array') {
|
||||
$value['value'] = (array)json_decode($value['value'], true);
|
||||
|
|
@ -276,6 +284,13 @@ class Install extends Command
|
|||
throw new Exception(__('The current permissions are insufficient to write the file %s', 'application/admin/command/Install/install.lock'));
|
||||
}
|
||||
|
||||
try {
|
||||
//删除安装脚本
|
||||
@unlink(ROOT_PATH . 'public' . DS . 'install.php');
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
|
||||
return $adminName;
|
||||
}
|
||||
|
||||
|
|
@ -294,8 +309,8 @@ class Install extends Command
|
|||
//数据库配置文件
|
||||
$dbConfigFile = APP_PATH . 'database.php';
|
||||
|
||||
if (version_compare(PHP_VERSION, '7.1.0', '<')) {
|
||||
throw new Exception(__("The current version %s is too low, please use PHP 7.1 or higher", PHP_VERSION));
|
||||
if (version_compare(PHP_VERSION, '7.4.0', '<')) {
|
||||
throw new Exception(__("The current version %s is too low, please use PHP 7.4 or higher", PHP_VERSION));
|
||||
}
|
||||
if (!extension_loaded("PDO")) {
|
||||
throw new Exception(__("PDO is not currently installed and cannot be installed"));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
FastAdmin Install SQL
|
||||
Date: 2020-06-11 22:11:09
|
||||
Date: 2024-09-03 15:05:25
|
||||
*/
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
|
@ -8,7 +8,6 @@ SET FOREIGN_KEY_CHECKS = 0;
|
|||
-- ----------------------------
|
||||
-- Table structure for fa_admin
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_admin`;
|
||||
CREATE TABLE `fa_admin` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`username` varchar(20) DEFAULT '' COMMENT '用户名',
|
||||
|
|
@ -17,53 +16,52 @@ CREATE TABLE `fa_admin` (
|
|||
`salt` varchar(30) DEFAULT '' COMMENT '密码盐',
|
||||
`avatar` varchar(255) DEFAULT '' COMMENT '头像',
|
||||
`email` varchar(100) DEFAULT '' COMMENT '电子邮箱',
|
||||
`mobile` varchar(11) DEFAULT '' COMMENT '手机号码',
|
||||
`loginfailure` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '失败次数',
|
||||
`logintime` int(10) DEFAULT NULL COMMENT '登录时间',
|
||||
`logintime` bigint(16) DEFAULT NULL COMMENT '登录时间',
|
||||
`loginip` varchar(50) DEFAULT NULL COMMENT '登录IP',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',
|
||||
`token` varchar(59) DEFAULT '' COMMENT 'Session标识',
|
||||
`status` varchar(30) NOT NULL DEFAULT 'normal' COMMENT '状态',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `username` (`username`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='管理员表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='管理员表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fa_admin
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `fa_admin` VALUES (1, 'admin', 'Admin', '', '', '/assets/img/avatar.png', 'admin@admin.com', 0, 1491635035, '127.0.0.1',1491635035, 1491635035, '', 'normal');
|
||||
INSERT INTO `fa_admin` VALUES (1, 'admin', 'Admin', '', '', '/assets/img/avatar.png', 'admin@example.com', '', 0, 1491635035, '127.0.0.1',1491635035, 1491635035, '', 'normal');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fa_admin_log
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_admin_log`;
|
||||
CREATE TABLE `fa_admin_log` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`admin_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '管理员ID',
|
||||
`username` varchar(30) DEFAULT '' COMMENT '管理员名字',
|
||||
`url` varchar(1500) DEFAULT '' COMMENT '操作页面',
|
||||
`title` varchar(100) DEFAULT '' COMMENT '日志标题',
|
||||
`content` text NOT NULL COMMENT '内容',
|
||||
`content` longtext NOT NULL COMMENT '内容',
|
||||
`ip` varchar(50) DEFAULT '' COMMENT 'IP',
|
||||
`useragent` varchar(255) DEFAULT '' COMMENT 'User-Agent',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '操作时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '操作时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `name` (`username`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='管理员日志表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='管理员日志表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fa_area
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_area`;
|
||||
CREATE TABLE `fa_area` (
|
||||
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`pid` int(10) DEFAULT NULL COMMENT '父id',
|
||||
`shortname` varchar(100) DEFAULT NULL COMMENT '简称',
|
||||
`name` varchar(100) DEFAULT NULL COMMENT '名称',
|
||||
`mergename` varchar(255) DEFAULT NULL COMMENT '全称',
|
||||
`level` tinyint(4) DEFAULT NULL COMMENT '层级 0 1 2 省市区县',
|
||||
`level` tinyint(4) DEFAULT NULL COMMENT '层级:1=省,2=市,3=区/县',
|
||||
`pinyin` varchar(100) DEFAULT NULL COMMENT '拼音',
|
||||
`code` varchar(100) DEFAULT NULL COMMENT '长途区号',
|
||||
`zip` varchar(100) DEFAULT NULL COMMENT '邮编',
|
||||
|
|
@ -72,33 +70,32 @@ CREATE TABLE `fa_area` (
|
|||
`lat` varchar(100) DEFAULT NULL COMMENT '纬度',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `pid` (`pid`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='地区表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='地区表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fa_attachment
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_attachment`;
|
||||
CREATE TABLE `fa_attachment` (
|
||||
`id` int(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`category` varchar(50) DEFAULT '' COMMENT '类别',
|
||||
`admin_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '管理员ID',
|
||||
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '会员ID',
|
||||
`url` varchar(255) DEFAULT '' COMMENT '物理路径',
|
||||
`imagewidth` varchar(30) DEFAULT '' COMMENT '宽度',
|
||||
`imageheight` varchar(30) DEFAULT '' COMMENT '高度',
|
||||
`imagewidth` int(10) unsigned DEFAULT 0 COMMENT '宽度',
|
||||
`imageheight` int(10) unsigned DEFAULT 0 COMMENT '高度',
|
||||
`imagetype` varchar(30) DEFAULT '' COMMENT '图片类型',
|
||||
`imageframes` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '图片帧数',
|
||||
`filename` varchar(100) DEFAULT '' COMMENT '文件名称',
|
||||
`filesize` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '文件大小',
|
||||
`mimetype` varchar(100) DEFAULT '' COMMENT 'mime类型',
|
||||
`extparam` varchar(255) DEFAULT '' COMMENT '透传数据',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建日期',
|
||||
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
|
||||
`uploadtime` int(10) DEFAULT NULL COMMENT '上传时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建日期',
|
||||
`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',
|
||||
`uploadtime` bigint(16) DEFAULT NULL COMMENT '上传时间',
|
||||
`storage` varchar(100) NOT NULL DEFAULT 'local' COMMENT '存储位置',
|
||||
`sha1` varchar(40) DEFAULT '' COMMENT '文件 sha1编码',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='附件表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='附件表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fa_attachment
|
||||
|
|
@ -110,17 +107,16 @@ COMMIT;
|
|||
-- ----------------------------
|
||||
-- Table structure for fa_auth_group
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_auth_group`;
|
||||
CREATE TABLE `fa_auth_group` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`pid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父组别',
|
||||
`name` varchar(100) DEFAULT '' COMMENT '组名',
|
||||
`rules` text NOT NULL COMMENT '规则ID',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',
|
||||
`status` varchar(30) DEFAULT '' COMMENT '状态',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='分组表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='分组表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fa_auth_group
|
||||
|
|
@ -136,14 +132,13 @@ COMMIT;
|
|||
-- ----------------------------
|
||||
-- Table structure for fa_auth_group_access
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_auth_group_access`;
|
||||
CREATE TABLE `fa_auth_group_access` (
|
||||
`uid` int(10) unsigned NOT NULL COMMENT '会员ID',
|
||||
`group_id` int(10) unsigned NOT NULL COMMENT '级别ID',
|
||||
UNIQUE KEY `uid_group_id` (`uid`,`group_id`),
|
||||
KEY `uid` (`uid`),
|
||||
KEY `group_id` (`group_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='权限分组表';
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='权限分组表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fa_auth_group_access
|
||||
|
|
@ -155,7 +150,6 @@ COMMIT;
|
|||
-- ----------------------------
|
||||
-- Table structure for fa_auth_rule
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_auth_rule`;
|
||||
CREATE TABLE `fa_auth_rule` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`type` enum('menu','file') NOT NULL DEFAULT 'file' COMMENT 'menu为菜单,file为权限节点',
|
||||
|
|
@ -171,15 +165,15 @@ CREATE TABLE `fa_auth_rule` (
|
|||
`extend` varchar(255) DEFAULT '' COMMENT '扩展属性',
|
||||
`py` varchar(30) DEFAULT '' COMMENT '拼音首字母',
|
||||
`pinyin` varchar(100) DEFAULT '' COMMENT '拼音',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',
|
||||
`weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重',
|
||||
`status` varchar(30) DEFAULT '' COMMENT '状态',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `name` (`name`) USING BTREE,
|
||||
KEY `pid` (`pid`),
|
||||
KEY `weigh` (`weigh`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='节点表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='节点表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fa_auth_rule
|
||||
|
|
@ -187,7 +181,7 @@ CREATE TABLE `fa_auth_rule` (
|
|||
BEGIN;
|
||||
INSERT INTO `fa_auth_rule` VALUES (1, 'file', 0, 'dashboard', 'Dashboard', 'fa fa-dashboard', '', '', 'Dashboard tips', 1, NULL, '', 'kzt', 'kongzhitai', 1491635035, 1491635035, 143, 'normal');
|
||||
INSERT INTO `fa_auth_rule` VALUES (2, 'file', 0, 'general', 'General', 'fa fa-cogs', '', '', '', 1, NULL, '', 'cggl', 'changguiguanli', 1491635035, 1491635035, 137, 'normal');
|
||||
INSERT INTO `fa_auth_rule` VALUES (3, 'file', 0, 'category', 'Category', 'fa fa-leaf', '', '', 'Category tips', 1, NULL, '', 'flgl', 'fenleiguanli', 1491635035, 1491635035, 119, 'normal');
|
||||
INSERT INTO `fa_auth_rule` VALUES (3, 'file', 0, 'category', 'Category', 'fa fa-leaf', '', '', 'Category tips', 0, NULL, '', 'flgl', 'fenleiguanli', 1491635035, 1491635035, 119, 'normal');
|
||||
INSERT INTO `fa_auth_rule` VALUES (4, 'file', 0, 'addon', 'Addon', 'fa fa-rocket', '', '', 'Addon tips', 1, NULL, '', 'cjgl', 'chajianguanli', 1491635035, 1491635035, 0, 'normal');
|
||||
INSERT INTO `fa_auth_rule` VALUES (5, 'file', 0, 'auth', 'Auth', 'fa fa-group', '', '', '', 1, NULL, '', 'qxgl', 'quanxianguanli', 1491635035, 1491635035, 99, 'normal');
|
||||
INSERT INTO `fa_auth_rule` VALUES (6, 'file', 2, 'general/config', 'Config', 'fa fa-cog', '', '', 'Config tips', 1, NULL, '', 'xtpz', 'xitongpeizhi', 1491635035, 1491635035, 60, 'normal');
|
||||
|
|
@ -272,7 +266,6 @@ COMMIT;
|
|||
-- ----------------------------
|
||||
-- Table structure for fa_category
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_category`;
|
||||
CREATE TABLE `fa_category` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`pid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父ID',
|
||||
|
|
@ -284,14 +277,14 @@ CREATE TABLE `fa_category` (
|
|||
`keywords` varchar(255) DEFAULT '' COMMENT '关键字',
|
||||
`description` varchar(255) DEFAULT '' COMMENT '描述',
|
||||
`diyname` varchar(30) DEFAULT '' COMMENT '自定义名称',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',
|
||||
`weigh` int(10) NOT NULL DEFAULT '0' COMMENT '权重',
|
||||
`status` varchar(30) DEFAULT '' COMMENT '状态',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `weigh` (`weigh`,`id`),
|
||||
KEY `pid` (`pid`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='分类表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='分类表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fa_category
|
||||
|
|
@ -315,7 +308,6 @@ COMMIT;
|
|||
-- ----------------------------
|
||||
-- Table structure for fa_config
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_config`;
|
||||
CREATE TABLE `fa_config` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(30) DEFAULT '' COMMENT '变量名',
|
||||
|
|
@ -323,6 +315,7 @@ CREATE TABLE `fa_config` (
|
|||
`title` varchar(100) DEFAULT '' COMMENT '变量标题',
|
||||
`tip` varchar(100) DEFAULT '' COMMENT '变量描述',
|
||||
`type` varchar(30) DEFAULT '' COMMENT '类型:string,text,int,bool,array,datetime,date,file',
|
||||
`visible` varchar(255) DEFAULT '' COMMENT '可见条件',
|
||||
`value` text COMMENT '变量值',
|
||||
`content` text COMMENT '变量字典数据',
|
||||
`rule` varchar(100) DEFAULT '' COMMENT '验证规则',
|
||||
|
|
@ -330,36 +323,35 @@ CREATE TABLE `fa_config` (
|
|||
`setting` varchar(255) DEFAULT '' COMMENT '配置',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `name` (`name`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='系统配置';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='系统配置';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fa_config
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `fa_config` VALUES (1, 'name', 'basic', 'Site name', '请填写站点名称', 'string', '我的网站', '', 'required', '', '');
|
||||
INSERT INTO `fa_config` VALUES (2, 'beian', 'basic', 'Beian', '粤ICP备15000000号-1', 'string', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (3, 'cdnurl', 'basic', 'Cdn url', '如果全站静态资源使用第三方云储存请配置该值', 'string', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (4, 'version', 'basic', 'Version', '如果静态资源有变动请重新配置该值', 'string', '1.0.1', '', 'required', '', '');
|
||||
INSERT INTO `fa_config` VALUES (5, 'timezone', 'basic', 'Timezone', '', 'string', 'Asia/Shanghai', '', 'required', '', '');
|
||||
INSERT INTO `fa_config` VALUES (6, 'forbiddenip', 'basic', 'Forbidden ip', '一行一条记录', 'text', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (7, 'languages', 'basic', 'Languages', '', 'array', '{\"backend\":\"zh-cn\",\"frontend\":\"zh-cn\"}', '', 'required', '', '');
|
||||
INSERT INTO `fa_config` VALUES (8, 'fixedpage', 'basic', 'Fixed page', '请尽量输入左侧菜单栏存在的链接', 'string', 'dashboard', '', 'required', '', '');
|
||||
INSERT INTO `fa_config` VALUES (9, 'categorytype', 'dictionary', 'Category type', '', 'array', '{\"default\":\"Default\",\"page\":\"Page\",\"article\":\"Article\",\"test\":\"Test\"}', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (10, 'configgroup', 'dictionary', 'Config group', '', 'array', '{\"basic\":\"Basic\",\"email\":\"Email\",\"dictionary\":\"Dictionary\",\"user\":\"User\",\"example\":\"Example\"}', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (11, 'mail_type', 'email', 'Mail type', '选择邮件发送方式', 'select', '1', '[\"请选择\",\"SMTP\"]', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (12, 'mail_smtp_host', 'email', 'Mail smtp host', '错误的配置发送邮件会导致服务器超时', 'string', 'smtp.qq.com', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (13, 'mail_smtp_port', 'email', 'Mail smtp port', '(不加密默认25,SSL默认465,TLS默认587)', 'string', '465', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (14, 'mail_smtp_user', 'email', 'Mail smtp user', '(填写完整用户名)', 'string', '10000', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (15, 'mail_smtp_pass', 'email', 'Mail smtp password', '(填写您的密码或授权码)', 'string', 'password', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (16, 'mail_verify_type', 'email', 'Mail vertify type', '(SMTP验证方式[推荐SSL])', 'select', '2', '[\"无\",\"TLS\",\"SSL\"]', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (17, 'mail_from', 'email', 'Mail from', '', 'string', '10000@qq.com', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (18, 'attachmentcategory', 'dictionary', 'Attachment category', '', 'array', '{\"category1\":\"Category1\",\"category2\":\"Category2\",\"custom\":\"Custom\"}', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (1, 'name', 'basic', 'Site name', '请填写站点名称', 'string', '', '我的网站', '', 'required', '', '');
|
||||
INSERT INTO `fa_config` VALUES (2, 'beian', 'basic', 'Beian', '粤ICP备15000000号-1', 'string', '', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (3, 'cdnurl', 'basic', 'Cdn url', '如果全站静态资源使用第三方云储存请配置该值', 'string', '', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (4, 'version', 'basic', 'Version', '如果静态资源有变动请重新配置该值', 'string', '', '1.0.1', '', 'required', '', '');
|
||||
INSERT INTO `fa_config` VALUES (5, 'timezone', 'basic', 'Timezone', '', 'string', '', 'Asia/Shanghai', '', 'required', '', '');
|
||||
INSERT INTO `fa_config` VALUES (6, 'forbiddenip', 'basic', 'Forbidden ip', '一行一条记录', 'text', '', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (7, 'languages', 'basic', 'Languages', '', 'array', '', '{\"backend\":\"zh-cn\",\"frontend\":\"zh-cn\"}', '', 'required', '', '');
|
||||
INSERT INTO `fa_config` VALUES (8, 'fixedpage', 'basic', 'Fixed page', '请输入左侧菜单栏存在的链接', 'string', '', 'dashboard', '', 'required', '', '');
|
||||
INSERT INTO `fa_config` VALUES (9, 'categorytype', 'dictionary', 'Category type', '', 'array', '', '{\"default\":\"Default\",\"page\":\"Page\",\"article\":\"Article\",\"test\":\"Test\"}', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (10, 'configgroup', 'dictionary', 'Config group', '', 'array', '', '{\"basic\":\"Basic\",\"email\":\"Email\",\"dictionary\":\"Dictionary\",\"user\":\"User\",\"example\":\"Example\"}', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (11, 'mail_type', 'email', 'Mail type', '选择邮件发送方式', 'select', '', '1', '[\"请选择\",\"SMTP\"]', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (12, 'mail_smtp_host', 'email', 'Mail smtp host', '错误的配置发送邮件会导致服务器超时', 'string', '', 'smtp.qq.com', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (13, 'mail_smtp_port', 'email', 'Mail smtp port', '(不加密默认25,SSL默认465,TLS默认587)', 'string', '', '465', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (14, 'mail_smtp_user', 'email', 'Mail smtp user', '(填写完整用户名)', 'string', '', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (15, 'mail_smtp_pass', 'email', 'Mail smtp password', '(填写您的密码或授权码)', 'password', '', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (16, 'mail_verify_type', 'email', 'Mail vertify type', '(SMTP验证方式[推荐SSL])', 'select', '', '2', '[\"无\",\"TLS\",\"SSL\"]', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (17, 'mail_from', 'email', 'Mail from', '', 'string', '', '', '', '', '', '');
|
||||
INSERT INTO `fa_config` VALUES (18, 'attachmentcategory', 'dictionary', 'Attachment category', '', 'array', '', '{\"category1\":\"Category1\",\"category2\":\"Category2\",\"custom\":\"Custom\"}', '', '', '', '');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fa_ems
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_ems`;
|
||||
CREATE TABLE `fa_ems` (
|
||||
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`event` varchar(30) DEFAULT '' COMMENT '事件',
|
||||
|
|
@ -367,14 +359,13 @@ CREATE TABLE `fa_ems` (
|
|||
`code` varchar(10) DEFAULT '' COMMENT '验证码',
|
||||
`times` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '验证次数',
|
||||
`ip` varchar(30) DEFAULT '' COMMENT 'IP',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='邮箱验证码表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='邮箱验证码表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fa_sms
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_sms`;
|
||||
CREATE TABLE `fa_sms` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`event` varchar(30) DEFAULT '' COMMENT '事件',
|
||||
|
|
@ -382,19 +373,20 @@ CREATE TABLE `fa_sms` (
|
|||
`code` varchar(10) DEFAULT '' COMMENT '验证码',
|
||||
`times` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '验证次数',
|
||||
`ip` varchar(30) DEFAULT '' COMMENT 'IP',
|
||||
`createtime` int(10) unsigned DEFAULT '0' COMMENT '创建时间',
|
||||
`createtime` bigint(16) unsigned DEFAULT '0' COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='短信验证码表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='短信验证码表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fa_test
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_test`;
|
||||
CREATE TABLE `fa_test` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`user_id` int(10) DEFAULT '0' COMMENT '会员ID',
|
||||
`admin_id` int(10) DEFAULT '0' COMMENT '管理员ID',
|
||||
`category_id` int(10) unsigned DEFAULT '0' COMMENT '分类ID(单选)',
|
||||
`category_ids` varchar(100) COMMENT '分类ID(多选)',
|
||||
`tags` varchar(255) DEFAULT '' COMMENT '标签',
|
||||
`week` enum('monday','tuesday','wednesday') COMMENT '星期(单选):monday=星期一,tuesday=星期二,wednesday=星期三',
|
||||
`flag` set('hot','index','recommend') DEFAULT '' COMMENT '标志(多选):hot=热门,index=首页,recommend=推荐',
|
||||
`genderdata` enum('male','female') DEFAULT 'male' COMMENT '性别(单选):male=男,female=女',
|
||||
|
|
@ -407,35 +399,37 @@ CREATE TABLE `fa_test` (
|
|||
`keywords` varchar(255) DEFAULT '' COMMENT '关键字',
|
||||
`description` varchar(255) DEFAULT '' COMMENT '描述',
|
||||
`city` varchar(100) DEFAULT '' COMMENT '省市',
|
||||
`json` varchar(255) DEFAULT NULL COMMENT '配置:key=名称,value=值',
|
||||
`array` varchar(255) DEFAULT '' COMMENT '数组:value=值',
|
||||
`json` varchar(255) DEFAULT '' COMMENT '配置:key=名称,value=值',
|
||||
`multiplejson` varchar(1500) DEFAULT '' COMMENT '二维数组:title=标题,intro=介绍,author=作者,age=年龄',
|
||||
`price` decimal(10,2) unsigned DEFAULT '0.00' COMMENT '价格',
|
||||
`views` int(10) unsigned DEFAULT '0' COMMENT '点击',
|
||||
`workrange` varchar(100) DEFAULT '' COMMENT '时间区间',
|
||||
`startdate` date DEFAULT NULL COMMENT '开始日期',
|
||||
`activitytime` datetime DEFAULT NULL COMMENT '活动时间(datetime)',
|
||||
`year` year(4) DEFAULT NULL COMMENT '年',
|
||||
`times` time DEFAULT NULL COMMENT '时间',
|
||||
`refreshtime` int(10) DEFAULT NULL COMMENT '刷新时间(int)',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
|
||||
`deletetime` int(10) DEFAULT NULL COMMENT '删除时间',
|
||||
`refreshtime` bigint(16) DEFAULT NULL COMMENT '刷新时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',
|
||||
`deletetime` bigint(16) DEFAULT NULL COMMENT '删除时间',
|
||||
`weigh` int(10) DEFAULT '0' COMMENT '权重',
|
||||
`switch` tinyint(1) DEFAULT '0' COMMENT '开关',
|
||||
`status` enum('normal','hidden') DEFAULT 'normal' COMMENT '状态',
|
||||
`state` enum('0','1','2') DEFAULT '1' COMMENT '状态值:0=禁用,1=正常,2=推荐',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='测试表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='测试表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fa_test
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `fa_test` VALUES (1, 0, 12, '12,13', 'monday', 'hot,index', 'male', 'music,reading', '我是一篇测试文章', '<p>我是测试内容</p>', '/assets/img/avatar.png', '/assets/img/avatar.png,/assets/img/qrcode.png', '/assets/img/avatar.png', '关键字', '描述', '广西壮族自治区/百色市/平果县', '{\"a\":\"1\",\"b\":\"2\"}', 0.00, 0, '2017-07-10', '2017-07-10 18:24:45', 2017, '18:24:45', 1491635035, 1491635035, 1491635035, NULL, 0, 1, 'normal', '1');
|
||||
INSERT INTO `fa_test` VALUES (1, 1, 1, 12, '12,13', '互联网,计算机', 'monday', 'hot,index', 'male', 'music,reading', '我是一篇测试文章', '<p>我是测试内容</p>', '/assets/img/avatar.png', '/assets/img/avatar.png,/assets/img/qrcode.png', '/assets/img/avatar.png', '关键字', '我是一篇测试文章描述,内容过多时将自动隐藏', '广西壮族自治区/百色市/平果县', '[\"a\",\"b\"]', '{\"a\":\"1\",\"b\":\"2\"}', '[{\"title\":\"标题一\",\"intro\":\"介绍一\",\"author\":\"小明\",\"age\":\"21\"}]', 0.00, 0, '2020-10-01 00:00:00 - 2021-10-31 23:59:59', '2017-07-10', '2017-07-10 18:24:45', 2017, '18:24:45', 1491635035, 1491635035, 1491635035, NULL, 0, 1, 'normal', '1');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fa_user
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_user`;
|
||||
CREATE TABLE `fa_user` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`group_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '组别ID',
|
||||
|
|
@ -454,14 +448,15 @@ CREATE TABLE `fa_user` (
|
|||
`score` int(10) NOT NULL DEFAULT '0' COMMENT '积分',
|
||||
`successions` int(10) unsigned NOT NULL DEFAULT '1' COMMENT '连续登录天数',
|
||||
`maxsuccessions` int(10) unsigned NOT NULL DEFAULT '1' COMMENT '最大连续登录天数',
|
||||
`prevtime` int(10) DEFAULT NULL COMMENT '上次登录时间',
|
||||
`logintime` int(10) DEFAULT NULL COMMENT '登录时间',
|
||||
`prevtime` bigint(16) DEFAULT NULL COMMENT '上次登录时间',
|
||||
`logintime` bigint(16) DEFAULT NULL COMMENT '登录时间',
|
||||
`loginip` varchar(50) DEFAULT '' COMMENT '登录IP',
|
||||
`loginfailure` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '失败次数',
|
||||
`loginfailuretime` bigint(16) DEFAULT NULL COMMENT '最后登录失败时间',
|
||||
`joinip` varchar(50) DEFAULT '' COMMENT '加入IP',
|
||||
`jointime` int(10) DEFAULT NULL COMMENT '加入时间',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
|
||||
`jointime` bigint(16) DEFAULT NULL COMMENT '加入时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',
|
||||
`token` varchar(50) DEFAULT '' COMMENT 'Token',
|
||||
`status` varchar(30) DEFAULT '' COMMENT '状态',
|
||||
`verification` varchar(255) DEFAULT '' COMMENT '验证',
|
||||
|
|
@ -469,28 +464,27 @@ CREATE TABLE `fa_user` (
|
|||
KEY `username` (`username`),
|
||||
KEY `email` (`email`),
|
||||
KEY `mobile` (`mobile`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='会员表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='会员表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fa_user
|
||||
-- ----------------------------
|
||||
BEGIN;
|
||||
INSERT INTO `fa_user` VALUES (1, 1, 'admin', 'admin', '', '', 'admin@163.com', '13888888888', '', 0, 0, '2017-04-08', '', 0, 0, 1, 1, 1491635035, 1491635035, '127.0.0.1', 0, '127.0.0.1', 1491635035, 0, 1491635035, '', 'normal','');
|
||||
INSERT INTO `fa_user` VALUES (1, 1, 'admin', 'admin', '', '', 'admin@163.com', '13000000000', '', 0, 0, '2017-04-08', '', 0, 0, 1, 1, 1491635035, 1491635035, '127.0.0.1', 0, 1491635035,'127.0.0.1', 1491635035, 0, 1491635035, '', 'normal','');
|
||||
COMMIT;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fa_user_group
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_user_group`;
|
||||
CREATE TABLE `fa_user_group` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) DEFAULT '' COMMENT '组名',
|
||||
`rules` text COMMENT '权限节点',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '添加时间',
|
||||
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '添加时间',
|
||||
`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',
|
||||
`status` enum('normal','hidden') DEFAULT NULL COMMENT '状态',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='会员组表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='会员组表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fa_user_group
|
||||
|
|
@ -502,7 +496,6 @@ COMMIT;
|
|||
-- ----------------------------
|
||||
-- Table structure for fa_user_money_log
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_user_money_log`;
|
||||
CREATE TABLE `fa_user_money_log` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '会员ID',
|
||||
|
|
@ -510,14 +503,13 @@ CREATE TABLE `fa_user_money_log` (
|
|||
`before` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '变更前余额',
|
||||
`after` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '变更后余额',
|
||||
`memo` varchar(255) DEFAULT '' COMMENT '备注',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='会员余额变动表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='会员余额变动表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fa_user_rule
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_user_rule`;
|
||||
CREATE TABLE `fa_user_rule` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`pid` int(10) DEFAULT NULL COMMENT '父ID',
|
||||
|
|
@ -525,12 +517,12 @@ CREATE TABLE `fa_user_rule` (
|
|||
`title` varchar(50) DEFAULT '' COMMENT '标题',
|
||||
`remark` varchar(100) DEFAULT NULL COMMENT '备注',
|
||||
`ismenu` tinyint(1) DEFAULT NULL COMMENT '是否菜单',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',
|
||||
`weigh` int(10) DEFAULT '0' COMMENT '权重',
|
||||
`status` enum('normal','hidden') DEFAULT NULL COMMENT '状态',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='会员规则表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='会员规则表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of fa_user_rule
|
||||
|
|
@ -553,7 +545,6 @@ COMMIT;
|
|||
-- ----------------------------
|
||||
-- Table structure for fa_user_score_log
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_user_score_log`;
|
||||
CREATE TABLE `fa_user_score_log` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '会员ID',
|
||||
|
|
@ -561,26 +552,24 @@ CREATE TABLE `fa_user_score_log` (
|
|||
`before` int(10) NOT NULL DEFAULT '0' COMMENT '变更前积分',
|
||||
`after` int(10) NOT NULL DEFAULT '0' COMMENT '变更后积分',
|
||||
`memo` varchar(255) DEFAULT '' COMMENT '备注',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='会员积分变动表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='会员积分变动表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fa_user_token
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_user_token`;
|
||||
CREATE TABLE `fa_user_token` (
|
||||
`token` varchar(50) NOT NULL COMMENT 'Token',
|
||||
`user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '会员ID',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`expiretime` int(10) DEFAULT NULL COMMENT '过期时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
`expiretime` bigint(16) DEFAULT NULL COMMENT '过期时间',
|
||||
PRIMARY KEY (`token`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='会员Token表';
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='会员Token表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for fa_version
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `fa_version`;
|
||||
CREATE TABLE `fa_version` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`oldversion` varchar(30) DEFAULT '' COMMENT '旧版本号',
|
||||
|
|
@ -589,11 +578,11 @@ CREATE TABLE `fa_version` (
|
|||
`content` varchar(500) DEFAULT '' COMMENT '升级内容',
|
||||
`downloadurl` varchar(255) DEFAULT '' COMMENT '下载地址',
|
||||
`enforce` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '强制更新',
|
||||
`createtime` int(10) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` int(10) DEFAULT NULL COMMENT '更新时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',
|
||||
`weigh` int(10) NOT NULL DEFAULT 0 COMMENT '权重',
|
||||
`status` varchar(30) DEFAULT '' COMMENT '状态',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='版本表';
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='版本表';
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
}
|
||||
|
||||
a {
|
||||
color: #18bc9c;
|
||||
color: #4e73df;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
}
|
||||
|
||||
.form-field input:focus {
|
||||
border-color: #18bc9c;
|
||||
border-color: #4e73df;
|
||||
background: #fff;
|
||||
color: #444;
|
||||
outline: none;
|
||||
|
|
@ -165,7 +165,7 @@
|
|||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="logo" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M64.433651,605.899968 C20.067302,536.265612 0,469.698785 0,389.731348 C0,174.488668 171.922656,0 384,0 C596.077344,0 768,174.488668 768,389.731348 C768,469.698785 747.932698,536.265612 703.566349,605.899968 C614.4,753.480595 441.6,870.4 384,870.4 C326.4,870.4 153.6,753.480595 64.433651,605.899968 L64.433651,605.899968 Z"
|
||||
id="body" fill="#18BC9C"></path>
|
||||
id="body" fill="#4e73df"></path>
|
||||
<path d="M429.648991,190.816 L430.160991,190.816 L429.648991,190.816 L429.648991,190.816 Z M429.648991,156 L427.088991,156 C419.408991,157.024 411.728991,160.608 404.560991,168.8 L403.024991,170.848 L206.928991,429.92 C198.736991,441.184 197.712991,453.984 204.368991,466.784 C210.512991,478.048 222.288991,485.728 235.600991,485.728 L336.464991,486.24 L304.208991,673.632 C301.648991,689.504 310.352991,705.376 325.200991,712.032 C329.808991,714.08 334.416991,714.592 339.536991,714.592 C349.776991,714.592 358.992991,709.472 366.160991,700.256 L561.744991,419.168 C569.936991,407.904 570.960991,395.104 564.304991,382.304 C557.648991,369.504 547.408991,363.36 533.072991,363.36 L432.208991,363.36 L463.952991,199.008 C464.464991,196.448 464.976991,193.376 464.976991,190.816 C464.976991,171.872 449.104991,156 431.184991,156 L429.648991,156 L429.648991,156 Z"
|
||||
id="flash" fill="#FFFFFF"></path>
|
||||
</g>
|
||||
|
|
@ -254,7 +254,7 @@
|
|||
</form>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="https://cdn.staticfile.org/jquery/2.1.4/jquery.min.js"></script>
|
||||
<script src="__ROOT__/assets/libs/jquery/dist/jquery.min.js"></script>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
|
|
@ -287,7 +287,7 @@
|
|||
if (typeof data.adminName !== 'undefined') {
|
||||
var url = location.href.replace(/install\.php/, data.adminName);
|
||||
$("#warmtips").html("{:__('Security tips')}" + '<a href="' + url + '">' + url + '</a>').show();
|
||||
$('<a class="btn" href="' + url + '" id="btn-admin" style="background:#18bc9c">' + "{:__('Dashboard')}" + '</a>').appendTo($buttons);
|
||||
$('<a class="btn" href="' + url + '" id="btn-admin" style="background:#4e73df">' + "{:__('Dashboard')}" + '</a>').appendTo($buttons);
|
||||
}
|
||||
localStorage.setItem("fastep", "installed");
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -20,13 +20,14 @@ return [
|
|||
'Dashboard' => '进入后台',
|
||||
'Go back' => '返回上一页',
|
||||
'Install Successed' => '安装成功!',
|
||||
'Security tips' => '温馨提示:请将以下后台登录入口添加到你的收藏夹,为了你的安全,不要泄漏或发送给他人!如有泄漏请及时修改!',
|
||||
'Security tips' => '温馨提示:请将以下后台登录入口添加到你的收藏夹,为了你的站点安全,不要泄漏或发送给他人!如有泄漏请及时修改!',
|
||||
'Please input correct database' => '请输入正确的数据库名',
|
||||
'Please input correct username' => '用户名只能由3-12位数字、字母、下划线组合',
|
||||
'Please input correct password' => '密码长度必须在6-16位之间,不能包含空格',
|
||||
'Please input correct username' => '用户名只能由3-30位数字、字母、下划线组合',
|
||||
'Please input correct password' => '密码长度必须在6-30位之间,不能包含空格',
|
||||
'Password is too weak' => '密码太简单,请重新输入',
|
||||
'The two passwords you entered did not match' => '两次输入的密码不一致',
|
||||
'Please input correct website' => '网站名称输入不正确',
|
||||
'The current version %s is too low, please use PHP 7.1 or higher' => '当前版本%s过低,请使用PHP7.1以上版本',
|
||||
'The current version %s is too low, please use PHP 7.4 or higher' => '当前版本%s过低,请使用PHP7.4及以上版本',
|
||||
'PDO is not currently installed and cannot be installed' => '当前未开启PDO,无法进行安装',
|
||||
'The current permissions are insufficient to write the file %s' => '当前权限不足,无法写入文件%s',
|
||||
'Please go to the official website to download the full package or resource package and try to install' => '当前代码仅包含核心代码,请前往官网下载完整包或资源包覆盖后再尝试安装',
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ class Min extends Command
|
|||
continue;
|
||||
}
|
||||
$config = preg_replace("/(urlArgs|baseUrl):(.*)\n/", '', $matches[1]);
|
||||
$config = preg_replace("/('tableexport'):(.*)\,\n/", "'tableexport': 'empty:',\n", $config);
|
||||
$data['config'] = $config;
|
||||
}
|
||||
// 生成压缩文件
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use app\common\model\Category;
|
|||
use fast\Form;
|
||||
use fast\Tree;
|
||||
use think\Db;
|
||||
use think\Loader;
|
||||
|
||||
if (!function_exists('build_select')) {
|
||||
|
||||
|
|
@ -17,8 +18,8 @@ if (!function_exists('build_select')) {
|
|||
*/
|
||||
function build_select($name, $options, $selected = [], $attr = [])
|
||||
{
|
||||
$options = is_array($options) ? $options : explode(',', $options);
|
||||
$selected = is_array($selected) ? $selected : explode(',', $selected);
|
||||
$options = is_array($options) ? $options : explode(',', $options ?? '');
|
||||
$selected = is_array($selected) ? $selected : explode(',', $selected ?? '');
|
||||
return Form::select($name, $options, $selected, $attr);
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +39,7 @@ if (!function_exists('build_radios')) {
|
|||
$selected = is_null($selected) ? key($list) : $selected;
|
||||
$selected = is_array($selected) ? $selected : explode(',', $selected);
|
||||
foreach ($list as $k => $v) {
|
||||
$html[] = sprintf(Form::label("{$name}-{$k}", "%s {$v}"), Form::radio($name, $k, in_array($k, $selected), ['id' => "{$name}-{$k}"]));
|
||||
$html[] = sprintf(Form::label("{$name}-{$k}", "%s " . str_replace('%', '%%', $v)), Form::radio($name, $k, in_array($k, $selected), ['id' => "{$name}-{$k}"]));
|
||||
}
|
||||
return '<div class="radio">' . implode(' ', $html) . '</div>';
|
||||
}
|
||||
|
|
@ -59,7 +60,7 @@ if (!function_exists('build_checkboxs')) {
|
|||
$selected = is_null($selected) ? [] : $selected;
|
||||
$selected = is_array($selected) ? $selected : explode(',', $selected);
|
||||
foreach ($list as $k => $v) {
|
||||
$html[] = sprintf(Form::label("{$name}-{$k}", "%s {$v}"), Form::checkbox($name, $k, in_array($k, $selected), ['id' => "{$name}-{$k}"]));
|
||||
$html[] = sprintf(Form::label("{$name}-{$k}", "%s " . str_replace('%', '%%', $v)), Form::checkbox($name, $k, in_array($k, $selected), ['id' => "{$name}-{$k}"]));
|
||||
}
|
||||
return '<div class="checkbox">' . implode(' ', $html) . '</div>';
|
||||
}
|
||||
|
|
@ -102,7 +103,7 @@ if (!function_exists('build_toolbar')) {
|
|||
function build_toolbar($btns = null, $attr = [])
|
||||
{
|
||||
$auth = \app\admin\library\Auth::instance();
|
||||
$controller = str_replace('.', '/', strtolower(think\Request::instance()->controller()));
|
||||
$controller = str_replace('.', '/', Loader::parseName(request()->controller()));
|
||||
$btns = $btns ? $btns : ['refresh', 'add', 'edit', 'del', 'import'];
|
||||
$btns = is_array($btns) ? $btns : explode(',', $btns);
|
||||
$index = array_search('delete', $btns);
|
||||
|
|
@ -120,7 +121,7 @@ if (!function_exists('build_toolbar')) {
|
|||
$html = [];
|
||||
foreach ($btns as $k => $v) {
|
||||
//如果未定义或没有权限
|
||||
if (!isset($btnAttr[$v]) || ($v !== 'refresh' && !$auth->check("{$controller}/{$v}"))) {
|
||||
if (!isset($btnAttr[$v]) || ($v !== 'refresh' && !$auth->check("{$controller}/{$v}", $auth->id))) {
|
||||
continue;
|
||||
}
|
||||
list($href, $class, $icon, $text, $title) = $btnAttr[$v];
|
||||
|
|
@ -175,7 +176,7 @@ if (!function_exists('build_heading')) {
|
|||
$title = $content = '';
|
||||
if (is_null($path)) {
|
||||
$action = request()->action();
|
||||
$controller = str_replace('.', '/', request()->controller());
|
||||
$controller = str_replace('.', '/', Loader::parseName(request()->controller()));
|
||||
$path = strtolower($controller . ($action && $action != 'index' ? '/' . $action : ''));
|
||||
}
|
||||
// 根据当前的URI自动匹配父节点的标题和备注
|
||||
|
|
@ -194,33 +195,3 @@ if (!function_exists('build_heading')) {
|
|||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('build_suffix_image')) {
|
||||
/**
|
||||
* 生成文件后缀图片
|
||||
* @param string $suffix 后缀
|
||||
* @param null $background
|
||||
* @return string
|
||||
*/
|
||||
function build_suffix_image($suffix, $background = null)
|
||||
{
|
||||
$suffix = mb_substr(strtoupper($suffix), 0, 4);
|
||||
$total = unpack('L', hash('adler32', $suffix, true))[1];
|
||||
$hue = $total % 360;
|
||||
list($r, $g, $b) = hsv2rgb($hue / 360, 0.3, 0.9);
|
||||
|
||||
$background = $background ? $background : "rgb({$r},{$g},{$b})";
|
||||
|
||||
$icon = <<<EOT
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<path style="fill:#E2E5E7;" d="M128,0c-17.6,0-32,14.4-32,32v448c0,17.6,14.4,32,32,32h320c17.6,0,32-14.4,32-32V128L352,0H128z"/>
|
||||
<path style="fill:#B0B7BD;" d="M384,128h96L352,0v96C352,113.6,366.4,128,384,128z"/>
|
||||
<polygon style="fill:#CAD1D8;" points="480,224 384,128 480,128 "/>
|
||||
<path style="fill:{$background};" d="M416,416c0,8.8-7.2,16-16,16H48c-8.8,0-16-7.2-16-16V256c0-8.8,7.2-16,16-16h352c8.8,0,16,7.2,16,16 V416z"/>
|
||||
<path style="fill:#CAD1D8;" d="M400,432H96v16h304c8.8,0,16-7.2,16-16v-16C416,424.8,408.8,432,400,432z"/>
|
||||
<g><text><tspan x="220" y="380" font-size="124" font-family="Verdana, Helvetica, Arial, sans-serif" fill="white" text-anchor="middle">{$suffix}</tspan></text></g>
|
||||
</svg>
|
||||
EOT;
|
||||
return $icon;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@ class Addon extends Backend
|
|||
public function _initialize()
|
||||
{
|
||||
parent::_initialize();
|
||||
if (!$this->auth->isSuperAdmin() && in_array($this->request->action(), ['install', 'uninstall', 'local', 'upgrade'])) {
|
||||
if (!$this->auth->isSuperAdmin() && in_array($this->request->action(), ['install', 'uninstall', 'local', 'upgrade', 'authorization', 'testdata'])) {
|
||||
$this->error(__('Access is allowed only to the super management group'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看
|
||||
* 插件列表
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
|
@ -41,7 +41,7 @@ class Addon extends Backend
|
|||
$v['config'] = $config ? 1 : 0;
|
||||
$v['url'] = str_replace($this->request->server('SCRIPT_NAME'), '', $v['url']);
|
||||
}
|
||||
$this->assignconfig(['addons' => $addons, 'api_url' => config('fastadmin.api_url'), 'faversion' => config('fastadmin.version')]);
|
||||
$this->assignconfig(['addons' => $addons, 'api_url' => config('fastadmin.api_url'), 'faversion' => config('fastadmin.version'), 'domain' => request()->host(true)]);
|
||||
return $this->view->fetch();
|
||||
}
|
||||
|
||||
|
|
@ -57,13 +57,10 @@ class Addon extends Backend
|
|||
if (!preg_match("/^[a-zA-Z0-9]+$/", $name)) {
|
||||
$this->error(__('Addon name incorrect'));
|
||||
}
|
||||
if (!is_dir(ADDON_PATH . $name)) {
|
||||
$this->error(__('Directory not found'));
|
||||
}
|
||||
$info = get_addon_info($name);
|
||||
$config = get_addon_fullconfig($name);
|
||||
if (!$info) {
|
||||
$this->error(__('No Results were found'));
|
||||
$this->error(__('Addon not exists'));
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$params = $this->request->post("row/a", [], 'trim');
|
||||
|
|
@ -80,23 +77,43 @@ class Addon extends Backend
|
|||
}
|
||||
}
|
||||
try {
|
||||
//更新配置文件
|
||||
set_addon_fullconfig($name, $config);
|
||||
Service::refresh();
|
||||
$this->success();
|
||||
$addon = get_addon_instance($name);
|
||||
//插件自定义配置实现逻辑
|
||||
if (method_exists($addon, 'config')) {
|
||||
$addon->config($name, $config);
|
||||
} else {
|
||||
//更新配置文件
|
||||
set_addon_fullconfig($name, $config);
|
||||
Service::refresh();
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->error(__($e->getMessage()));
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
$this->error(__('Parameter %s can not be empty', ''));
|
||||
}
|
||||
$tips = [];
|
||||
$groupList = [];
|
||||
$ungroupList = [];
|
||||
foreach ($config as $index => &$item) {
|
||||
//如果有设置分组
|
||||
if (isset($item['group']) && $item['group']) {
|
||||
if (!in_array($item['group'], $groupList)) {
|
||||
$groupList["custom" . (count($groupList) + 1)] = $item['group'];
|
||||
}
|
||||
} elseif ($item['name'] != '__tips__') {
|
||||
$ungroupList[] = $item['name'];
|
||||
}
|
||||
if ($item['name'] == '__tips__') {
|
||||
$tips = $item;
|
||||
unset($config[$index]);
|
||||
}
|
||||
}
|
||||
if ($ungroupList) {
|
||||
$groupList['other'] = '其它';
|
||||
}
|
||||
$this->view->assign("groupList", $groupList);
|
||||
$this->view->assign("addon", ['info' => $info, 'config' => $config, 'tips' => $tips]);
|
||||
$configFile = ADDON_PATH . $name . DS . 'config.html';
|
||||
$viewFile = is_file($configFile) ? $configFile : '';
|
||||
|
|
@ -218,6 +235,7 @@ class Addon extends Backend
|
|||
$uid = $this->request->post("uid");
|
||||
$token = $this->request->post("token");
|
||||
$faversion = $this->request->post("faversion");
|
||||
$force = $this->request->post("force");
|
||||
if (!$uid || !$token) {
|
||||
throw new Exception(__('Please login and try to install'));
|
||||
}
|
||||
|
|
@ -226,7 +244,7 @@ class Addon extends Backend
|
|||
'token' => $token,
|
||||
'faversion' => $faversion
|
||||
];
|
||||
$info = Service::local($file, $extend);
|
||||
$info = Service::local($file, $extend, $force);
|
||||
} catch (AddonException $e) {
|
||||
$this->result($e->getData(), $e->getCode(), __($e->getMessage()));
|
||||
} catch (Exception $e) {
|
||||
|
|
@ -254,15 +272,17 @@ class Addon extends Backend
|
|||
|
||||
$info = [];
|
||||
try {
|
||||
$info = get_addon_info($name);
|
||||
$uid = $this->request->post("uid");
|
||||
$token = $this->request->post("token");
|
||||
$version = $this->request->post("version");
|
||||
$faversion = $this->request->post("faversion");
|
||||
$extend = [
|
||||
'uid' => $uid,
|
||||
'token' => $token,
|
||||
'version' => $version,
|
||||
'faversion' => $faversion
|
||||
'uid' => $uid,
|
||||
'token' => $token,
|
||||
'version' => $version,
|
||||
'oldversion' => $info['version'] ?? '',
|
||||
'faversion' => $faversion
|
||||
];
|
||||
//调用更新的方法
|
||||
$info = Service::upgrade($name, $extend);
|
||||
|
|
@ -275,6 +295,29 @@ class Addon extends Backend
|
|||
$this->success(__('Operate successful'), '', ['addon' => $info]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试数据
|
||||
*/
|
||||
public function testdata()
|
||||
{
|
||||
$name = $this->request->post("name");
|
||||
if (!$name) {
|
||||
$this->error(__('Parameter %s can not be empty', 'name'));
|
||||
}
|
||||
if (!preg_match("/^[a-zA-Z0-9]+$/", $name)) {
|
||||
$this->error(__('Addon name incorrect'));
|
||||
}
|
||||
|
||||
try {
|
||||
Service::importsql($name, 'testdata.sql');
|
||||
} catch (AddonException $e) {
|
||||
$this->result($e->getData(), $e->getCode(), __($e->getMessage()));
|
||||
} catch (Exception $e) {
|
||||
$this->error(__($e->getMessage()), $e->getCode());
|
||||
}
|
||||
$this->success(__('Import successful'), '');
|
||||
}
|
||||
|
||||
/**
|
||||
* 已装插件
|
||||
*/
|
||||
|
|
@ -282,25 +325,9 @@ class Addon extends Backend
|
|||
{
|
||||
$offset = (int)$this->request->get("offset");
|
||||
$limit = (int)$this->request->get("limit");
|
||||
$filter = $this->request->get("filter");
|
||||
$search = $this->request->get("search");
|
||||
$search = htmlspecialchars(strip_tags($search));
|
||||
$onlineaddons = Cache::get("onlineaddons");
|
||||
if (!is_array($onlineaddons) && config('fastadmin.api_url')) {
|
||||
$onlineaddons = [];
|
||||
$result = Http::sendRequest(config('fastadmin.api_url') . '/addon/index', [], 'GET', [
|
||||
CURLOPT_HTTPHEADER => ['Accept-Encoding:gzip'],
|
||||
CURLOPT_ENCODING => "gzip"
|
||||
]);
|
||||
if ($result['ret']) {
|
||||
$json = (array)json_decode($result['msg'], true);
|
||||
$rows = isset($json['rows']) ? $json['rows'] : [];
|
||||
foreach ($rows as $index => $row) {
|
||||
$onlineaddons[$row['name']] = $row;
|
||||
}
|
||||
}
|
||||
Cache::set("onlineaddons", $onlineaddons, 600);
|
||||
}
|
||||
$filter = $this->request->get("filter", '');
|
||||
$search = $this->request->get("search", '', 'strip_tags,htmlspecialchars');
|
||||
$onlineaddons = $this->getAddonList();
|
||||
$filter = (array)json_decode($filter, true);
|
||||
$addons = get_addon_list();
|
||||
$list = [];
|
||||
|
|
@ -311,19 +338,19 @@ class Addon extends Backend
|
|||
|
||||
if (isset($onlineaddons[$v['name']])) {
|
||||
$v = array_merge($v, $onlineaddons[$v['name']]);
|
||||
$v['price'] = '-';
|
||||
} else {
|
||||
$v['category_id'] = 0;
|
||||
$v['flag'] = '';
|
||||
$v['banner'] = '';
|
||||
$v['image'] = '';
|
||||
$v['donateimage'] = '';
|
||||
$v['demourl'] = '';
|
||||
$v['price'] = __('None');
|
||||
$v['screenshots'] = [];
|
||||
$v['releaselist'] = [];
|
||||
$v['url'] = addon_url($v['name']);
|
||||
$v['url'] = str_replace($this->request->server('SCRIPT_NAME'), '', $v['url']);
|
||||
}
|
||||
$v['url'] = addon_url($v['name']);
|
||||
$v['url'] = str_replace($this->request->server('SCRIPT_NAME'), '', $v['url']);
|
||||
$v['createtime'] = filemtime(ADDON_PATH . $v['name']);
|
||||
if ($filter && isset($filter['category_id']) && is_numeric($filter['category_id']) && $filter['category_id'] != $v['category_id']) {
|
||||
continue;
|
||||
|
|
@ -340,6 +367,48 @@ class Addon extends Backend
|
|||
return $callback($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测
|
||||
*/
|
||||
public function isbuy()
|
||||
{
|
||||
$name = $this->request->post("name");
|
||||
$uid = $this->request->post("uid");
|
||||
$token = $this->request->post("token");
|
||||
$version = $this->request->post("version");
|
||||
$faversion = $this->request->post("faversion");
|
||||
$extend = [
|
||||
'uid' => $uid,
|
||||
'token' => $token,
|
||||
'version' => $version,
|
||||
'faversion' => $faversion
|
||||
];
|
||||
try {
|
||||
$result = Service::isBuy($name, $extend);
|
||||
} catch (Exception $e) {
|
||||
$this->error(__($e->getMessage()));
|
||||
}
|
||||
return json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新授权
|
||||
*/
|
||||
public function authorization()
|
||||
{
|
||||
$params = [
|
||||
'uid' => $this->request->post('uid'),
|
||||
'token' => $this->request->post('token'),
|
||||
'faversion' => $this->request->post('faversion'),
|
||||
];
|
||||
try {
|
||||
Service::authorization($params);
|
||||
} catch (Exception $e) {
|
||||
$this->error(__($e->getMessage()));
|
||||
}
|
||||
$this->success(__('Operate successful'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件相关表
|
||||
*/
|
||||
|
|
@ -360,4 +429,34 @@ class Addon extends Backend
|
|||
$tables = array_values($tables);
|
||||
$this->success('', null, ['tables' => $tables]);
|
||||
}
|
||||
|
||||
protected function getAddonList()
|
||||
{
|
||||
$onlineaddons = Cache::get("onlineaddons");
|
||||
if (!is_array($onlineaddons) && config('fastadmin.api_url')) {
|
||||
$onlineaddons = [];
|
||||
$params = [
|
||||
'uid' => $this->request->post('uid'),
|
||||
'token' => $this->request->post('token'),
|
||||
'version' => config('fastadmin.version'),
|
||||
'faversion' => config('fastadmin.version'),
|
||||
];
|
||||
$json = [];
|
||||
try {
|
||||
$json = Service::addons($params);
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
$rows = $json['rows'] ?? [];
|
||||
foreach ($rows as $index => $row) {
|
||||
if (!isset($row['name'])) {
|
||||
continue;
|
||||
}
|
||||
$onlineaddons[$row['name']] = $row;
|
||||
}
|
||||
Cache::set("onlineaddons", $onlineaddons, 600);
|
||||
}
|
||||
return $onlineaddons;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ use think\Cache;
|
|||
use think\Config;
|
||||
use think\Db;
|
||||
use think\Lang;
|
||||
use think\Loader;
|
||||
use think\Response;
|
||||
use think\Validate;
|
||||
|
||||
/**
|
||||
|
|
@ -37,17 +39,30 @@ class Ajax extends Backend
|
|||
*/
|
||||
public function lang()
|
||||
{
|
||||
header('Content-Type: application/javascript');
|
||||
header("Cache-Control: public");
|
||||
header("Pragma: cache");
|
||||
$this->request->get(['callback' => 'define']);
|
||||
$header = ['Content-Type' => 'application/javascript'];
|
||||
if (!config('app_debug')) {
|
||||
$offset = 30 * 60 * 60 * 24; // 缓存一个月
|
||||
$header['Cache-Control'] = 'public';
|
||||
$header['Pragma'] = 'cache';
|
||||
$header['Expires'] = gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
|
||||
}
|
||||
|
||||
$offset = 30 * 60 * 60 * 24; // 缓存一个月
|
||||
header("Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT");
|
||||
$controllername = $this->request->get('controllername');
|
||||
$lang = $this->request->get('lang');
|
||||
if (!$lang || !in_array($lang, config('allow_lang_list')) || !$controllername || !preg_match("/^[a-z0-9_\.]+$/i", $controllername)) {
|
||||
return jsonp(['errmsg' => '参数错误'], 200, [], ['json_encode_param' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]);
|
||||
}
|
||||
|
||||
$controllername = input("controllername");
|
||||
//默认只加载了控制器对应的语言名,你还根据控制器名来加载额外的语言包
|
||||
$this->loadlang($controllername);
|
||||
return jsonp(Lang::get(), 200, [], ['json_encode_param' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]);
|
||||
$className = Loader::parseClass($this->request->module(), 'controller', $controllername, false);
|
||||
|
||||
//存在对应的类才加载
|
||||
if (class_exists($className)) {
|
||||
$this->loadlang($controllername);
|
||||
}
|
||||
|
||||
return jsonp(Lang::get(), 200, $header, ['json_encode_param' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -56,8 +71,10 @@ class Ajax extends Backend
|
|||
public function upload()
|
||||
{
|
||||
Config::set('default_return_type', 'json');
|
||||
//必须设定cdnurl为空,否则cdnurl函数计算错误
|
||||
Config::set('upload.cdnurl', '');
|
||||
|
||||
//必须还原upload配置,否则分片及cdnurl函数计算错误
|
||||
Config::load(APP_PATH . 'extra/upload.php', 'upload');
|
||||
|
||||
$chunkid = $this->request->post("chunkid");
|
||||
if ($chunkid) {
|
||||
if (!Config::get('upload.chunking')) {
|
||||
|
|
@ -270,18 +287,18 @@ class Ajax extends Backend
|
|||
{
|
||||
$params = $this->request->get("row/a");
|
||||
if (!empty($params)) {
|
||||
$province = isset($params['province']) ? $params['province'] : '';
|
||||
$city = isset($params['city']) ? $params['city'] : '';
|
||||
$province = isset($params['province']) ? $params['province'] : null;
|
||||
$city = isset($params['city']) ? $params['city'] : null;
|
||||
} else {
|
||||
$province = $this->request->get('province', '');
|
||||
$city = $this->request->get('city', '');
|
||||
$province = $this->request->get('province');
|
||||
$city = $this->request->get('city');
|
||||
}
|
||||
$where = ['pid' => 0, 'level' => 1];
|
||||
$provincelist = null;
|
||||
if ($province !== '') {
|
||||
if ($province !== null) {
|
||||
$where['pid'] = $province;
|
||||
$where['level'] = 2;
|
||||
if ($city !== '') {
|
||||
if ($city !== null) {
|
||||
$where['pid'] = $city;
|
||||
$where['level'] = 3;
|
||||
}
|
||||
|
|
@ -296,10 +313,15 @@ class Ajax extends Backend
|
|||
public function icon()
|
||||
{
|
||||
$suffix = $this->request->request("suffix");
|
||||
header('Content-type: image/svg+xml');
|
||||
$suffix = $suffix ? $suffix : "FILE";
|
||||
echo build_suffix_image($suffix);
|
||||
exit;
|
||||
$data = build_suffix_image($suffix);
|
||||
$header = ['Content-Type' => 'image/svg+xml'];
|
||||
$offset = 30 * 60 * 60 * 24; // 缓存一个月
|
||||
$header['Cache-Control'] = 'public';
|
||||
$header['Pragma'] = 'cache';
|
||||
$header['Expires'] = gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
|
||||
$response = Response::create($data, '', 200, $header);
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,25 +45,34 @@ class Dashboard extends Backend
|
|||
}
|
||||
|
||||
$dbTableList = Db::query("SHOW TABLE STATUS");
|
||||
$addonList = get_addon_list();
|
||||
$totalworkingaddon = 0;
|
||||
$totaladdon = count($addonList);
|
||||
foreach ($addonList as $index => $item) {
|
||||
if ($item['state']) {
|
||||
$totalworkingaddon += 1;
|
||||
}
|
||||
}
|
||||
$this->view->assign([
|
||||
'totaluser' => User::count(),
|
||||
'totaladdon' => count(get_addon_list()),
|
||||
'totaladmin' => Admin::count(),
|
||||
'totalcategory' => \app\common\model\Category::count(),
|
||||
'todayusersignup' => User::whereTime('jointime', 'today')->count(),
|
||||
'todayuserlogin' => User::whereTime('logintime', 'today')->count(),
|
||||
'sevendau' => User::whereTime('jointime|logintime|prevtime', '-7 days')->count(),
|
||||
'thirtydau' => User::whereTime('jointime|logintime|prevtime', '-30 days')->count(),
|
||||
'threednu' => User::whereTime('jointime', '-3 days')->count(),
|
||||
'sevendnu' => User::whereTime('jointime', '-7 days')->count(),
|
||||
'dbtablenums' => count($dbTableList),
|
||||
'dbsize' => array_sum(array_map(function ($item) {
|
||||
'totaluser' => User::count(),
|
||||
'totaladdon' => $totaladdon,
|
||||
'totaladmin' => Admin::count(),
|
||||
'totalcategory' => \app\common\model\Category::count(),
|
||||
'todayusersignup' => User::whereTime('jointime', 'today')->count(),
|
||||
'todayuserlogin' => User::whereTime('logintime', 'today')->count(),
|
||||
'sevendau' => User::whereTime('jointime|logintime|prevtime', '-7 days')->count(),
|
||||
'thirtydau' => User::whereTime('jointime|logintime|prevtime', '-30 days')->count(),
|
||||
'threednu' => User::whereTime('jointime', '-3 days')->count(),
|
||||
'sevendnu' => User::whereTime('jointime', '-7 days')->count(),
|
||||
'dbtablenums' => count($dbTableList),
|
||||
'dbsize' => array_sum(array_map(function ($item) {
|
||||
return $item['Data_length'] + $item['Index_length'];
|
||||
}, $dbTableList)),
|
||||
'attachmentnums' => Attachment::count(),
|
||||
'attachmentsize' => Attachment::sum('filesize'),
|
||||
'picturenums' => Attachment::where('mimetype', 'like', 'image/%')->count(),
|
||||
'picturesize' => Attachment::where('mimetype', 'like', 'image/%')->sum('filesize'),
|
||||
'totalworkingaddon' => $totalworkingaddon,
|
||||
'attachmentnums' => Attachment::count(),
|
||||
'attachmentsize' => Attachment::sum('filesize'),
|
||||
'picturenums' => Attachment::where('mimetype', 'like', 'image/%')->count(),
|
||||
'picturesize' => Attachment::where('mimetype', 'like', 'image/%')->sum('filesize'),
|
||||
]);
|
||||
|
||||
$this->assignconfig('column', array_keys($userlist));
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use app\admin\model\AdminLog;
|
|||
use app\common\controller\Backend;
|
||||
use think\Config;
|
||||
use think\Hook;
|
||||
use think\Session;
|
||||
use think\Validate;
|
||||
|
||||
/**
|
||||
|
|
@ -31,12 +32,18 @@ class Index extends Backend
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
$cookieArr = ['adminskin' => "/^skin\-([a-z\-]+)\$/i", 'multiplenav' => "/^(0|1)\$/", 'multipletab' => "/^(0|1)\$/", 'show_submenu' => "/^(0|1)\$/"];
|
||||
foreach ($cookieArr as $key => $regex) {
|
||||
$cookieValue = $this->request->cookie($key);
|
||||
if (!is_null($cookieValue) && preg_match($regex, $cookieValue)) {
|
||||
config('fastadmin.' . $key, $cookieValue);
|
||||
}
|
||||
}
|
||||
//左侧菜单
|
||||
list($menulist, $navlist, $fixedmenu, $referermenu) = $this->auth->getSidebar([
|
||||
'dashboard' => 'hot',
|
||||
'addon' => ['new', 'red', 'badge'],
|
||||
'auth/rule' => __('Menu'),
|
||||
'general' => ['new', 'purple'],
|
||||
], $this->view->site['fixedpage']);
|
||||
$action = $this->request->request('action');
|
||||
if ($this->request->isPost()) {
|
||||
|
|
@ -44,6 +51,7 @@ class Index extends Backend
|
|||
$this->success('', null, ['menulist' => $menulist, 'navlist' => $navlist]);
|
||||
}
|
||||
}
|
||||
$this->assignconfig('cookie', ['prefix' => config('cookie.prefix')]);
|
||||
$this->view->assign('menulist', $menulist);
|
||||
$this->view->assign('navlist', $navlist);
|
||||
$this->view->assign('fixedmenu', $fixedmenu);
|
||||
|
|
@ -57,13 +65,16 @@ class Index extends Backend
|
|||
*/
|
||||
public function login()
|
||||
{
|
||||
$url = $this->request->get('url', 'index/index');
|
||||
$url = $this->request->get('url', '', 'url_clean');
|
||||
$url = $url ?: 'index/index';
|
||||
if ($this->auth->isLogin()) {
|
||||
$this->success(__("You've logged in, do not login again"), $url);
|
||||
}
|
||||
//保持会话有效时长,单位:小时
|
||||
$keeyloginhours = 24;
|
||||
if ($this->request->isPost()) {
|
||||
$username = $this->request->post('username');
|
||||
$password = $this->request->post('password');
|
||||
$password = $this->request->post('password', '', null);
|
||||
$keeplogin = $this->request->post('keeplogin');
|
||||
$token = $this->request->post('__token__');
|
||||
$rule = [
|
||||
|
|
@ -86,7 +97,7 @@ class Index extends Backend
|
|||
$this->error($validate->getError(), $url, ['token' => $this->request->token()]);
|
||||
}
|
||||
AdminLog::setTitle(__('Login'));
|
||||
$result = $this->auth->login($username, $password, $keeplogin ? 86400 : 0);
|
||||
$result = $this->auth->login($username, $password, $keeplogin ? $keeyloginhours * 3600 : 0);
|
||||
if ($result === true) {
|
||||
Hook::listen("admin_login_after", $this->request);
|
||||
$this->success(__('Login successful'), $url, ['url' => $url, 'id' => $this->auth->id, 'username' => $username, 'avatar' => $this->auth->avatar]);
|
||||
|
|
@ -99,10 +110,12 @@ class Index extends Backend
|
|||
|
||||
// 根据客户端的cookie,判断是否可以自动登录
|
||||
if ($this->auth->autologin()) {
|
||||
Session::delete("referer");
|
||||
$this->redirect($url);
|
||||
}
|
||||
$background = Config::get('fastadmin.login_background');
|
||||
$background = $background ? (stripos($background, 'http') === 0 ? $background : config('site.cdnurl') . $background) : '';
|
||||
$this->view->assign('keeyloginhours', $keeyloginhours);
|
||||
$this->view->assign('background', $background);
|
||||
$this->view->assign('title', __('Login'));
|
||||
Hook::listen("admin_login_init", $this->request);
|
||||
|
|
|
|||
|
|
@ -125,11 +125,11 @@ class Admin extends Backend
|
|||
if ($params) {
|
||||
Db::startTrans();
|
||||
try {
|
||||
if (!Validate::is($params['password'], '\S{6,16}')) {
|
||||
if (!Validate::is($params['password'], '\S{6,30}')) {
|
||||
exception(__("Please input correct password"));
|
||||
}
|
||||
$params['salt'] = Random::alnum();
|
||||
$params['password'] = md5(md5($params['password']) . $params['salt']);
|
||||
$params['password'] = $this->auth->getEncryptPassword($params['password'], $params['salt']);
|
||||
$params['avatar'] = '/assets/img/avatar.png'; //设置新管理员默认头像。
|
||||
$result = $this->model->validate('Admin.add')->save($params);
|
||||
if ($result === false) {
|
||||
|
|
@ -179,19 +179,20 @@ class Admin extends Backend
|
|||
Db::startTrans();
|
||||
try {
|
||||
if ($params['password']) {
|
||||
if (!Validate::is($params['password'], '\S{6,16}')) {
|
||||
if (!Validate::is($params['password'], '\S{6,30}')) {
|
||||
exception(__("Please input correct password"));
|
||||
}
|
||||
$params['salt'] = Random::alnum();
|
||||
$params['password'] = md5(md5($params['password']) . $params['salt']);
|
||||
$params['password'] = $this->auth->getEncryptPassword($params['password'], $params['salt']);
|
||||
} else {
|
||||
unset($params['password'], $params['salt']);
|
||||
}
|
||||
//这里需要针对username和email做唯一验证
|
||||
$adminValidate = \think\Loader::validate('Admin');
|
||||
$adminValidate->rule([
|
||||
'username' => 'require|regex:\w{3,12}|unique:admin,username,' . $row->id,
|
||||
'username' => 'require|regex:\w{3,30}|unique:admin,username,' . $row->id,
|
||||
'email' => 'require|email|unique:admin,email,' . $row->id,
|
||||
'mobile' => 'regex:1[3-9]\d{9}|unique:admin,mobile,' . $row->id,
|
||||
'password' => 'regex:\S{32}',
|
||||
]);
|
||||
$result = $row->validate('Admin.edit')->save($params);
|
||||
|
|
|
|||
|
|
@ -44,9 +44,16 @@ class Adminlog extends Backend
|
|||
$this->request->filter(['strip_tags', 'trim']);
|
||||
if ($this->request->isAjax()) {
|
||||
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
|
||||
$isSuperAdmin = $this->auth->isSuperAdmin();
|
||||
$childrenAdminIds = $this->childrenAdminIds;
|
||||
$list = $this->model
|
||||
->where($where)
|
||||
->where('admin_id', 'in', $this->childrenAdminIds)
|
||||
->where(function ($query) use ($isSuperAdmin, $childrenAdminIds) {
|
||||
if (!$isSuperAdmin) {
|
||||
$query->where('admin_id', 'in', $childrenAdminIds);
|
||||
}
|
||||
})
|
||||
->field('content,useragent', true)
|
||||
->order($sort, $order)
|
||||
->paginate($limit);
|
||||
|
||||
|
|
@ -66,8 +73,10 @@ class Adminlog extends Backend
|
|||
if (!$row) {
|
||||
$this->error(__('No Results were found'));
|
||||
}
|
||||
if (!$row['admin_id'] || !in_array($row['admin_id'], $this->childrenAdminIds)) {
|
||||
$this->error(__('You have no permission'));
|
||||
if (!$this->auth->isSuperAdmin()) {
|
||||
if (!$row['admin_id'] || !in_array($row['admin_id'], $this->childrenAdminIds)) {
|
||||
$this->error(__('You have no permission'));
|
||||
}
|
||||
}
|
||||
$this->view->assign("row", $row->toArray());
|
||||
return $this->view->fetch();
|
||||
|
|
@ -101,7 +110,15 @@ class Adminlog extends Backend
|
|||
}
|
||||
$ids = $ids ? $ids : $this->request->post("ids");
|
||||
if ($ids) {
|
||||
$adminList = $this->model->where('id', 'in', $ids)->where('admin_id', 'in', $this->childrenAdminIds)->select();
|
||||
$isSuperAdmin = $this->auth->isSuperAdmin();
|
||||
$childrenAdminIds = $this->childrenAdminIds;
|
||||
$adminList = $this->model->where('id', 'in', $ids)
|
||||
->where(function ($query) use ($isSuperAdmin, $childrenAdminIds) {
|
||||
if (!$isSuperAdmin) {
|
||||
$query->where('admin_id', 'in', $childrenAdminIds);
|
||||
}
|
||||
})
|
||||
->select();
|
||||
if ($adminList) {
|
||||
$deleteIds = [];
|
||||
foreach ($adminList as $k => $v) {
|
||||
|
|
@ -126,8 +143,4 @@ class Adminlog extends Backend
|
|||
$this->error();
|
||||
}
|
||||
|
||||
public function selectpage()
|
||||
{
|
||||
return parent::selectpage();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class Rule extends Backend
|
|||
$v['title'] = __($v['title']);
|
||||
}
|
||||
unset($v);
|
||||
Tree::instance()->init($ruleList);
|
||||
Tree::instance()->init($ruleList)->icon = [' ', ' ', ' '];
|
||||
$this->rulelist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'title');
|
||||
$ruledata = [0 => __('None')];
|
||||
foreach ($this->rulelist as $k => &$v) {
|
||||
|
|
@ -118,7 +118,7 @@ class Rule extends Backend
|
|||
//这里需要针对name做唯一验证
|
||||
$ruleValidate = \think\Loader::validate('AuthRule');
|
||||
$ruleValidate->rule([
|
||||
'name' => 'require|format|unique:AuthRule,name,' . $row->id,
|
||||
'name' => 'require|unique:AuthRule,name,' . $row->id,
|
||||
]);
|
||||
$result = $row->validate()->save($params);
|
||||
if ($result === false) {
|
||||
|
|
|
|||
|
|
@ -45,17 +45,13 @@ class Attachment extends Backend
|
|||
$filterArr['category'] = ',unclassed';
|
||||
$this->request->get(['filter' => json_encode(array_diff_key($filterArr, ['category' => '']))]);
|
||||
}
|
||||
if (isset($filterArr['mimetype']) && preg_match("/[]\,|\*]/", $filterArr['mimetype'])) {
|
||||
if (isset($filterArr['mimetype']) && preg_match("/(\/|\,|\*)/", $filterArr['mimetype'])) {
|
||||
$mimetype = $filterArr['mimetype'];
|
||||
$filterArr = array_diff_key($filterArr, ['mimetype' => '']);
|
||||
$mimetypeQuery = function ($query) use ($mimetype) {
|
||||
$mimetypeArr = explode(',', $mimetype);
|
||||
$mimetypeArr = array_filter(explode(',', $mimetype));
|
||||
foreach ($mimetypeArr as $index => $item) {
|
||||
if (stripos($item, "/*") !== false) {
|
||||
$query->whereOr('mimetype', 'like', str_replace("/*", "/", $item) . '%');
|
||||
} else {
|
||||
$query->whereOr('mimetype', 'like', '%' . $item . '%');
|
||||
}
|
||||
$query->whereOr('mimetype', 'like', '%' . str_replace("/*", "/", $item) . '%');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -89,6 +85,9 @@ class Attachment extends Backend
|
|||
if ($this->request->isAjax()) {
|
||||
return $this->index();
|
||||
}
|
||||
$mimetype = $this->request->get('mimetype', '');
|
||||
$mimetype = substr($mimetype, -1) === '/' ? $mimetype . '*' : $mimetype;
|
||||
$this->view->assign('mimetype', $mimetype);
|
||||
return $this->view->fetch();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,10 @@ class Config extends Backend
|
|||
$value['value'] = json_encode($dictValue, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
$value['tip'] = htmlspecialchars($value['tip']);
|
||||
if ($value['name'] == 'cdnurl') {
|
||||
//cdnurl不支持在线修改
|
||||
continue;
|
||||
}
|
||||
$siteList[$v['group']]['list'][] = $value;
|
||||
}
|
||||
$index = 0;
|
||||
|
|
@ -88,6 +92,9 @@ class Config extends Backend
|
|||
*/
|
||||
public function add()
|
||||
{
|
||||
if (!config('app_debug')) {
|
||||
$this->error(__('Only work at development environment'));
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$this->token();
|
||||
$params = $this->request->post("row/a", [], 'trim');
|
||||
|
|
@ -166,6 +173,9 @@ class Config extends Backend
|
|||
*/
|
||||
public function del($ids = "")
|
||||
{
|
||||
if (!config('app_debug')) {
|
||||
$this->error(__('Only work at development environment'));
|
||||
}
|
||||
$name = $this->request->post('name');
|
||||
$config = ConfigModel::getByName($name);
|
||||
if ($name && $config) {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class Profile extends Backend
|
|||
$this->error(__("Please input correct email"));
|
||||
}
|
||||
if (isset($params['password'])) {
|
||||
if (!Validate::is($params['password'], "/^[\S]{6,16}$/")) {
|
||||
if (!Validate::is($params['password'], "/^[\S]{6,30}$/")) {
|
||||
$this->error(__("Please input correct password"));
|
||||
}
|
||||
$params['salt'] = Random::alnum();
|
||||
|
|
@ -74,6 +74,7 @@ class Profile extends Backend
|
|||
$admin->save($params);
|
||||
//因为个人资料面板读取的Session显示,修改自己资料后同时更新Session
|
||||
Session::set("admin", $admin->toArray());
|
||||
Session::set("admin.safecode", $this->auth->getEncryptSafecode($admin));
|
||||
$this->success();
|
||||
}
|
||||
$this->error();
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class Rule extends Backend
|
|||
$v['remark'] = __($v['remark']);
|
||||
}
|
||||
unset($v);
|
||||
Tree::instance()->init($ruleList);
|
||||
Tree::instance()->init($ruleList)->icon = [' ', ' ', ' '];
|
||||
$this->rulelist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'title');
|
||||
$ruledata = [0 => __('None')];
|
||||
foreach ($this->rulelist as $k => &$v) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class User extends Backend
|
|||
public function _initialize()
|
||||
{
|
||||
parent::_initialize();
|
||||
$this->model = model('User');
|
||||
$this->model = new \app\admin\model\User;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ return [
|
|||
'User id' => '会员ID',
|
||||
'Username' => '用户名',
|
||||
'Nickname' => '昵称',
|
||||
'Mobile' => '手机',
|
||||
'Email' => '邮箱',
|
||||
'Password' => '密码',
|
||||
'Sign up' => '注 册',
|
||||
'Sign in' => '登 录',
|
||||
|
|
@ -114,8 +116,17 @@ return [
|
|||
'%d week%s ago' => '%d周前',
|
||||
'%d month%s ago' => '%d月前',
|
||||
'%d year%s ago' => '%d年前',
|
||||
'%d second%s after' => '%d秒后',
|
||||
'%d minute%s after' => '%d分钟后',
|
||||
'%d hour%s after' => '%d小时后',
|
||||
'%d day%s after' => '%d天后',
|
||||
'%d week%s after' => '%d周后',
|
||||
'%d month%s after' => '%d月后',
|
||||
'%d year%s after' => '%d年后',
|
||||
'Set to normal' => '设为正常',
|
||||
'Set to hidden' => '设为隐藏',
|
||||
'Set status to normal' => '设为正常',
|
||||
'Set status to hidden' => '设为隐藏',
|
||||
'Recycle bin' => '回收站',
|
||||
'Restore' => '还原',
|
||||
'Restore all' => '还原全部',
|
||||
|
|
@ -194,13 +205,13 @@ return [
|
|||
'Third group 2' => '三级管理组2',
|
||||
'Dashboard tips' => '用于展示当前系统中的统计数据、统计报表及重要实时数据',
|
||||
'Config tips' => '可以在此增改系统的变量和分组,也可以自定义分组和变量',
|
||||
'Category tips' => '用于管理网站的所有分类,分类可进行无限级分类,分类类型请在常规管理->系统配置->字典配置中添加',
|
||||
'Category tips' => '分类类型请在常规管理->系统配置->字典配置中添加',
|
||||
'Attachment tips' => '主要用于管理上传到服务器或第三方存储的数据',
|
||||
'Addon tips' => '可在线安装、卸载、禁用、启用、配置、升级插件,插件升级前请做好备份。',
|
||||
'Admin tips' => '一个管理员可以有多个角色组,左侧的菜单根据管理员所拥有的权限进行生成',
|
||||
'Admin log tips' => '管理员可以查看自己所拥有的权限的管理员日志',
|
||||
'Group tips' => '角色组可以有多个,角色有上下级层级关系,如果子角色有角色组和管理员的权限则可以派生属于自己组别的下级角色组或管理员',
|
||||
'Rule tips' => '规则通常对应一个控制器的方法,同时左侧的菜单栏数据也从规则中体现,通常建议通过命令行进行生成规则节点',
|
||||
'Rule tips' => '菜单规则通常对应一个控制器的方法,同时菜单栏数据也从规则中获取',
|
||||
'Access is allowed only to the super management group' => '仅超级管理组能访问',
|
||||
'Local addon' => '本地插件',
|
||||
// 前台菜单
|
||||
|
|
|
|||
|
|
@ -10,28 +10,30 @@ return [
|
|||
'Donate' => '打赏作者',
|
||||
'Warmtips' => '温馨提示',
|
||||
'Pay now' => '立即支付',
|
||||
'Offline install' => '离线安装',
|
||||
'Local install' => '本地安装',
|
||||
'Refresh addon cache' => '刷新插件缓存',
|
||||
'Userinfo' => '会员信息',
|
||||
'Online store' => '在线商店',
|
||||
'Reload authorization' => '刷新授权',
|
||||
'Local addon' => '本地插件',
|
||||
'Conflict tips' => '此插件中发现和现有系统中部分文件发现冲突!以下文件将会被影响,请备份好相关文件后再继续操作',
|
||||
'Login tips' => '此处登录账号为<a href="https://www.fastadmin.net" target="_blank">FastAdmin官网账号</a>',
|
||||
'Logined tips' => '你好!%s<br />当前你已经登录,将同步保存你的购买记录',
|
||||
'Pay tips' => '扫码支付后如果仍然无法立即下载,请不要重复支付,请稍后再重试安装!',
|
||||
'Pay tips' => '扫码支付后如果仍然无法安装,请不要重复支付,请稍后再重试安装!',
|
||||
'Pay successful tips' => '购买成功!请点击继续安装按钮完成安装!',
|
||||
'Pay click tips' => '请点击这里在新窗口中进行支付!',
|
||||
'Pay new window tips' => '请在新弹出的窗口中进行支付,支付完成后再重新点击安装按钮进行安装!',
|
||||
'Upgrade tips' => '确认升级<b>《%s》</b>?<p class="text-danger">1、请务必做好代码和数据库备份!备份!备份!<br>2、升级后如出现冗余数据,请根据需要移除即可!<br>3、不建议在生产环境升级,请在本地完成升级测试</p>如有重要数据请备份后再操作!',
|
||||
'Offline installed tips' => '安装成功!清除浏览器缓存和框架缓存后生效!',
|
||||
'Online installed tips' => '安装成功!清除浏览器缓存和框架缓存后生效!',
|
||||
'Not login tips' => '你当前未登录FastAdmin,登录后将同步已购买的记录,下载时无需二次付费!',
|
||||
'Please login and try to install' => '请登录FastAdmin后再进行离线安装!',
|
||||
'Please login and try to install' => '请登录FastAdmin后再进行本地安装!',
|
||||
'Not installed tips' => '请安装后再访问插件前台页面!',
|
||||
'Not enabled tips' => '插件已经禁用,请启用后再访问插件前台页面!',
|
||||
'New version tips' => '发现新版本:%s 点击查看更新日志',
|
||||
'Store now available tips' => '插件市场暂不可用,是否切换到本地插件?',
|
||||
'Testdata tips' => '你还可以继续导入测试数据!',
|
||||
'Import testdata' => '导入测试数据',
|
||||
'Skip testdata' => '暂不导入',
|
||||
'Store not available tips' => '插件市场暂不可用,是否切换到本地插件?',
|
||||
'Switch to the local' => '切换到本地插件',
|
||||
'try to reload' => '重新尝试加载',
|
||||
'Please disable addon first' => '请先禁用插件再进行操作',
|
||||
'Please disable the add before trying to upgrade' => '请先禁用插件再进行升级',
|
||||
'Please disable the add before trying to uninstall' => '请先禁用插件再进行卸载',
|
||||
'Login now' => '立即登录',
|
||||
|
|
@ -41,6 +43,7 @@ return [
|
|||
'View addon screenshots' => '点击查看插件截图',
|
||||
'Click to toggle status' => '点击切换插件状态',
|
||||
'Click to contact developer' => '点击与插件开发者取得联系',
|
||||
'Continue installation' => '继续安装',
|
||||
'My addons' => '我购买的插件',
|
||||
'Index' => '前台',
|
||||
'All' => '全部',
|
||||
|
|
@ -74,7 +77,6 @@ return [
|
|||
'Enable' => '启用',
|
||||
'Your username or email' => '你的手机号、用户名或邮箱',
|
||||
'Your password' => '你的密码',
|
||||
'Login FastAdmin' => '登录',
|
||||
'Login' => '登录',
|
||||
'Logout' => '退出登录',
|
||||
'Register' => '注册账号',
|
||||
|
|
@ -84,13 +86,18 @@ return [
|
|||
'Install successful' => '安装成功',
|
||||
'Uninstall successful' => '卸载成功',
|
||||
'Operate successful' => '操作成功',
|
||||
'Import successful' => '导入测试数据成功!清除浏览器缓存和框架缓存后生效!',
|
||||
'Initialize successful' => '初始化成功',
|
||||
'Initialize template not found' => '初始化模板未找到',
|
||||
'Addon name incorrect' => '插件名称不正确',
|
||||
'Addon info file was not found' => '插件配置文件未找到',
|
||||
'Addon info file data incorrect' => '插件配置信息不正确',
|
||||
'Addon already exists' => '插件已经存在',
|
||||
'Addon not exists' => '插件不存在',
|
||||
'Addon package download failed' => '插件下载失败',
|
||||
'Conflicting file found' => '发现冲突文件',
|
||||
'Invalid addon package' => '未验证的插件',
|
||||
'No initialize method' => '未找到初始化方法',
|
||||
'No permission to write temporary files' => '没有权限写入临时文件',
|
||||
'The addon file does not exist' => '插件主启动程序不存在',
|
||||
'The configuration file content is incorrect' => '配置文件不完整',
|
||||
|
|
@ -98,6 +105,7 @@ return [
|
|||
'Unable to extract the file' => '无法解压ZIP文件',
|
||||
'Unable to open file \'%s\' for writing' => '文件(%s)没有写入权限',
|
||||
'Are you sure you want to unstall %s?' => '确认卸载<b>《%s》</b>?',
|
||||
'Are you sure you want to refresh authorization?' => '确认刷新应用插件授权?',
|
||||
'Delete all the addon file and cannot be recovered!' => '卸载将会删除所有插件文件且不可找回!!!',
|
||||
'Delete all the addon database and cannot be recovered!' => '删除所有插件相关数据表且不可找回!!!',
|
||||
'Please backup important data manually before uninstall!' => '如有重要数据请备份后再操作!!!',
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Email' => '电子邮箱',
|
||||
'Mobile' => '手机号',
|
||||
'Group' => '所属组别',
|
||||
'Loginfailure' => '登录失败次数',
|
||||
'Login time' => '最后登录',
|
||||
'The parent group exceeds permission limit' => '父组别超出权限范围',
|
||||
'Please input correct username' => '用户名只能由3-12位数字、字母、下划线组合',
|
||||
'Please input correct password' => '密码长度必须在6-16位之间,不能包含空格',
|
||||
'Please input correct username' => '用户名只能由3-30位数字、字母、下划线组合',
|
||||
'Username must be 3 to 30 characters' => '用户名只能由3-30位数字、字母、下划线组合',
|
||||
'Please input correct password' => '密码长度必须在6-30位之间,不能包含空格',
|
||||
'Password must be 6 to 30 characters' => '密码长度必须在6-30位之间,不能包含空格',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,47 +1,50 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Custom' => '自定义',
|
||||
'Pid' => '父ID',
|
||||
'Type' => '栏目类型',
|
||||
'Image' => '图片',
|
||||
'Total user' => '总会员数',
|
||||
'Total addon' => '总插件数',
|
||||
'Total category' => '总分类数',
|
||||
'Total admin' => '总管理员数',
|
||||
'Today user signup' => '今日注册',
|
||||
'Today user login' => '今日登录',
|
||||
'Today order' => '今日订单',
|
||||
'Unsettle order' => '未处理订单',
|
||||
'Three dnu' => '三日新增',
|
||||
'Seven dnu' => '七日新增',
|
||||
'Seven dau' => '七日活跃',
|
||||
'Thirty dau' => '月活跃',
|
||||
'Custom zone' => '这里是你的自定义数据',
|
||||
'Register user' => '注册用户数',
|
||||
'Real time' => '实时',
|
||||
'Category count' => '分类统计',
|
||||
'Category count tips' => '当前分类总记录数',
|
||||
'Database count' => '数据库统计',
|
||||
'Database table nums' => '数据表数量',
|
||||
'Database size' => '占用空间',
|
||||
'Attachment count' => '附件统计',
|
||||
'Attachment nums' => '附件数量',
|
||||
'Attachment size' => '附件大小',
|
||||
'Attachment count tips' => '当前上传的附件数量',
|
||||
'Picture count' => '图片统计',
|
||||
'Picture nums' => '图片数量',
|
||||
'Picture size' => '图片大小',
|
||||
'Server info' => '服务器信息',
|
||||
'PHP version' => 'PHP版本',
|
||||
'Sapi name' => '运行方式',
|
||||
'Debug mode' => '调试模式',
|
||||
'Software' => '环境信息',
|
||||
'Upload mode' => '上传模式',
|
||||
'Upload url' => '上传URL',
|
||||
'Upload cdn url' => '上传CDN',
|
||||
'Cdn url' => '静态资源CDN',
|
||||
'Timezone' => '时区',
|
||||
'Language' => '语言',
|
||||
'View more' => '查看更多',
|
||||
'Custom' => '自定义',
|
||||
'Pid' => '父ID',
|
||||
'Type' => '栏目类型',
|
||||
'Image' => '图片',
|
||||
'Total user' => '总会员数',
|
||||
'Total addon' => '总插件数',
|
||||
'Total category' => '总分类数',
|
||||
'Total attachment' => '总附件数',
|
||||
'Total admin' => '总管理员数',
|
||||
'Today user signup' => '今日注册',
|
||||
'Today user login' => '今日登录',
|
||||
'Today order' => '今日订单',
|
||||
'Unsettle order' => '未处理订单',
|
||||
'Three dnu' => '三日新增',
|
||||
'Seven dnu' => '七日新增',
|
||||
'Seven dau' => '七日活跃',
|
||||
'Thirty dau' => '月活跃',
|
||||
'Custom zone' => '这里是你的自定义数据',
|
||||
'Register user' => '注册用户数',
|
||||
'Real time' => '实时',
|
||||
'Category count' => '分类统计',
|
||||
'Working addon count' => '运行中的插件',
|
||||
'Category count tips' => '当前分类总记录数',
|
||||
'Working addon count tips' => '当前运行中的插件数',
|
||||
'Database count' => '数据库统计',
|
||||
'Database table nums' => '数据表数量',
|
||||
'Database size' => '占用空间',
|
||||
'Attachment count' => '附件统计',
|
||||
'Attachment nums' => '附件数量',
|
||||
'Attachment size' => '附件大小',
|
||||
'Attachment count tips' => '当前上传的附件数量',
|
||||
'Picture count' => '图片统计',
|
||||
'Picture nums' => '图片数量',
|
||||
'Picture size' => '图片大小',
|
||||
'Server info' => '服务器信息',
|
||||
'PHP version' => 'PHP版本',
|
||||
'Sapi name' => '运行方式',
|
||||
'Debug mode' => '调试模式',
|
||||
'Software' => '环境信息',
|
||||
'Upload mode' => '上传模式',
|
||||
'Upload url' => '上传URL',
|
||||
'Upload cdn url' => '上传CDN',
|
||||
'Cdn url' => '静态资源CDN',
|
||||
'Timezone' => '时区',
|
||||
'Language' => '语言',
|
||||
'View more' => '查看更多',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,80 +1,83 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Name' => '变量名',
|
||||
'Tip' => '提示信息',
|
||||
'Group' => '分组',
|
||||
'Type' => '类型',
|
||||
'Title' => '变量标题',
|
||||
'Value' => '变量值',
|
||||
'Basic' => '基础配置',
|
||||
'Email' => '邮件配置',
|
||||
'Attachment' => '附件配置',
|
||||
'Dictionary' => '字典配置',
|
||||
'User' => '会员配置',
|
||||
'Example' => '示例分组',
|
||||
'Extend' => '扩展属性',
|
||||
'String' => '字符',
|
||||
'Text' => '文本',
|
||||
'Editor' => '编辑器',
|
||||
'Number' => '数字',
|
||||
'Date' => '日期',
|
||||
'Time' => '时间',
|
||||
'Datetime' => '日期时间',
|
||||
'Datetimerange' => '日期时间区间',
|
||||
'Image' => '图片',
|
||||
'Images' => '图片(多)',
|
||||
'File' => '文件',
|
||||
'Files' => '文件(多)',
|
||||
'Select' => '列表',
|
||||
'Selects' => '列表(多选)',
|
||||
'Switch' => '开关',
|
||||
'Checkbox' => '复选',
|
||||
'Radio' => '单选',
|
||||
'Array' => '数组',
|
||||
'Array key' => '键名',
|
||||
'Array value' => '键值',
|
||||
'City' => '城市地区',
|
||||
'Selectpage' => '关联表',
|
||||
'Selectpages' => '关联表(多选)',
|
||||
'Custom' => '自定义',
|
||||
'Please select table' => '关联表',
|
||||
'Selectpage table' => '关联表',
|
||||
'Selectpage primarykey' => '存储字段',
|
||||
'Selectpage field' => '显示字段',
|
||||
'Selectpage conditions' => '筛选条件',
|
||||
'Field title' => '字段名',
|
||||
'Field value' => '字段值',
|
||||
'Content' => '数据列表',
|
||||
'Rule' => '校验规则',
|
||||
'Site name' => '站点名称',
|
||||
'Beian' => '备案号',
|
||||
'Cdn url' => 'CDN地址',
|
||||
'Version' => '版本号',
|
||||
'Timezone' => '时区',
|
||||
'Forbidden ip' => '禁止IP',
|
||||
'Languages' => '语言',
|
||||
'Fixed page' => '后台固定页',
|
||||
'Category type' => '分类类型',
|
||||
'Config group' => '配置分组',
|
||||
'Attachment category' => '附件类别',
|
||||
'Category1' => '分类一',
|
||||
'Category2' => '分类二',
|
||||
'Rule tips' => '校验规则使用请参考Nice-validator文档',
|
||||
'Extend tips' => '扩展属性支持{id}、{name}、{group}、{title}、{value}、{content}、{rule}替换',
|
||||
'Mail type' => '邮件发送方式',
|
||||
'Mail smtp host' => 'SMTP服务器',
|
||||
'Mail smtp port' => 'SMTP端口',
|
||||
'Mail smtp user' => 'SMTP用户名',
|
||||
'Mail smtp password' => 'SMTP密码',
|
||||
'Mail vertify type' => 'SMTP验证方式',
|
||||
'Mail from' => '发件人邮箱',
|
||||
'Site name incorrect' => '网站名称错误',
|
||||
'Name already exist' => '变量名称已经存在',
|
||||
'Add new config' => '点击添加新的配置',
|
||||
'Send a test message' => '发送测试邮件',
|
||||
'This is a test mail content' => '这是一封来自%s的校验邮件,用于校验邮件配置是否正常!',
|
||||
'This is a test mail' => '这是一封来自%s的邮件',
|
||||
'Please input your email' => '请输入测试接收者邮箱',
|
||||
'Please input correct email' => '请输入正确的邮箱地址',
|
||||
'Name' => '变量名',
|
||||
'Tip' => '提示信息',
|
||||
'Group' => '分组',
|
||||
'Type' => '类型',
|
||||
'Title' => '变量标题',
|
||||
'Value' => '变量值',
|
||||
'Basic' => '基础配置',
|
||||
'Email' => '邮件配置',
|
||||
'Attachment' => '附件配置',
|
||||
'Dictionary' => '字典配置',
|
||||
'User' => '会员配置',
|
||||
'Example' => '示例分组',
|
||||
'Extend' => '扩展属性',
|
||||
'String' => '字符',
|
||||
'Password' => '密码',
|
||||
'Text' => '文本',
|
||||
'Editor' => '编辑器',
|
||||
'Number' => '数字',
|
||||
'Date' => '日期',
|
||||
'Time' => '时间',
|
||||
'Datetime' => '日期时间',
|
||||
'Datetimerange' => '日期时间区间',
|
||||
'Image' => '图片',
|
||||
'Images' => '图片(多)',
|
||||
'File' => '文件',
|
||||
'Files' => '文件(多)',
|
||||
'Select' => '列表',
|
||||
'Selects' => '列表(多选)',
|
||||
'Switch' => '开关',
|
||||
'Checkbox' => '复选',
|
||||
'Radio' => '单选',
|
||||
'Array' => '数组',
|
||||
'Array key' => '键名',
|
||||
'Array value' => '键值',
|
||||
'City' => '城市地区',
|
||||
'Selectpage' => '关联表',
|
||||
'Selectpages' => '关联表(多选)',
|
||||
'Custom' => '自定义',
|
||||
'Please select table' => '关联表',
|
||||
'Selectpage table' => '关联表',
|
||||
'Selectpage primarykey' => '存储字段',
|
||||
'Selectpage field' => '显示字段',
|
||||
'Selectpage conditions' => '筛选条件',
|
||||
'Field title' => '字段名',
|
||||
'Field value' => '字段值',
|
||||
'Content' => '数据列表',
|
||||
'Rule' => '校验规则',
|
||||
'Visible condition' => '可见条件',
|
||||
'Site name' => '站点名称',
|
||||
'Beian' => '备案号',
|
||||
'Cdn url' => 'CDN地址',
|
||||
'Version' => '版本号',
|
||||
'Timezone' => '时区',
|
||||
'Forbidden ip' => '禁止IP',
|
||||
'Languages' => '语言',
|
||||
'Fixed page' => '后台固定页',
|
||||
'Category type' => '分类类型',
|
||||
'Config group' => '配置分组',
|
||||
'Attachment category' => '附件类别',
|
||||
'Category1' => '分类一',
|
||||
'Category2' => '分类二',
|
||||
'Rule tips' => '校验规则使用请参考Nice-validator文档',
|
||||
'Extend tips' => '扩展属性支持{id}、{name}、{group}、{title}、{value}、{content}、{rule}替换',
|
||||
'Mail type' => '邮件发送方式',
|
||||
'Mail smtp host' => 'SMTP服务器',
|
||||
'Mail smtp port' => 'SMTP端口',
|
||||
'Mail smtp user' => 'SMTP用户名',
|
||||
'Mail smtp password' => 'SMTP密码',
|
||||
'Mail vertify type' => 'SMTP验证方式',
|
||||
'Mail from' => '发件人邮箱',
|
||||
'Site name incorrect' => '网站名称错误',
|
||||
'Name already exist' => '变量名称已经存在',
|
||||
'Add new config' => '点击添加新的配置',
|
||||
'Send a test message' => '发送测试邮件',
|
||||
'Only work at development environment' => '只允许在开发环境开操作',
|
||||
'This is a test mail content' => '这是一封来自%s的校验邮件,用于校验邮件配置是否正常!',
|
||||
'This is a test mail' => '这是一封来自%s的邮件',
|
||||
'Please input your email' => '请输入测试接收者邮箱',
|
||||
'Please input correct email' => '请输入正确的邮箱地址',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
return [
|
||||
'Url' => '链接',
|
||||
'Userame' => '用户名',
|
||||
'Username' => '用户名',
|
||||
'Createtime' => '操作时间',
|
||||
'Click to edit' => '点击编辑',
|
||||
'Admin log' => '操作日志',
|
||||
'Leave password blank if dont want to change' => '不修改密码请留空',
|
||||
'Please input correct email' => '请输入正确的Email地址',
|
||||
'Please input correct password' => '密码长度不正确',
|
||||
'Please input correct password' => '密码长度必须在6-30位之间,不能包含空格',
|
||||
'Password must be 6 to 30 characters' => '密码长度必须在6-30位之间,不能包含空格',
|
||||
'Email already exists' => '邮箱已经存在',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -8,19 +8,25 @@ return [
|
|||
'You can\'t use fixed and boxed layouts together' => '盒子模型和固定布局不能同时启作用',
|
||||
'Boxed Layout' => '盒子布局',
|
||||
'Activate the boxed layout' => '盒子布局最大宽度将被限定为1250px',
|
||||
'Toggle Sidebar' => '切换菜单栏',
|
||||
'Toggle the left sidebar\'s state (open or collapse)' => '切换菜单栏的展示或收起',
|
||||
'Toggle Sidebar' => '收起菜单栏',
|
||||
'Toggle the left sidebar\'s state (open or collapse)' => '切换菜单栏的展开或收起',
|
||||
'Sidebar Expand on Hover' => '菜单栏自动展开',
|
||||
'Let the sidebar mini expand on hover' => '鼠标移到菜单栏自动展开',
|
||||
'Toggle Right Sidebar Slide' => '切换右侧操作栏',
|
||||
'Toggle between slide over content and push content effects' => '切换右侧操作栏覆盖或独占',
|
||||
'Toggle Right Sidebar Skin' => '切换右侧操作栏背景',
|
||||
'Toggle between dark and light skins for the right sidebar' => '将右侧操作栏背景亮色或深色切换',
|
||||
'Multiple nav' => '多级菜单导航',
|
||||
'Toggle the top menu state (multiple or single)' => '切换顶部菜单为多级菜单导航模式',
|
||||
'Multiple tab' => '多选项卡',
|
||||
'Always show multiple tab when multiple nav is set' => '当配置为多级菜单导航时是否启用多选项卡',
|
||||
'Show sub menu' => '显示菜单栏子菜单',
|
||||
'Always show sub menu' => '菜单栏子菜单将始终显示',
|
||||
'Disable top menu badge' => '禁用顶部彩色小角标',
|
||||
'Disable top menu badge without left menu' => '左边菜单栏的彩色小角标不受影响',
|
||||
'Skins' => '皮肤',
|
||||
'Username must be 3 to 30 characters' => '用户名只能由3-30位数字、字母、下划线组合',
|
||||
'Password must be 6 to 30 characters' => '密码长度必须在6-30位之间,不能包含空格',
|
||||
'You\'ve logged in, do not login again' => '你已经登录,无需重复登录',
|
||||
'Username or password can not be empty' => '用户名密码不能为空',
|
||||
'Username or password is incorrect' => '用户名或密码不正确',
|
||||
|
|
@ -56,5 +62,6 @@ return [
|
|||
'Forum' => '交流社区',
|
||||
'QQ qun' => 'QQ交流群',
|
||||
'Captcha' => '验证码',
|
||||
'The duration of the session is %s hours' => '设定会话有效时长为%s小时',
|
||||
'Security tips' => '<i class="fa fa-warning"></i> 安全提示:为了你的后台安全,请勿将后台管理入口设置为admin或admin.php',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Name' => '组名',
|
||||
'Rules' => '权限节点',
|
||||
'Createtime' => '添加时间',
|
||||
'Updatetime' => '更新时间',
|
||||
'Status' => '状态'
|
||||
'Name' => '组名',
|
||||
'Rules' => '权限节点',
|
||||
'Change password' => '修改密码',
|
||||
'Createtime' => '添加时间',
|
||||
'Updatetime' => '更新时间',
|
||||
'Status' => '状态'
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,15 +1,19 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'Pid' => '父ID',
|
||||
'Name' => '规则',
|
||||
'Title' => '标题',
|
||||
'Remark' => '备注',
|
||||
'Ismenu' => '是否菜单',
|
||||
'Createtime' => '创建时间',
|
||||
'Updatetime' => '更新时间',
|
||||
'Menu tips' => '规则任意,请不可重复,仅做层级显示,无需匹配控制器和方法',
|
||||
'Node tips' => '模块/控制器/方法名',
|
||||
'Weigh' => '权重',
|
||||
'Status' => '状态'
|
||||
'Pid' => '父ID',
|
||||
'Name' => '规则',
|
||||
'Title' => '标题',
|
||||
'Remark' => '备注',
|
||||
'Ismenu' => '是否菜单',
|
||||
'Change password' => '修改密码',
|
||||
'Createtime' => '创建时间',
|
||||
'Updatetime' => '更新时间',
|
||||
'Menu tips' => '规则任意,请不可重复,仅做层级显示,无需匹配控制器和方法',
|
||||
'Node tips' => '模块/控制器/方法名',
|
||||
'Weigh' => '权重',
|
||||
'Status' => '状态',
|
||||
'Toggle all' => '显示全部',
|
||||
'Toggle menu visible' => '点击切换菜单显示',
|
||||
'Toggle sub menu' => '点击切换子菜单',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class Auth extends \fast\Auth
|
|||
$this->setError('Please try again after 1 day');
|
||||
return false;
|
||||
}
|
||||
if ($admin->password != md5(md5($password) . $admin->salt)) {
|
||||
if ($admin->password != $this->getEncryptPassword($password, $admin->salt)) {
|
||||
$admin->loginfailure++;
|
||||
$admin->save();
|
||||
$this->setError('Password is incorrect');
|
||||
|
|
@ -63,7 +63,8 @@ class Auth extends \fast\Auth
|
|||
$admin->token = Random::uuid();
|
||||
$admin->save();
|
||||
Session::set("admin", $admin->toArray());
|
||||
$this->keeplogin($keeptime);
|
||||
Session::set("admin.safecode", $this->getEncryptSafecode($admin));
|
||||
$this->keeplogin($admin, $keeptime);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -80,6 +81,7 @@ class Auth extends \fast\Auth
|
|||
$this->logined = false; //重置登录状态
|
||||
Session::delete("admin");
|
||||
Cookie::delete("keeplogin");
|
||||
setcookie('fastadmin_userinfo', '', $_SERVER['REQUEST_TIME'] - 3600, rtrim(url("/" . request()->module(), '', false), '/'));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +102,7 @@ class Auth extends \fast\Auth
|
|||
return false;
|
||||
}
|
||||
//token有变更
|
||||
if ($key != md5(md5($id) . md5($keeptime) . md5($expiretime) . $admin->token . config('token.key'))) {
|
||||
if ($key != $this->getKeeploginKey($admin, $keeptime, $expiretime)) {
|
||||
return false;
|
||||
}
|
||||
$ip = request()->ip();
|
||||
|
|
@ -109,8 +111,9 @@ class Auth extends \fast\Auth
|
|||
return false;
|
||||
}
|
||||
Session::set("admin", $admin->toArray());
|
||||
Session::set("admin.safecode", $this->getEncryptSafecode($admin));
|
||||
//刷新自动登录的时效
|
||||
$this->keeplogin($keeptime);
|
||||
$this->keeplogin($admin, $keeptime);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
@ -123,18 +126,64 @@ class Auth extends \fast\Auth
|
|||
* @param int $keeptime
|
||||
* @return boolean
|
||||
*/
|
||||
protected function keeplogin($keeptime = 0)
|
||||
protected function keeplogin($admin, $keeptime = 0)
|
||||
{
|
||||
if ($keeptime) {
|
||||
$expiretime = time() + $keeptime;
|
||||
$key = md5(md5($this->id) . md5($keeptime) . md5($expiretime) . $this->token . config('token.key'));
|
||||
$data = [$this->id, $keeptime, $expiretime, $key];
|
||||
Cookie::set('keeplogin', implode('|', $data), 86400 * 7);
|
||||
$key = $this->getKeeploginKey($admin, $keeptime, $expiretime);
|
||||
Cookie::set('keeplogin', implode('|', [$admin['id'], $keeptime, $expiretime, $key]), $keeptime);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取密码加密后的字符串
|
||||
* @param string $password 密码
|
||||
* @param string $salt 密码盐
|
||||
* @return string
|
||||
*/
|
||||
public function getEncryptPassword($password, $salt = '')
|
||||
{
|
||||
return md5(md5($password) . $salt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取密码加密后的自动登录码
|
||||
* @param string $password 密码
|
||||
* @param string $salt 密码盐
|
||||
* @return string
|
||||
*/
|
||||
public function getEncryptKeeplogin($params, $keeptime)
|
||||
{
|
||||
$expiretime = time() + $keeptime;
|
||||
$key = md5(md5($params['id']) . md5($keeptime) . md5($expiretime) . $params['token'] . config('token.key'));
|
||||
return implode('|', [$this->id, $keeptime, $expiretime, $key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自动登录Key
|
||||
* @param $params
|
||||
* @param $keeptime
|
||||
* @param $expiretime
|
||||
* @return string
|
||||
*/
|
||||
public function getKeeploginKey($params, $keeptime, $expiretime)
|
||||
{
|
||||
$key = md5(md5($params['id']) . md5($keeptime) . md5($expiretime) . $params['token'] . config('token.key'));
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取加密后的安全码
|
||||
* @param $params
|
||||
* @return string
|
||||
*/
|
||||
public function getEncryptSafecode($params)
|
||||
{
|
||||
return md5(md5($params['username']) . md5(substr($params['password'], 0, 6)) . config('token.key'));
|
||||
}
|
||||
|
||||
public function check($name, $uid = '', $relation = 'or', $mode = 'url')
|
||||
{
|
||||
$uid = $uid ? $uid : $this->id;
|
||||
|
|
@ -179,13 +228,19 @@ class Auth extends \fast\Auth
|
|||
if (!$admin) {
|
||||
return false;
|
||||
}
|
||||
$my = Admin::get($admin['id']);
|
||||
if (!$my) {
|
||||
return false;
|
||||
}
|
||||
//校验安全码,可用于判断关键信息发生了变更需要重新登录
|
||||
if (!isset($admin['safecode']) || $this->getEncryptSafecode($my) !== $admin['safecode']) {
|
||||
$this->logout();
|
||||
return false;
|
||||
}
|
||||
//判断是否同一时间同一账号只能在一个地方登录
|
||||
if (Config::get('fastadmin.login_unique')) {
|
||||
$my = Admin::get($admin['id']);
|
||||
if (!$my || $my['token'] != $admin['token']) {
|
||||
$this->logined = false; //重置登录状态
|
||||
Session::delete("admin");
|
||||
Cookie::delete("keeplogin");
|
||||
if ($my['token'] != $admin['token']) {
|
||||
$this->logout();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -284,7 +339,7 @@ class Auth extends \fast\Auth
|
|||
}
|
||||
}
|
||||
// 取出所有分组
|
||||
$groupList = \app\admin\model\AuthGroup::where(['status' => 'normal'])->select();
|
||||
$groupList = \app\admin\model\AuthGroup::where($this->isSuperAdmin() ? '1=1' : ['status' => 'normal'])->select();
|
||||
$objList = [];
|
||||
foreach ($groups as $k => $v) {
|
||||
if ($v['rules'] === '*') {
|
||||
|
|
@ -316,8 +371,7 @@ class Auth extends \fast\Auth
|
|||
$childrenAdminIds = [];
|
||||
if (!$this->isSuperAdmin()) {
|
||||
$groupIds = $this->getChildrenGroupIds(false);
|
||||
$authGroupList = \app\admin\model\AuthGroupAccess::
|
||||
field('uid,group_id')
|
||||
$authGroupList = \app\admin\model\AuthGroupAccess::field('uid,group_id')
|
||||
->where('group_id', 'in', $groupIds)
|
||||
->select();
|
||||
foreach ($authGroupList as $k => $v) {
|
||||
|
|
@ -363,7 +417,6 @@ class Auth extends \fast\Auth
|
|||
$titleArr[$pathArr[$rule['name']]] = $rule['title'];
|
||||
$menuArr[$pathArr[$rule['name']]] = $rule;
|
||||
}
|
||||
|
||||
}
|
||||
ksort($menuArr);
|
||||
$this->breadcrumb = $menuArr;
|
||||
|
|
@ -389,9 +442,9 @@ class Auth extends \fast\Auth
|
|||
foreach ($params as $k => $v) {
|
||||
$url = $k;
|
||||
if (is_array($v)) {
|
||||
$nums = isset($v[0]) ? $v[0] : 0;
|
||||
$color = isset($v[1]) ? $v[1] : $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums];
|
||||
$class = isset($v[2]) ? $v[2] : 'label';
|
||||
$nums = $v[0] ?? 0;
|
||||
$color = $v[1] ?? $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums];
|
||||
$class = $v[2] ?? 'label';
|
||||
} else {
|
||||
$nums = $v;
|
||||
$color = $colorArr[(is_numeric($nums) ? $nums : strlen($nums)) % $colorNums];
|
||||
|
|
@ -419,7 +472,7 @@ class Auth extends \fast\Auth
|
|||
->column('name,pid');
|
||||
$pidArr = array_unique(array_filter(array_column($ruleList, 'pid')));
|
||||
foreach ($ruleList as $k => &$v) {
|
||||
if (!in_array($v['name'], $userRule)) {
|
||||
if (!in_array(strtolower($v['name']), $userRule)) {
|
||||
unset($ruleList[$k]);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -430,7 +483,7 @@ class Auth extends \fast\Auth
|
|||
}
|
||||
$v['icon'] = $v['icon'] . ' fa-fw';
|
||||
$v['url'] = isset($v['url']) && $v['url'] ? $v['url'] : '/' . $module . '/' . $v['name'];
|
||||
$v['badge'] = isset($badgeList[$v['name']]) ? $badgeList[$v['name']] : '';
|
||||
$v['badge'] = $badgeList[$v['name']] ?? '';
|
||||
$v['title'] = __($v['title']);
|
||||
$v['url'] = preg_match("/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/i", $v['url']) ? $v['url'] : url($v['url']);
|
||||
$v['menuclass'] = in_array($v['menutype'], ['dialog', 'ajax']) ? 'btn-' . $v['menutype'] : '';
|
||||
|
|
@ -449,8 +502,9 @@ class Auth extends \fast\Auth
|
|||
$referer = [];
|
||||
}
|
||||
|
||||
$select_id = $selected ? $selected['id'] : 0;
|
||||
$select_id = $referer ? $referer['id'] : ($selected ? $selected['id'] : 0);
|
||||
$menu = $nav = '';
|
||||
$showSubmenu = config('fastadmin.show_submenu');
|
||||
if (Config::get('fastadmin.multiplenav')) {
|
||||
$topList = [];
|
||||
foreach ($ruleList as $index => $item) {
|
||||
|
|
@ -471,11 +525,11 @@ class Auth extends \fast\Auth
|
|||
$select_id,
|
||||
'',
|
||||
'ul',
|
||||
'class="treeview-menu"'
|
||||
'class="treeview-menu' . ($showSubmenu ? ' menu-open' : '') . '"'
|
||||
);
|
||||
$current = in_array($item['id'], $selectParentIds);
|
||||
$url = $childList ? 'javascript:;' : $item['url'];
|
||||
$addtabs = $childList || !$url ? "" : (stripos($url, "?") !== false ? "&" : "?") . "ref=addtabs";
|
||||
$addtabs = $childList || !$url ? "" : (stripos($url, "?") !== false ? "&" : "?") . "ref=" . ($item['menutype'] ? $item['menutype'] : 'addtabs');
|
||||
$childList = str_replace(
|
||||
'" pid="' . $item['id'] . '"',
|
||||
' ' . ($current ? '' : 'hidden') . '" pid="' . $item['id'] . '"',
|
||||
|
|
@ -493,7 +547,7 @@ class Auth extends \fast\Auth
|
|||
$select_id,
|
||||
'',
|
||||
'ul',
|
||||
'class="treeview-menu"'
|
||||
'class="treeview-menu' . ($showSubmenu ? ' menu-open' : '') . '"'
|
||||
);
|
||||
if ($selected) {
|
||||
$nav .= '<li role="presentation" id="tab_' . $selected['id'] . '" class="' . ($referer ? '' : 'active') . '"><a href="#con_' . $selected['id'] . '" node-id="' . $selected['id'] . '" aria-controls="' . $selected['id'] . '" role="tab" data-toggle="tab"><i class="' . $selected['icon'] . ' fa-fw"></i> <span>' . $selected['title'] . '</span> </a></li>';
|
||||
|
|
|
|||
|
|
@ -9,12 +9,16 @@ use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
|
|||
use PhpOffice\PhpSpreadsheet\Reader\Xls;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Csv;
|
||||
use think\Db;
|
||||
use think\db\exception\BindParamException;
|
||||
use think\db\exception\DataNotFoundException;
|
||||
use think\db\exception\ModelNotFoundException;
|
||||
use think\exception\DbException;
|
||||
use think\exception\PDOException;
|
||||
use think\exception\ValidateException;
|
||||
use think\response\Json;
|
||||
|
||||
trait Backend
|
||||
{
|
||||
|
||||
/**
|
||||
* 排除前台提交过来的字段
|
||||
* @param $params
|
||||
|
|
@ -24,115 +28,114 @@ trait Backend
|
|||
{
|
||||
if (is_array($this->excludeFields)) {
|
||||
foreach ($this->excludeFields as $field) {
|
||||
if (key_exists($field, $params)) {
|
||||
if (array_key_exists($field, $params)) {
|
||||
unset($params[$field]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (key_exists($this->excludeFields, $params)) {
|
||||
unset($params[$this->excludeFields]);
|
||||
}
|
||||
} else if (array_key_exists($this->excludeFields, $params)) {
|
||||
unset($params[$this->excludeFields]);
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查看
|
||||
*
|
||||
* @return string|Json
|
||||
* @throws \think\Exception
|
||||
* @throws DbException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//设置过滤方法
|
||||
$this->request->filter(['strip_tags', 'trim']);
|
||||
if ($this->request->isAjax()) {
|
||||
//如果发送的来源是Selectpage,则转发到Selectpage
|
||||
if ($this->request->request('keyField')) {
|
||||
return $this->selectpage();
|
||||
}
|
||||
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
|
||||
|
||||
$list = $this->model
|
||||
->where($where)
|
||||
->order($sort, $order)
|
||||
->paginate($limit);
|
||||
|
||||
$result = array("total" => $list->total(), "rows" => $list->items());
|
||||
|
||||
return json($result);
|
||||
if (false === $this->request->isAjax()) {
|
||||
return $this->view->fetch();
|
||||
}
|
||||
return $this->view->fetch();
|
||||
//如果发送的来源是 Selectpage,则转发到 Selectpage
|
||||
if ($this->request->request('keyField')) {
|
||||
return $this->selectpage();
|
||||
}
|
||||
[$where, $sort, $order, $offset, $limit] = $this->buildparams();
|
||||
$list = $this->model
|
||||
->where($where)
|
||||
->order($sort, $order)
|
||||
->paginate($limit);
|
||||
$result = ['total' => $list->total(), 'rows' => $list->items()];
|
||||
return json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回收站
|
||||
*
|
||||
* @return string|Json
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
public function recyclebin()
|
||||
{
|
||||
//设置过滤方法
|
||||
$this->request->filter(['strip_tags', 'trim']);
|
||||
if ($this->request->isAjax()) {
|
||||
list($where, $sort, $order, $offset, $limit) = $this->buildparams();
|
||||
|
||||
$list = $this->model
|
||||
->onlyTrashed()
|
||||
->where($where)
|
||||
->order($sort, $order)
|
||||
->paginate($limit);
|
||||
|
||||
$result = array("total" => $list->total(), "rows" => $list->items());
|
||||
|
||||
return json($result);
|
||||
if (false === $this->request->isAjax()) {
|
||||
return $this->view->fetch();
|
||||
}
|
||||
return $this->view->fetch();
|
||||
[$where, $sort, $order, $offset, $limit] = $this->buildparams();
|
||||
$list = $this->model
|
||||
->onlyTrashed()
|
||||
->where($where)
|
||||
->order($sort, $order)
|
||||
->paginate($limit);
|
||||
$result = ['total' => $list->total(), 'rows' => $list->items()];
|
||||
return json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @return string
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$params = $this->request->post("row/a");
|
||||
if ($params) {
|
||||
$params = $this->preExcludeFields($params);
|
||||
|
||||
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
|
||||
$params[$this->dataLimitField] = $this->auth->id;
|
||||
}
|
||||
$result = false;
|
||||
Db::startTrans();
|
||||
try {
|
||||
//是否采用模型验证
|
||||
if ($this->modelValidate) {
|
||||
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
|
||||
$this->model->validateFailException(true)->validate($validate);
|
||||
}
|
||||
$result = $this->model->allowField(true)->save($params);
|
||||
Db::commit();
|
||||
} catch (ValidateException $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
} catch (PDOException $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success();
|
||||
} else {
|
||||
$this->error(__('No rows were inserted'));
|
||||
}
|
||||
}
|
||||
if (false === $this->request->isPost()) {
|
||||
return $this->view->fetch();
|
||||
}
|
||||
$params = $this->request->post('row/a');
|
||||
if (empty($params)) {
|
||||
$this->error(__('Parameter %s can not be empty', ''));
|
||||
}
|
||||
return $this->view->fetch();
|
||||
$params = $this->preExcludeFields($params);
|
||||
|
||||
if ($this->dataLimit && $this->dataLimitFieldAutoFill) {
|
||||
$params[$this->dataLimitField] = $this->auth->id;
|
||||
}
|
||||
$result = false;
|
||||
Db::startTrans();
|
||||
try {
|
||||
//是否采用模型验证
|
||||
if ($this->modelValidate) {
|
||||
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.add' : $name) : $this->modelValidate;
|
||||
$this->model->validateFailException()->validate($validate);
|
||||
}
|
||||
$result = $this->model->allowField(true)->save($params);
|
||||
Db::commit();
|
||||
} catch (ValidateException|PDOException|Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result === false) {
|
||||
$this->error(__('No rows were inserted'));
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @param $ids
|
||||
* @return string
|
||||
* @throws DbException
|
||||
* @throws \think\Exception
|
||||
*/
|
||||
public function edit($ids = null)
|
||||
{
|
||||
|
|
@ -141,137 +144,93 @@ trait Backend
|
|||
$this->error(__('No Results were found'));
|
||||
}
|
||||
$adminIds = $this->getDataLimitAdminIds();
|
||||
if (is_array($adminIds)) {
|
||||
if (!in_array($row[$this->dataLimitField], $adminIds)) {
|
||||
$this->error(__('You have no permission'));
|
||||
}
|
||||
if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
|
||||
$this->error(__('You have no permission'));
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$params = $this->request->post("row/a");
|
||||
if ($params) {
|
||||
$params = $this->preExcludeFields($params);
|
||||
$result = false;
|
||||
Db::startTrans();
|
||||
try {
|
||||
//是否采用模型验证
|
||||
if ($this->modelValidate) {
|
||||
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
|
||||
$row->validateFailException(true)->validate($validate);
|
||||
}
|
||||
$result = $row->allowField(true)->save($params);
|
||||
Db::commit();
|
||||
} catch (ValidateException $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
} catch (PDOException $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($result !== false) {
|
||||
$this->success();
|
||||
} else {
|
||||
$this->error(__('No rows were updated'));
|
||||
}
|
||||
}
|
||||
if (false === $this->request->isPost()) {
|
||||
$this->view->assign('row', $row);
|
||||
return $this->view->fetch();
|
||||
}
|
||||
$params = $this->request->post('row/a');
|
||||
if (empty($params)) {
|
||||
$this->error(__('Parameter %s can not be empty', ''));
|
||||
}
|
||||
$this->view->assign("row", $row);
|
||||
return $this->view->fetch();
|
||||
$params = $this->preExcludeFields($params);
|
||||
$result = false;
|
||||
Db::startTrans();
|
||||
try {
|
||||
//是否采用模型验证
|
||||
if ($this->modelValidate) {
|
||||
$name = str_replace("\\model\\", "\\validate\\", get_class($this->model));
|
||||
$validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : $name) : $this->modelValidate;
|
||||
$row->validateFailException()->validate($validate);
|
||||
}
|
||||
$result = $row->allowField(true)->save($params);
|
||||
Db::commit();
|
||||
} catch (ValidateException|PDOException|Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if (false === $result) {
|
||||
$this->error(__('No rows were updated'));
|
||||
}
|
||||
$this->success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param $ids
|
||||
* @return void
|
||||
* @throws DbException
|
||||
* @throws DataNotFoundException
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function del($ids = "")
|
||||
public function del($ids = null)
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
if (false === $this->request->isPost()) {
|
||||
$this->error(__("Invalid parameters"));
|
||||
}
|
||||
$ids = $ids ? $ids : $this->request->post("ids");
|
||||
if ($ids) {
|
||||
$pk = $this->model->getPk();
|
||||
$adminIds = $this->getDataLimitAdminIds();
|
||||
if (is_array($adminIds)) {
|
||||
$this->model->where($this->dataLimitField, 'in', $adminIds);
|
||||
}
|
||||
$list = $this->model->where($pk, 'in', $ids)->select();
|
||||
|
||||
$count = 0;
|
||||
Db::startTrans();
|
||||
try {
|
||||
foreach ($list as $k => $v) {
|
||||
$count += $v->delete();
|
||||
}
|
||||
Db::commit();
|
||||
} catch (PDOException $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($count) {
|
||||
$this->success();
|
||||
} else {
|
||||
$this->error(__('No rows were deleted'));
|
||||
}
|
||||
$ids = $ids ?: $this->request->post("ids");
|
||||
if (empty($ids)) {
|
||||
$this->error(__('Parameter %s can not be empty', 'ids'));
|
||||
}
|
||||
$this->error(__('Parameter %s can not be empty', 'ids'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 真实删除
|
||||
*/
|
||||
public function destroy($ids = "")
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
$this->error(__("Invalid parameters"));
|
||||
}
|
||||
$ids = $ids ? $ids : $this->request->post("ids");
|
||||
$pk = $this->model->getPk();
|
||||
$adminIds = $this->getDataLimitAdminIds();
|
||||
if (is_array($adminIds)) {
|
||||
$this->model->where($this->dataLimitField, 'in', $adminIds);
|
||||
}
|
||||
if ($ids) {
|
||||
$this->model->where($pk, 'in', $ids);
|
||||
}
|
||||
$list = $this->model->where($pk, 'in', $ids)->select();
|
||||
|
||||
$count = 0;
|
||||
Db::startTrans();
|
||||
try {
|
||||
$list = $this->model->onlyTrashed()->select();
|
||||
foreach ($list as $k => $v) {
|
||||
$count += $v->delete(true);
|
||||
foreach ($list as $item) {
|
||||
$count += $item->delete();
|
||||
}
|
||||
Db::commit();
|
||||
} catch (PDOException $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
} catch (PDOException|Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($count) {
|
||||
$this->success();
|
||||
} else {
|
||||
$this->error(__('No rows were deleted'));
|
||||
}
|
||||
$this->error(__('Parameter %s can not be empty', 'ids'));
|
||||
$this->error(__('No rows were deleted'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 还原
|
||||
* 真实删除
|
||||
*
|
||||
* @param $ids
|
||||
* @return void
|
||||
*/
|
||||
public function restore($ids = "")
|
||||
public function destroy($ids = null)
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
if (false === $this->request->isPost()) {
|
||||
$this->error(__("Invalid parameters"));
|
||||
}
|
||||
$ids = $ids ? $ids : $this->request->post("ids");
|
||||
$ids = $ids ?: $this->request->post('ids');
|
||||
$pk = $this->model->getPk();
|
||||
$adminIds = $this->getDataLimitAdminIds();
|
||||
if (is_array($adminIds)) {
|
||||
|
|
@ -284,14 +243,49 @@ trait Backend
|
|||
Db::startTrans();
|
||||
try {
|
||||
$list = $this->model->onlyTrashed()->select();
|
||||
foreach ($list as $index => $item) {
|
||||
foreach ($list as $item) {
|
||||
$count += $item->delete(true);
|
||||
}
|
||||
Db::commit();
|
||||
} catch (PDOException|Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($count) {
|
||||
$this->success();
|
||||
}
|
||||
$this->error(__('No rows were deleted'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 还原
|
||||
*
|
||||
* @param $ids
|
||||
* @return void
|
||||
*/
|
||||
public function restore($ids = null)
|
||||
{
|
||||
if (false === $this->request->isPost()) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
$ids = $ids ?: $this->request->post('ids');
|
||||
$pk = $this->model->getPk();
|
||||
$adminIds = $this->getDataLimitAdminIds();
|
||||
if (is_array($adminIds)) {
|
||||
$this->model->where($this->dataLimitField, 'in', $adminIds);
|
||||
}
|
||||
if ($ids) {
|
||||
$this->model->where($pk, 'in', $ids);
|
||||
}
|
||||
$count = 0;
|
||||
Db::startTrans();
|
||||
try {
|
||||
$list = $this->model->onlyTrashed()->select();
|
||||
foreach ($list as $item) {
|
||||
$count += $item->restore();
|
||||
}
|
||||
Db::commit();
|
||||
} catch (PDOException $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
} catch (PDOException|Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
|
@ -303,52 +297,56 @@ trait Backend
|
|||
|
||||
/**
|
||||
* 批量更新
|
||||
*
|
||||
* @param $ids
|
||||
* @return void
|
||||
*/
|
||||
public function multi($ids = "")
|
||||
public function multi($ids = null)
|
||||
{
|
||||
if (!$this->request->isPost()) {
|
||||
$this->error(__("Invalid parameters"));
|
||||
if (false === $this->request->isPost()) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
$ids = $ids ? $ids : $this->request->post("ids");
|
||||
if ($ids) {
|
||||
if ($this->request->has('params')) {
|
||||
parse_str($this->request->post("params"), $values);
|
||||
$values = $this->auth->isSuperAdmin() ? $values : array_intersect_key($values, array_flip(is_array($this->multiFields) ? $this->multiFields : explode(',', $this->multiFields)));
|
||||
if ($values) {
|
||||
$adminIds = $this->getDataLimitAdminIds();
|
||||
if (is_array($adminIds)) {
|
||||
$this->model->where($this->dataLimitField, 'in', $adminIds);
|
||||
}
|
||||
$count = 0;
|
||||
Db::startTrans();
|
||||
try {
|
||||
$list = $this->model->where($this->model->getPk(), 'in', $ids)->select();
|
||||
foreach ($list as $index => $item) {
|
||||
$count += $item->allowField(true)->isUpdate(true)->save($values);
|
||||
}
|
||||
Db::commit();
|
||||
} catch (PDOException $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
if ($count) {
|
||||
$this->success();
|
||||
} else {
|
||||
$this->error(__('No rows were updated'));
|
||||
}
|
||||
} else {
|
||||
$this->error(__('You have no permission'));
|
||||
}
|
||||
$ids = $ids ?: $this->request->post('ids');
|
||||
if (empty($ids)) {
|
||||
$this->error(__('Parameter %s can not be empty', 'ids'));
|
||||
}
|
||||
|
||||
if (false === $this->request->has('params')) {
|
||||
$this->error(__('No rows were updated'));
|
||||
}
|
||||
parse_str($this->request->post('params'), $values);
|
||||
$values = $this->auth->isSuperAdmin() ? $values : array_intersect_key($values, array_flip(is_array($this->multiFields) ? $this->multiFields : explode(',', $this->multiFields)));
|
||||
if (empty($values)) {
|
||||
$this->error(__('You have no permission'));
|
||||
}
|
||||
$adminIds = $this->getDataLimitAdminIds();
|
||||
if (is_array($adminIds)) {
|
||||
$this->model->where($this->dataLimitField, 'in', $adminIds);
|
||||
}
|
||||
$count = 0;
|
||||
Db::startTrans();
|
||||
try {
|
||||
$list = $this->model->where($this->model->getPk(), 'in', $ids)->select();
|
||||
foreach ($list as $item) {
|
||||
$count += $item->allowField(true)->isUpdate(true)->save($values);
|
||||
}
|
||||
Db::commit();
|
||||
} catch (PDOException|Exception $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->error(__('Parameter %s can not be empty', 'ids'));
|
||||
if ($count) {
|
||||
$this->success();
|
||||
}
|
||||
$this->error(__('No rows were updated'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入
|
||||
*
|
||||
* @return void
|
||||
* @throws PDOException
|
||||
* @throws BindParamException
|
||||
*/
|
||||
protected function import()
|
||||
{
|
||||
|
|
@ -368,12 +366,12 @@ trait Backend
|
|||
if ($ext === 'csv') {
|
||||
$file = fopen($filePath, 'r');
|
||||
$filePath = tempnam(sys_get_temp_dir(), 'import_csv');
|
||||
$fp = fopen($filePath, "w");
|
||||
$fp = fopen($filePath, 'w');
|
||||
$n = 0;
|
||||
while ($line = fgets($file)) {
|
||||
$line = rtrim($line, "\n\r\0");
|
||||
$encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']);
|
||||
if ($encoding != 'utf-8') {
|
||||
if ($encoding !== 'utf-8') {
|
||||
$line = mb_convert_encoding($line, 'utf-8', $encoding);
|
||||
}
|
||||
if ($n == 0 || preg_match('/^".*"$/', $line)) {
|
||||
|
|
@ -401,6 +399,7 @@ trait Backend
|
|||
$list = db()->query("SELECT COLUMN_NAME,COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ?", [$table, $database]);
|
||||
foreach ($list as $k => $v) {
|
||||
if ($importHeadType == 'comment') {
|
||||
$v['COLUMN_COMMENT'] = explode(':', $v['COLUMN_COMMENT'])[0]; //字段备注有:时截取
|
||||
$fieldArr[$v['COLUMN_COMMENT']] = $v['COLUMN_NAME'];
|
||||
} else {
|
||||
$fieldArr[$v['COLUMN_NAME']] = $v['COLUMN_NAME'];
|
||||
|
|
@ -461,7 +460,7 @@ trait Backend
|
|||
if ($has_admin_id) {
|
||||
$auth = Auth::instance();
|
||||
foreach ($insert as &$val) {
|
||||
if (!isset($val['admin_id']) || empty($val['admin_id'])) {
|
||||
if (empty($val['admin_id'])) {
|
||||
$val['admin_id'] = $auth->isLogin() ? $auth->id : 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,22 +13,20 @@ class Admin extends Model
|
|||
// 定义时间戳字段名
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = 'updatetime';
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'salt'
|
||||
];
|
||||
|
||||
/**
|
||||
* 重置用户密码
|
||||
* @author baiyouwen
|
||||
*/
|
||||
public function resetPassword($uid, $NewPassword)
|
||||
public static function init()
|
||||
{
|
||||
$passwd = $this->encryptPassword($NewPassword);
|
||||
$ret = $this->where(['id' => $uid])->update(['password' => $passwd]);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// 密码加密
|
||||
protected function encryptPassword($password, $salt = '', $encrypt = 'md5')
|
||||
{
|
||||
return $encrypt($password . $salt);
|
||||
self::beforeWrite(function ($row) {
|
||||
$changed = $row->getChangedData();
|
||||
//如果修改了用户或或密码则需要重新登录
|
||||
if (isset($changed['username']) || isset($changed['password']) || isset($changed['salt'])) {
|
||||
$row->token = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ class AdminLog extends Model
|
|||
|
||||
/**
|
||||
* 记录日志
|
||||
* @param string $title
|
||||
* @param string $content
|
||||
* @param string $title 日志标题
|
||||
* @param string $content 日志内容
|
||||
*/
|
||||
public static function record($title = '', $content = '')
|
||||
{
|
||||
|
|
@ -50,6 +50,9 @@ class AdminLog extends Model
|
|||
$admin_id = $auth->isLogin() ? $auth->id : 0;
|
||||
$username = $auth->isLogin() ? $auth->username : __('Unknown');
|
||||
|
||||
// 设置过滤函数
|
||||
request()->filter('trim,strip_tags,htmlspecialchars');
|
||||
|
||||
$controllername = Loader::parseName(request()->controller());
|
||||
$actionname = strtolower(request()->action());
|
||||
$path = str_replace('.', '/', $controllername) . '/' . $actionname;
|
||||
|
|
@ -60,12 +63,12 @@ class AdminLog extends Model
|
|||
}
|
||||
}
|
||||
}
|
||||
$content = $content ? $content : self::$content;
|
||||
$content = $content ?: self::$content;
|
||||
if (!$content) {
|
||||
$content = request()->param('', null, 'trim,strip_tags,htmlspecialchars');
|
||||
$content = request()->param('') ?: file_get_contents("php://input");
|
||||
$content = self::getPureContent($content);
|
||||
}
|
||||
$title = $title ? $title : self::$title;
|
||||
$title = $title ?: self::$title;
|
||||
if (!$title) {
|
||||
$title = [];
|
||||
$breadcrumb = Auth::instance()->getBreadcrumb($path);
|
||||
|
|
@ -77,18 +80,18 @@ class AdminLog extends Model
|
|||
self::create([
|
||||
'title' => $title,
|
||||
'content' => !is_scalar($content) ? json_encode($content, JSON_UNESCAPED_UNICODE) : $content,
|
||||
'url' => substr(request()->url(), 0, 1500),
|
||||
'url' => substr(xss_clean(strip_tags(request()->url())), 0, 1500),
|
||||
'admin_id' => $admin_id,
|
||||
'username' => $username,
|
||||
'useragent' => substr(request()->server('HTTP_USER_AGENT'), 0, 255),
|
||||
'ip' => request()->ip()
|
||||
'ip' => xss_clean(strip_tags(request()->ip()))
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取已屏蔽关键信息的数据
|
||||
* @param $content
|
||||
* @return false|string
|
||||
* @return array
|
||||
*/
|
||||
protected static function getPureContent($content)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@ class User extends Model
|
|||
self::beforeUpdate(function ($row) {
|
||||
$changedata = $row->getChangedData();
|
||||
$origin = $row->getOriginData();
|
||||
if (isset($changedata['money']) && (function_exists('bccomp') ? bccomp($changedata['money'], $origin['money'], 2) !== 0 : (double) $changedata['money'] !== (double) $origin['money'])) {
|
||||
if (isset($changedata['money']) && (function_exists('bccomp') ? bccomp($changedata['money'], $origin['money'], 2) !== 0 : (double)$changedata['money'] !== (double)$origin['money'])) {
|
||||
MoneyLog::create(['user_id' => $row['id'], 'money' => $changedata['money'] - $origin['money'], 'before' => $origin['money'], 'after' => $changedata['money'], 'memo' => '管理员变更金额']);
|
||||
}
|
||||
if (isset($changedata['score']) && (int) $changedata['score'] !== (int) $origin['score']) {
|
||||
if (isset($changedata['score']) && (int)$changedata['score'] !== (int)$origin['score']) {
|
||||
ScoreLog::create(['user_id' => $row['id'], 'score' => $changedata['score'] - $origin['score'], 'before' => $origin['score'], 'after' => $changedata['score'], 'memo' => '管理员变更积分']);
|
||||
}
|
||||
});
|
||||
|
|
@ -67,21 +67,22 @@ class User extends Model
|
|||
return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
|
||||
}
|
||||
|
||||
|
||||
public function getPrevtimeTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : $data['prevtime'];
|
||||
$value = $value ? $value : ($data['prevtime'] ?? "");
|
||||
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
|
||||
}
|
||||
|
||||
public function getLogintimeTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : $data['logintime'];
|
||||
$value = $value ? $value : ($data['logintime'] ?? "");
|
||||
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
|
||||
}
|
||||
|
||||
public function getJointimeTextAttr($value, $data)
|
||||
{
|
||||
$value = $value ? $value : $data['jointime'];
|
||||
$value = $value ? $value : ($data['jointime'] ?? "");
|
||||
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class UserGroup extends Model
|
|||
{
|
||||
$value = $value ? $value : $data['status'];
|
||||
$list = $this->getStatusList();
|
||||
return isset($list[$value]) ? $list[$value] : '';
|
||||
return $list[$value] ?? '';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,11 +23,18 @@ class UserRule extends Model
|
|||
protected static function init()
|
||||
{
|
||||
self::afterInsert(function ($row) {
|
||||
$pk = $row->getPk();
|
||||
$row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]);
|
||||
if (!$row['weigh']) {
|
||||
$pk = $row->getPk();
|
||||
$row->getQuery()->where($pk, $row[$pk])->update(['weigh' => $row[$pk]]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function getTitleAttr($value, $data)
|
||||
{
|
||||
return __($value);
|
||||
}
|
||||
|
||||
public function getStatusList()
|
||||
{
|
||||
return ['normal' => __('Normal'), 'hidden' => __('Hidden')];
|
||||
|
|
@ -37,7 +44,7 @@ class UserRule extends Model
|
|||
{
|
||||
$value = $value ? $value : $data['status'];
|
||||
$list = $this->getStatusList();
|
||||
return isset($list[$value]) ? $list[$value] : '';
|
||||
return $list[$value] ?? '';
|
||||
}
|
||||
|
||||
public static function getTreeList($selected = [])
|
||||
|
|
|
|||
|
|
@ -11,10 +11,11 @@ class Admin extends Validate
|
|||
* 验证规则
|
||||
*/
|
||||
protected $rule = [
|
||||
'username' => 'require|regex:\w{3,12}|unique:admin',
|
||||
'username' => 'require|regex:\w{3,30}|unique:admin',
|
||||
'nickname' => 'require',
|
||||
'password' => 'require|regex:\S{32}',
|
||||
'email' => 'require|email|unique:admin,email',
|
||||
'mobile' => 'regex:1[3-9]\d{9}|unique:admin,mobile',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -33,8 +34,8 @@ class Admin extends Validate
|
|||
* 验证场景
|
||||
*/
|
||||
protected $scene = [
|
||||
'add' => ['username', 'email', 'nickname', 'password'],
|
||||
'edit' => ['username', 'email', 'nickname', 'password'],
|
||||
'add' => ['username', 'email', 'nickname', 'password', 'mobile'],
|
||||
'edit' => ['username', 'email', 'nickname', 'password', 'mobile'],
|
||||
];
|
||||
|
||||
public function __construct(array $rules = [], $message = [], $field = [])
|
||||
|
|
@ -44,6 +45,7 @@ class Admin extends Validate
|
|||
'nickname' => __('Nickname'),
|
||||
'password' => __('Password'),
|
||||
'email' => __('Email'),
|
||||
'mobile' => __('Mobile'),
|
||||
];
|
||||
$this->message = array_merge($this->message, [
|
||||
'username.regex' => __('Please input correct username'),
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class AuthRule extends Validate
|
|||
* 验证规则
|
||||
*/
|
||||
protected $rule = [
|
||||
'name' => 'require|format|unique:AuthRule',
|
||||
'name' => 'require|unique:AuthRule',
|
||||
'title' => 'require',
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ class User extends Validate
|
|||
* 验证规则
|
||||
*/
|
||||
protected $rule = [
|
||||
'username' => 'require|regex:\w{3,32}|unique:user',
|
||||
'username' => 'require|regex:\w{3,30}|unique:user',
|
||||
'nickname' => 'require|unique:user',
|
||||
'password' => 'regex:\S{6,32}',
|
||||
'password' => 'regex:\S{6,30}',
|
||||
'email' => 'require|email|unique:user',
|
||||
'mobile' => 'unique:user'
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,115 +1,142 @@
|
|||
<form id="config-form" class="edit-form form-horizontal" role="form" data-toggle="validator" method="POST" action="">
|
||||
{if $addon.tips}
|
||||
{if $addon.tips && $addon.tips.value}
|
||||
<div class="alert {$addon.tips.extend|default='alert-info-light'}" style="margin-bottom:10px;">
|
||||
{if $addon.tips.title}
|
||||
<b>{$addon.tips.title}</b><br>
|
||||
{/if}
|
||||
{$addon.tips.value}
|
||||
</div>
|
||||
{/if}
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="15%">{:__('Title')}</th>
|
||||
<th width="85%">{:__('Value')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $addon.config as $item}
|
||||
<tr>
|
||||
<td>{$item.title}</td>
|
||||
<td>
|
||||
<div class="row">
|
||||
<div class="col-sm-8 col-xs-12">
|
||||
{switch $item.type}
|
||||
{case string}
|
||||
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}"/>
|
||||
{/case}
|
||||
{case text}
|
||||
<textarea {$item.extend} name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
|
||||
{/case}
|
||||
{case array}
|
||||
<dl class="fieldlist" data-name="row[{$item.name}]">
|
||||
<dd>
|
||||
<ins>{:__('Array key')}</ins>
|
||||
<ins>{:__('Array value')}</ins>
|
||||
</dd>
|
||||
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
|
||||
<textarea name="row[{$item.name}]" cols="30" rows="5" class="hide">{$item.value|json_encode|htmlentities}</textarea>
|
||||
</dl>
|
||||
{/case}
|
||||
{case date}
|
||||
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
|
||||
{/case}
|
||||
{case time}
|
||||
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
|
||||
{/case}
|
||||
{case datetime}
|
||||
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
|
||||
{/case}
|
||||
{case number}
|
||||
<input {$item.extend} type="number" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
|
||||
{/case}
|
||||
{case checkbox}
|
||||
{foreach name="item.content" item="vo"}
|
||||
<label for="row[{$item.name}][]-{$key}"><input id="row[{$item.name}][]-{$key}" name="row[{$item.name}][]" type="checkbox" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value" }checked{/in} /> {$vo}</label>
|
||||
{/foreach}
|
||||
{/case}
|
||||
{case radio}
|
||||
{foreach name="item.content" item="vo"}
|
||||
<label for="row[{$item.name}]-{$key}"><input id="row[{$item.name}]-{$key}" name="row[{$item.name}]" type="radio" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value" }checked{/in} /> {$vo}</label>
|
||||
{/foreach}
|
||||
{/case}
|
||||
{case value="select" break="0"}{/case}
|
||||
{case value="selects"}
|
||||
<select {$item.extend} name="row[{$item.name}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip}" {$item.type=='selects'?'multiple':''}>
|
||||
{foreach name="item.content" item="vo"}
|
||||
<option value="{$key}" {in name="key" value="$item.value" }selected{/in}>{$vo}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
{/case}
|
||||
{case value="image" break="0"}{/case}
|
||||
{case value="images"}
|
||||
<div class="input-group">
|
||||
<input {$item.extend} id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}" data-rule="{$item.rule}">
|
||||
<div class="input-group-addon no-border no-padding">
|
||||
<span><button type="button" id="faupload-{$item.name}" class="btn btn-danger faupload" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
</div>
|
||||
<span class="msg-box n-right" for="c-{$item.name}"></span>
|
||||
</div>
|
||||
<ul class="row list-inline faupload-preview" id="p-{$item.name}"></ul>
|
||||
{/case}
|
||||
{case value="file" break="0"}{/case}
|
||||
{case value="files"}
|
||||
<div class="input-group">
|
||||
<input {$item.extend} id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}" data-rule="{$item.rule}">
|
||||
<div class="input-group-addon no-border no-padding">
|
||||
<span><button type="button" id="faupload-{$item.name}" class="btn btn-danger faupload" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
</div>
|
||||
<span class="msg-box n-right" for="c-{$item.name}"></span>
|
||||
</div>
|
||||
<ul class="row list-inline faupload-preview" id="p-{$item.name}"></ul>
|
||||
{/case}
|
||||
{case bool}
|
||||
<label for="row[{$item.name}]-yes"><input id="row[{$item.name}]-yes" name="row[{$item.name}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip}" /> {:__('Yes')}</label>
|
||||
<label for="row[{$item.name}]-no"><input id="row[{$item.name}]-no" name="row[{$item.name}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip}" /> {:__('No')}</label>
|
||||
{/case}
|
||||
{default /}{$item.value}
|
||||
{/switch}
|
||||
</div>
|
||||
<div class="col-sm-4"></div>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
<div class="panel panel-default panel-intro">
|
||||
{if count($groupList)>1}
|
||||
<div class="panel-heading mb-3">
|
||||
<ul class="nav nav-tabs nav-group">
|
||||
<li class="active"><a href="#all" data-toggle="tab">全部</a></li>
|
||||
{foreach name="groupList" id="tab"}
|
||||
<li><a href="#tab-{$key}" title="{$tab}" data-toggle="tab">{$tab}</a></li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="panel-body no-padding">
|
||||
<div id="myTabContent" class="tab-content">
|
||||
{foreach name="groupList" id="group" key="groupName"}
|
||||
<div class="tab-pane fade active in" id="tab-{$groupName}">
|
||||
|
||||
<table class="table table-striped table-config mb-0">
|
||||
<tbody>
|
||||
{foreach name="$addon.config" id="item"}
|
||||
{if ((!isset($item['group']) || $item['group']=='') && $groupName=='other') || (isset($item['group']) && $item['group']==$group)}
|
||||
<tr data-favisible="{$item.visible|default=''|htmlentities}" data-name="{$item.name}" class="{if $item.visible??''}hidden{/if}">
|
||||
<td width="15%">{$item.title}</td>
|
||||
<td>
|
||||
<div class="row">
|
||||
<div class="col-sm-8 col-xs-12">
|
||||
{switch $item.type}
|
||||
{case string}
|
||||
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}"/>
|
||||
{/case}
|
||||
{case password}
|
||||
<input {$item.extend} type="password" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}"/>
|
||||
{/case}
|
||||
{case text}
|
||||
<textarea {$item.extend} name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
|
||||
{/case}
|
||||
{case array}
|
||||
<dl class="fieldlist" data-name="row[{$item.name}]">
|
||||
<dd>
|
||||
<ins>{:__('Array key')}</ins>
|
||||
<ins>{:__('Array value')}</ins>
|
||||
</dd>
|
||||
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
|
||||
<textarea name="row[{$item.name}]" cols="30" rows="5" class="hide">{$item.value|json_encode|htmlentities}</textarea>
|
||||
</dl>
|
||||
{/case}
|
||||
{case date}
|
||||
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
|
||||
{/case}
|
||||
{case time}
|
||||
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
|
||||
{/case}
|
||||
{case datetime}
|
||||
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
|
||||
{/case}
|
||||
{case number}
|
||||
<input {$item.extend} type="number" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
|
||||
{/case}
|
||||
{case checkbox}
|
||||
{foreach name="item.content" item="vo"}
|
||||
<label for="row[{$item.name}][]-{$key}"><input id="row[{$item.name}][]-{$key}" name="row[{$item.name}][]" type="checkbox" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value" }checked{/in} /> {$vo}</label>
|
||||
{/foreach}
|
||||
<span class="msg-box n-right" for="row[{$item.name}]"></span>
|
||||
{/case}
|
||||
{case radio}
|
||||
{foreach name="item.content" item="vo"}
|
||||
<label for="row[{$item.name}]-{$key}"><input id="row[{$item.name}]-{$key}" name="row[{$item.name}]" type="radio" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value" }checked{/in} /> {$vo}</label>
|
||||
{/foreach}
|
||||
<span class="msg-box n-right" for="row[{$item.name}]"></span>
|
||||
{/case}
|
||||
{case value="select" break="0"}{/case}
|
||||
{case value="selects"}
|
||||
<select {$item.extend} name="row[{$item.name}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip}" {$item.type=='selects'?'multiple':''}>
|
||||
{foreach name="item.content" item="vo"}
|
||||
<option value="{$key}" {in name="key" value="$item.value" }selected{/in}>{$vo}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
{/case}
|
||||
{case value="image" break="0"}{/case}
|
||||
{case value="images"}
|
||||
<div class="form-inline">
|
||||
<input id="c-{$item.name}" class="form-control" size="28" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
|
||||
<span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
<ul class="row list-inline plupload-preview" id="p-{$item.name}"></ul>
|
||||
<span class="msg-box n-right" for="c-{$item.name}"></span>
|
||||
</div>
|
||||
{/case}
|
||||
{case value="file" break="0"}{/case}
|
||||
{case value="files"}
|
||||
<div class="form-inline">
|
||||
<input id="c-{$item.name}" class="form-control" size="28" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
|
||||
<span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
<span class="msg-box n-right" for="c-{$item.name}"></span>
|
||||
</div>
|
||||
{/case}
|
||||
{case switch}
|
||||
<input id="c-{$item.name}" name="row[{$item.name}]" type="hidden" value="{:$item.value?1:0}">
|
||||
<a href="javascript:;" data-toggle="switcher" class="btn-switcher" data-input-id="c-{$item.name}" data-yes="1" data-no="0">
|
||||
<i class="fa fa-toggle-on text-success {if !$item.value}fa-flip-horizontal text-gray{/if} fa-2x"></i>
|
||||
</a>
|
||||
{/case}
|
||||
{case bool}
|
||||
<label for="row[{$item.name}]-yes"><input id="row[{$item.name}]-yes" name="row[{$item.name}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip}" /> {:__('Yes')}</label>
|
||||
<label for="row[{$item.name}]-no"><input id="row[{$item.name}]-no" name="row[{$item.name}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip}" /> {:__('No')}</label>
|
||||
{/case}
|
||||
{default /}{$item.value}
|
||||
{/switch}
|
||||
</div>
|
||||
<div class="col-sm-4"></div>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/foreach}
|
||||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2" style="width:15%;"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -61,6 +61,11 @@
|
|||
.btn-toggle {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.operate .dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu {
|
||||
bottom: inherit;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div class="panel panel-default panel-intro">
|
||||
<div class="panel-heading">
|
||||
|
|
@ -81,7 +86,7 @@
|
|||
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" data-force-refresh="false"><i class="fa fa-refresh"></i> </a>
|
||||
{if $Think.config.fastadmin.api_url}
|
||||
<button type="button" id="faupload-addon" class="btn btn-danger faupload btn-mini-xs" data-url="addon/local" data-chunking="false" data-mimetype="zip,fastaddon" data-multiple="false"><i class="fa fa-upload"></i>
|
||||
{:__('Offline install')}
|
||||
{:__('Local install')}
|
||||
</button>
|
||||
<div class="btn-group">
|
||||
<a href="#" class="btn btn-info btn-switch active btn-mini-xs" data-type="all"><i class="fa fa-list"></i> {:__('All')}</a>
|
||||
|
|
@ -151,61 +156,6 @@
|
|||
</div>
|
||||
</form>
|
||||
</script>
|
||||
<script id="logintpl" type="text/html">
|
||||
<div>
|
||||
<form class="form-horizontal">
|
||||
<fieldset>
|
||||
<div class="alert alert-dismissable alert-danger">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<strong>{:__('Warning')}</strong><br/>{:__('Login tips')}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-12">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-user"></i></span>
|
||||
<input type="text" class="form-control" id="inputAccount" value=""
|
||||
placeholder="{:__('Your username or email')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-lg-12">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-lock"></i></span>
|
||||
<input type="password" class="form-control" id="inputPassword" value=""
|
||||
placeholder="{:__('Your password')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</script>
|
||||
<script id="userinfotpl" type="text/html">
|
||||
<div>
|
||||
<form class="form-horizontal form-userinfo">
|
||||
<fieldset>
|
||||
<div class="alert alert-dismissable alert-success">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<strong>{:__('Warning')}</strong><br/>{:__('Logined tips', '<%=username%>')}
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="breadcrumb"><a href="https://www.fastadmin.net/user/myaddon.html" target="_blank"><i class="fa fa-money"></i> {:__('My addons')}</a></div>
|
||||
</form>
|
||||
</div>
|
||||
</script>
|
||||
<script id="paytpl" type="text/html">
|
||||
<div class="payimg" style="background:url('<%=payimg%>') 0 0 no-repeat;background-size:cover;">
|
||||
<%if(paycode){%>
|
||||
<div class="alipaycode">
|
||||
<%=paycode%>
|
||||
</div>
|
||||
<div class="wechatcode">
|
||||
<%=paycode%>
|
||||
</div>
|
||||
<%}%>
|
||||
</div>
|
||||
</script>
|
||||
<script id="uninstalltpl" type="text/html">
|
||||
<div class="">
|
||||
<div class=""><%=#__("Are you sure you want to unstall %s?", addon['title'])%>
|
||||
|
|
@ -217,6 +167,11 @@
|
|||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script id="upgradetpl" type="text/html">
|
||||
<div class="">
|
||||
<div class=""><%=#__("Upgrade tips", addon['title'])%></div>
|
||||
</div>
|
||||
</script>
|
||||
<script id="conflicttpl" type="text/html">
|
||||
<div class="alert alert-dismissable alert-danger">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
|
|
@ -245,12 +200,12 @@
|
|||
<% var label = labelarr[item.id % 5]; %>
|
||||
<% var addon = item.addon; %>
|
||||
|
||||
<div class="operate" data-id="<%=item.id%>" data-name="<%=item.name%>">
|
||||
<span class="operate" data-id="<%=item.id%>" data-name="<%=item.name%>">
|
||||
<% if(!addon){ %>
|
||||
<% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%>
|
||||
<span class="btn-group">
|
||||
<a href="javascript:;" class="btn btn-xs btn-primary btn-success btn-install"
|
||||
data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>"
|
||||
data-type="<%=item.price<=0?'free':'price';%>"
|
||||
data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a>
|
||||
<a class="btn btn-xs btn-success dropdown-toggle" data-toggle="dropdown" href="javascript:;">
|
||||
<span class="fa fa-caret-down"></span>
|
||||
|
|
@ -258,14 +213,13 @@
|
|||
<ul class="dropdown-menu">
|
||||
<% for(var j=0;j< item.releaselist.length;j++){ %>
|
||||
<li><a href="javascript:;" class="btn-install" data-type="<%=item.price<=0?'free':'price';%>"
|
||||
data-donateimage="<%=item.donateimage%>"
|
||||
data-version="<%=item.releaselist[j].version%>"><%=item.releaselist[j].version%></a></li>
|
||||
<% } %>
|
||||
</ul>
|
||||
</span>
|
||||
<% }else if(typeof item.releaselist !="undefined" && item.releaselist.length>0){%>
|
||||
<a href="javascript:;" class="btn btn-xs btn-primary btn-success btn-install"
|
||||
data-type="<%=item.price<=0?'free':'price';%>" data-donateimage="<%=item.donateimage%>"
|
||||
data-type="<%=item.price<=0?'free':'price';%>"
|
||||
data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a>
|
||||
<% } %>
|
||||
|
||||
|
|
@ -309,6 +263,6 @@
|
|||
<a href="javascript:;" class="btn btn-xs btn-danger btn-uninstall" title="{:__('Uninstall')}"><i class="fa fa-times"></i>
|
||||
{:__('Uninstall')}</a>
|
||||
<% } %>
|
||||
</div>
|
||||
</span>
|
||||
</script>
|
||||
<!--@formatter:on-->
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@
|
|||
<input type="email" class="form-control" id="email" name="row[email]" value="" data-rule="required;email" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mobile" class="control-label col-xs-12 col-sm-2">{:__('Mobile')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" class="form-control" id="mobile" name="row[mobile]" value="" data-rule="mobile" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
|
@ -39,8 +45,8 @@
|
|||
<div class="form-group hidden layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@
|
|||
<input type="email" class="form-control" id="email" name="row[email]" value="{$row.email|htmlentities}" data-rule="required;email" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mobile" class="control-label col-xs-12 col-sm-2">{:__('Mobile')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" class="form-control" id="mobile" name="row[mobile]" value="{$row.mobile|default=''|htmlentities}" data-rule="mobile" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
|
@ -33,7 +39,7 @@
|
|||
<div class="form-group">
|
||||
<label for="loginfailure" class="control-label col-xs-12 col-sm-2">{:__('Loginfailure')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="number" class="form-control" id="loginfailure" name="row[loginfailure]" value="{$row.loginfailure}" data-rule="required" />
|
||||
<input type="number" class="form-control" id="loginfailure" name="row[loginfailure]" value="{$row.loginfailure|htmlentities}" data-rule="required" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -45,8 +51,8 @@
|
|||
<div class="form-group hidden layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
<div id="toolbar" class="toolbar">
|
||||
{:build_toolbar('refresh,add,delete')}
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover"
|
||||
data-operate-edit="{:$auth->check('auth/admin/edit')}"
|
||||
data-operate-del="{:$auth->check('auth/admin/del')}"
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('auth/admin/edit')}"
|
||||
data-operate-del="{:$auth->check('auth/admin/del')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -18,4 +18,4 @@
|
|||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
<div id="toolbar" class="toolbar">
|
||||
{:build_toolbar('refresh,delete')}
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover"
|
||||
data-operate-detail="{:$auth->check('auth/adminlog/index')}"
|
||||
data-operate-del="{:$auth->check('auth/adminlog/del')}"
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-detail="{:$auth->check('auth/adminlog/index')}"
|
||||
data-operate-del="{:$auth->check('auth/adminlog/del')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -18,4 +18,4 @@
|
|||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Permission')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<span class="text-muted"><input type="checkbox" name="" id="checkall" /> <label for="checkall"><small>{:__('Check all')}</small></label></span>
|
||||
<span class="text-muted"><input type="checkbox" name="" id="expandall" /> <label for="expandall"><small>{:__('Expand all')}</small></label></span>
|
||||
<span class="text-muted"><input type="checkbox" name="" id="checkall" /> <label for="checkall"><span>{:__('Check all')}</span></label></span>
|
||||
<span class="text-muted"><input type="checkbox" name="" id="expandall" /> <label for="expandall"><span>{:__('Expand all')}</span></label></span>
|
||||
|
||||
<div id="treeview"></div>
|
||||
</div>
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
<div class="form-group hidden layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Permission')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<span class="text-muted"><input type="checkbox" name="" id="checkall" /> <label for="checkall"><small>{:__('Check all')}</small></label></span>
|
||||
<span class="text-muted"><input type="checkbox" name="" id="expandall" /> <label for="expandall"><small>{:__('Expand all')}</small></label></span>
|
||||
<span class="text-muted"><input type="checkbox" name="" id="checkall" /> <label for="checkall"><span>{:__('Check all')}</span></label></span>
|
||||
<span class="text-muted"><input type="checkbox" name="" id="expandall" /> <label for="expandall"><span>{:__('Expand all')}</span></label></span>
|
||||
|
||||
<div id="treeview"></div>
|
||||
</div>
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
<div class="form-group hidden layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2 col-xs-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
<div id="toolbar" class="toolbar">
|
||||
{:build_toolbar('refresh,add,delete')}
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover"
|
||||
data-operate-edit="{:$auth->check('auth/group/edit')}"
|
||||
data-operate-del="{:$auth->check('auth/group/del')}"
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('auth/group/edit')}"
|
||||
data-operate-del="{:$auth->check('auth/group/del')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -34,17 +34,12 @@
|
|||
<label for="icon" class="control-label col-xs-12 col-sm-2">{:__('Icon')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="input-group input-groupp-md">
|
||||
<span class="input-group-addon"><i class="fa fa-circle-o" id="icon-style"></i></span>
|
||||
<input type="text" class="form-control" id="icon" name="row[icon]" value="fa fa-circle-o" />
|
||||
<a href="javascript:;" class="btn-search-icon input-group-addon">{:__('Search icon')}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" class="form-control" id="weigh" name="row[weigh]" value="0" data-rule="required" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Condition')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
|
@ -69,6 +64,12 @@
|
|||
<textarea class="form-control" id="remark" name="row[remark]"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" class="form-control" id="weigh" name="row[weigh]" value="0" data-rule="required" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
|
@ -78,7 +79,7 @@
|
|||
<div class="form-group hidden layer-footer">
|
||||
<div class="col-xs-2"></div>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -34,17 +34,12 @@
|
|||
<label for="icon" class="control-label col-xs-12 col-sm-2">{:__('Icon')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="input-group input-groupp-md">
|
||||
<input type="text" class="form-control" id="icon" name="row[icon]" value="{$row.icon}" />
|
||||
<span class="input-group-addon"><i class="{$row.icon|htmlentities}" id="icon-style"></i></span>
|
||||
<input type="text" class="form-control" id="icon" name="row[icon]" value="{$row.icon|htmlentities}" />
|
||||
<a href="javascript:;" class="btn-search-icon input-group-addon">{:__('Search icon')}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" class="form-control" id="weigh" name="row[weigh]" value="{$row.weigh}" data-rule="required" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Condition')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
|
@ -66,7 +61,13 @@
|
|||
<div class="form-group">
|
||||
<label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<textarea class="form-control" id="remark" name="row[remark]">{$row.remark|htmlentities}</textarea>
|
||||
<textarea class="form-control" id="remark" name="row[remark]">{$row.remark|__|htmlentities}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" class="form-control" id="weigh" name="row[weigh]" value="{$row.weigh|htmlentities}" data-rule="required" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -78,7 +79,7 @@
|
|||
<div class="form-group hidden layer-footer">
|
||||
<div class="col-xs-2"></div>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@
|
|||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
<label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="input-group">
|
||||
<input id="c-image" class="form-control" size="35" name="row[image]" type="text" value="{$row.image}">
|
||||
<input id="c-image" class="form-control" size="35" name="row[image]" type="text" value="{$row.image|htmlentities}">
|
||||
<div class="input-group-addon no-border no-padding">
|
||||
<span><button type="button" id="faupload-image" class="btn btn-danger faupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
|
|
@ -77,7 +77,7 @@
|
|||
<div class="form-group">
|
||||
<label for="c-weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-weigh" class="form-control" name="row[weigh]" type="number" value="{$row.weigh}">
|
||||
<input id="c-weigh" class="form-control" name="row[weigh]" type="number" value="{$row.weigh|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover"
|
||||
data-operate-edit="{:$auth->check('category/edit')}"
|
||||
data-operate-del="{:$auth->check('category/del')}"
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('category/edit')}"
|
||||
data-operate-del="{:$auth->check('category/del')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,13 @@
|
|||
display: block;
|
||||
float:left;
|
||||
}
|
||||
.skin-list li.active a {
|
||||
opacity: 1;
|
||||
filter: alpha(opacity=100);
|
||||
}
|
||||
.skin-list li.active p {
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
<!-- Control Sidebar -->
|
||||
<aside class="control-sidebar control-sidebar-dark">
|
||||
|
|
@ -23,12 +30,11 @@
|
|||
<!-- Home tab content -->
|
||||
<div class="tab-pane active" id="control-sidebar-setting-tab">
|
||||
<h4 class="control-sidebar-heading">{:__('Layout Options')}</h4>
|
||||
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-layout="fixed" class="pull-right"> {:__('Fixed Layout')}</label><p>{:__("You can't use fixed and boxed layouts together")}</p></div>
|
||||
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-layout="layout-boxed" class="pull-right"> {:__('Boxed Layout')}</label><p>{:__('Activate the boxed layout')}</p></div>
|
||||
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-config="multiplenav" {if $Think.config.fastadmin.multiplenav}checked{/if} class="pull-right"> {:__('Multiple Nav')}</label><p>{:__("Toggle the top menu state (multiple or single)")}</p></div>
|
||||
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-config="multipletab" {if $Think.config.fastadmin.multipletab}checked{/if} class="pull-right"> {:__('Multiple Tab')}</label><p>{:__("Always show multiple tab when multiple nav is set")}</p></div>
|
||||
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-layout="sidebar-collapse" class="pull-right"> {:__('Toggle Sidebar')}</label><p>{:__("Toggle the left sidebar's state (open or collapse)")}</p></div>
|
||||
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-enable="expandOnHover" class="pull-right"> {:__('Sidebar Expand on Hover')}</label><p>{:__('Let the sidebar mini expand on hover')}</p></div>
|
||||
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-menu="show-submenu" class="pull-right"> {:__('Show sub menu')}</label><p>{:__('Always show sub menu')}</p></div>
|
||||
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-menu="disable-top-badge" class="pull-right"> {:__('Disable top menu badge')}</label><p>{:__('Disable top menu badge without left menu')}</p></div>
|
||||
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-controlsidebar="control-sidebar-open" class="pull-right"> {:__('Toggle Right Sidebar Slide')}</label><p>{:__('Toggle between slide over content and push content effects')}</p></div>
|
||||
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-sidebarskin="toggle" class="pull-right"> {:__('Toggle Right Sidebar Skin')}</label><p>{:__('Toggle between dark and light skins for the right sidebar')}</p></div>
|
||||
<h4 class="control-sidebar-heading">{:__('Skins')}</h4>
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@
|
|||
|
||||
</div>
|
||||
|
||||
<!--如果想始终显示子菜单,则给ul加上show-submenu类即可,当multiplenav开启的情况下默认为展开-->
|
||||
<ul class="sidebar-menu {if $Think.config.fastadmin.multiplenav}show-submenu{/if}">
|
||||
<!-- 左侧菜单栏 -->
|
||||
<ul class="sidebar-menu {if $Think.config.fastadmin.show_submenu}show-submenu{/if}">
|
||||
|
||||
<!-- 菜单可以在 后台管理->权限管理->菜单规则 中进行增删改排序 -->
|
||||
{$menulist}
|
||||
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@
|
|||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
margin-bottom: 20px;
|
||||
-webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.sm-st-icon {
|
||||
|
|
@ -27,7 +25,6 @@
|
|||
}
|
||||
|
||||
.sm-st-info {
|
||||
font-size: 12px;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
|
|
@ -125,6 +122,7 @@
|
|||
.stat .name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.stat.lg .value {
|
||||
|
|
@ -132,6 +130,9 @@
|
|||
line-height: 28px;
|
||||
}
|
||||
|
||||
.stat-col {
|
||||
margin:0 0 10px 0;
|
||||
}
|
||||
.stat.lg .name {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
|
@ -155,7 +156,7 @@
|
|||
}
|
||||
|
||||
#statistics .panel h5 {
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
<div class="panel panel-default panel-intro">
|
||||
|
|
@ -193,8 +194,8 @@
|
|||
<div class="sm-st clearfix">
|
||||
<span class="sm-st-icon st-blue"><i class="fa fa-leaf"></i></span>
|
||||
<div class="sm-st-info">
|
||||
<span>{$totalcategory}</span>
|
||||
{:__('Total category')}
|
||||
<span>{$attachmentnums}</span>
|
||||
{:__('Total attachment')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -211,7 +212,7 @@
|
|||
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<div id="echart" class="btn-refresh" style="height:200px;width:100%;"></div>
|
||||
<div id="echart" class="btn-refresh" style="height:300px;width:100%;"></div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="card sameheight-item stats">
|
||||
|
|
@ -224,7 +225,7 @@
|
|||
<div class="name"> {:__('Today user signup')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 30%"></div>
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 stat-col">
|
||||
|
|
@ -234,7 +235,7 @@
|
|||
<div class="name"> {:__('Today user login')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 25%"></div>
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 stat-col">
|
||||
|
|
@ -244,7 +245,7 @@
|
|||
<div class="name"> {:__('Three dnu')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 25%"></div>
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 stat-col">
|
||||
|
|
@ -254,7 +255,7 @@
|
|||
<div class="name"> {:__('Seven dnu')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 25%"></div>
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 stat-col">
|
||||
|
|
@ -264,7 +265,7 @@
|
|||
<div class="name"> {:__('Seven dau')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 25%"></div>
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 stat-col">
|
||||
|
|
@ -274,7 +275,7 @@
|
|||
<div class="name"> {:__('Thirty dau')}</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 25%"></div>
|
||||
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -292,14 +293,14 @@
|
|||
<div class="panel-body">
|
||||
<div class="panel-title">
|
||||
<span class="label label-primary pull-right">{:__('Real time')}</span>
|
||||
<h5>{:__('Category count')}</h5>
|
||||
<h5>{:__('Working addon count')}</h5>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1 class="no-margins">{$totalcategory}</h1>
|
||||
<h1 class="no-margins">{$totalworkingaddon}</h1>
|
||||
<div class="font-bold"><i class="fa fa-magic"></i>
|
||||
<small>{:__('Category count tips')}</small>
|
||||
<small>{:__('Working addon count tips')}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -308,7 +309,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6 col-md-3">
|
||||
<div class="panel bg-aqua-gradient no-border">
|
||||
<div class="panel bg-teal-gradient no-border">
|
||||
<div class="panel-body">
|
||||
<div class="ibox-title">
|
||||
<span class="label label-primary pull-right">{:__('Real time')}</span>
|
||||
|
|
|
|||
|
|
@ -3,16 +3,25 @@
|
|||
<div class="form-group">
|
||||
<label for="c-third" class="control-label col-xs-12 col-sm-2">{:__('Upload to third')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" name="row[third]" id="c-third" class="form-control" />
|
||||
<input type="text" name="row[third]" id="c-third" class="form-control"/>
|
||||
<ul class="row list-inline faupload-preview" id="p-third"></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="c-third" class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="button" id="faupload-third" class="btn btn-danger faupload" data-multiple="true" data-input-id="c-third" ><i class="fa fa-upload"></i> {:__("Upload to third")}</button>
|
||||
<div style="width:180px;display:inline-block;">
|
||||
<select name="category-third" id="category-third" class="form-control selectpicker">
|
||||
<option value="">{:__('Please select category')}</option>
|
||||
{foreach name="categoryList" id="item"}
|
||||
<option value="{$key}">{$item}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
<button type="button" id="faupload-third" class="btn btn-danger faupload" data-multiple="true" data-input-id="c-third" data-preview-id="p-third"><i class="fa fa-upload"></i> {:__("Upload to third")}</button>
|
||||
{if $config.upload.chunking}
|
||||
<button type="button" id="faupload-third-chunking" class="btn btn-danger faupload" data-chunking="true" data-maxsize="1gb" data-multiple="true" data-input-id="c-third" ><i class="fa fa-upload"></i> {:__("Upload to third by chunk")}</button>
|
||||
<button type="button" id="faupload-third-chunking" class="btn btn-danger faupload" data-chunking="true" data-maxsize="1gb" data-multiple="true" data-input-id="c-third" data-preview-id="p-third"><i class="fa fa-upload"></i> {:__("Upload to third by chunk")}</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -21,27 +30,29 @@
|
|||
<div class="form-group">
|
||||
<label for="c-local" class="control-label col-xs-12 col-sm-2">{:__('Upload to local')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" name="row[local]" id="c-local" class="form-control" />
|
||||
<input type="text" name="row[local]" id="c-local" class="form-control"/>
|
||||
<ul class="row list-inline faupload-preview" id="p-local"></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="c-local" class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="button" id="faupload-local" class="btn btn-primary faupload" data-input-id="c-local" data-url="{:url('ajax/upload')}"><i class="fa fa-upload"></i> {:__("Upload to local")}</button>
|
||||
<div style="width:180px;display:inline-block;">
|
||||
<select name="category-local" id="category-local" class="form-control selectpicker">
|
||||
<option value="">{:__('Please select category')}</option>
|
||||
{foreach name="categoryList" id="item"}
|
||||
<option value="{$key}">{$item}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
</div>
|
||||
<button type="button" id="faupload-local" class="btn btn-primary faupload" data-input-id="c-local" data-multiple="true" data-preview-id="p-local" data-url="{:url('ajax/upload')}"><i class="fa fa-upload"></i> {:__("Upload to local")}</button>
|
||||
{if $config.upload.chunking}
|
||||
<button type="button" id="faupload-local-chunking" class="btn btn-primary faupload" data-chunking="true" data-maxsize="1gb" data-input-id="c-local" data-url="{:url('ajax/upload')}"><i class="fa fa-upload"></i> {:__("Upload to local by chunk")}</button>
|
||||
<button type="button" id="faupload-local-chunking" class="btn btn-primary faupload" data-chunking="true" data-maxsize="1gb" data-input-id="c-local" data-multiple="true" data-preview-id="p-local" data-url="{:url('ajax/upload')}"><i class="fa fa-upload"></i> {:__("Upload to local by chunk")}</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="c-editor" class="control-label col-xs-12 col-sm-2">{:__('Upload from editor')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<textarea name="row[editor]" id="c-editor" cols="60" rows="5" class="form-control editor"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group hidden layer-footer">
|
||||
<div class="col-xs-2"></div>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@
|
|||
<div class="form-group">
|
||||
<label for="c-imagewidth" class="control-label col-xs-12 col-sm-2">{:__('Imagewidth')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" name="row[imagewidth]" value="{$row.imagewidth}" id="c-imagewidth" class="form-control" required />
|
||||
<input type="text" name="row[imagewidth]" value="{$row.imagewidth|htmlentities}" id="c-imagewidth" class="form-control" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-imageheight" class="control-label col-xs-12 col-sm-2">{:__('Imageheight')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" name="row[imageheight]" value="{$row.imageheight}" id="c-imageheight" class="form-control" required />
|
||||
<input type="text" name="row[imageheight]" value="{$row.imageheight|htmlentities}" id="c-imageheight" class="form-control" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
<div class="form-group">
|
||||
<label for="c-imageframes" class="control-label col-xs-12 col-sm-2">{:__('Imageframes')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="number" name="row[imageframes]" value="{$row.imageframes}" id="c-imageframes" class="form-control" />
|
||||
<input type="number" name="row[imageframes]" value="{$row.imageframes|htmlentities}" id="c-imageframes" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
<div class="form-group">
|
||||
<label for="c-filesize" class="control-label col-xs-12 col-sm-2">{:__('Filesize')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="number" name="row[filesize]" value="{$row.filesize}" id="c-filesize" class="form-control" />
|
||||
<input type="number" name="row[filesize]" value="{$row.filesize|htmlentities}" id="c-filesize" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -76,13 +76,13 @@
|
|||
<div class="form-group">
|
||||
<label for="c-storage" class="control-label col-xs-12 col-sm-2">{:__('Storage')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input type="text" name="row[storage]" value="{$row.storage}" id="c-storage" class="form-control" />
|
||||
<input type="text" name="row[storage]" value="{$row.storage|htmlentities}" id="c-storage" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group hide layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@
|
|||
<div class="widget-body no-padding">
|
||||
<div id="toolbar" class="toolbar">
|
||||
{:build_toolbar('refresh')}
|
||||
<span><button type="button" id="faupload-image" class="btn btn-success faupload" data-mimetype="{$Think.get.mimetype|default=''|htmlentities}" data-multiple="true"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="faupload-image" class="btn btn-success faupload" data-mimetype="{$mimetype|default=''|htmlentities}" data-multiple="true"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
{if request()->get('multiple') == 'true'}
|
||||
<a class="btn btn-danger btn-choose-multi"><i class="fa fa-check"></i> {:__('Choose')}</a>
|
||||
{/if}
|
||||
</div>
|
||||
<table id="table" class="table table-bordered table-hover" width="100%">
|
||||
<table id="table" class="table table-bordered table-hover table-nowrap" width="100%">
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -21,25 +21,19 @@
|
|||
visibility: visible;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.edit-form table tr th:nth-last-child(-n + 2), .edit-form table tr td:nth-last-child(-n + 2) {
|
||||
display: none;
|
||||
}
|
||||
.edit-form table tr td .msg-box {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="panel panel-default panel-intro">
|
||||
<div class="panel-heading">
|
||||
{:build_heading(null, false)}
|
||||
<ul class="nav nav-tabs">
|
||||
{foreach $siteList as $index=>$vo}
|
||||
<li class="{$vo.active?'active':''}"><a href="#{$vo.name}" data-toggle="tab">{:__($vo.title)}</a></li>
|
||||
<li class="{$vo.active?'active':''}"><a href="#tab-{$vo.name}" data-toggle="tab">{:__($vo.title)}</a></li>
|
||||
{/foreach}
|
||||
{if $Think.config.app_debug}
|
||||
<li data-toggle="tooltip" title="{:__('Add new config')}">
|
||||
<a href="#addcfg" data-toggle="tab"><i class="fa fa-plus"></i></a>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
@ -47,7 +41,7 @@
|
|||
<div id="myTabContent" class="tab-content">
|
||||
<!--@formatter:off-->
|
||||
{foreach $siteList as $index=>$vo}
|
||||
<div class="tab-pane fade {$vo.active ? 'active in' : ''}" id="{$vo.name}">
|
||||
<div class="tab-pane fade {$vo.active ? 'active in' : ''}" id="tab-{$vo.name}">
|
||||
<div class="widget-body no-padding">
|
||||
<form id="{$vo.name}-form" class="edit-form form-horizontal" role="form" data-toggle="validator" method="POST" action="{:url('general.config/edit')}">
|
||||
{:token()}
|
||||
|
|
@ -56,13 +50,15 @@
|
|||
<tr>
|
||||
<th width="15%">{:__('Title')}</th>
|
||||
<th width="68%">{:__('Value')}</th>
|
||||
{if $Think.config.app_debug}
|
||||
<th width="15%">{:__('Name')}</th>
|
||||
<th width="2%"></th>
|
||||
{/if}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $vo.list as $item}
|
||||
<tr>
|
||||
<tr data-favisible="{$item.visible|default=''|htmlentities}" data-name="{$item.name}" class="{if $item.visible??''}hidden{/if}">
|
||||
<td>{$item.title}</td>
|
||||
<td>
|
||||
<div class="row">
|
||||
|
|
@ -71,6 +67,9 @@
|
|||
{case string}
|
||||
<input {$item.extend_html} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}"/>
|
||||
{/case}
|
||||
{case password}
|
||||
<input {$item.extend_html} type="password" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}"/>
|
||||
{/case}
|
||||
{case text}
|
||||
<textarea {$item.extend_html} name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
|
||||
{/case}
|
||||
|
|
@ -128,7 +127,7 @@
|
|||
{case value="images"}
|
||||
<div class="form-inline">
|
||||
<input id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
|
||||
<span><button type="button" id="faupload-{$item.name}" class="btn btn-danger faupload" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="faupload-{$item.name}" class="btn btn-danger faupload" data-input-id="c-{$item.name}" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
<span class="msg-box n-right" for="c-{$item.name}"></span>
|
||||
<ul class="row list-inline faupload-preview" id="p-{$item.name}"></ul>
|
||||
|
|
@ -171,8 +170,10 @@
|
|||
</div>
|
||||
|
||||
</td>
|
||||
{if $Think.config.app_debug}
|
||||
<td>{php}echo "{\$site.". $item['name'] . "}";{/php}</td>
|
||||
<td>{if $item['id']>17}<a href="javascript:;" class="btn-delcfg text-muted" data-name="{$item.name}"><i class="fa fa-times"></i></a>{/if}</td>
|
||||
<td>{if $item['id']>18}<a href="javascript:;" class="btn-delcfg text-muted" data-name="{$item.name}"><i class="fa fa-times"></i></a>{/if}</td>
|
||||
{/if}
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
|
|
@ -180,11 +181,15 @@
|
|||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
<div class="layer-footer">
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</td>
|
||||
{if $Think.config.app_debug}
|
||||
<td></td>
|
||||
<td></td>
|
||||
{/if}
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
|
@ -309,6 +314,12 @@ value2|title2</textarea>
|
|||
<span class="msg-box n-right" for="rule"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="visible" class="control-label col-xs-12 col-sm-2">{:__('Visible condition')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input type="text" class="form-control" id="visible" name="row[visible]" value="" data-rule=""/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="extend" class="control-label col-xs-12 col-sm-2">{:__('Extend')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
|
|
@ -318,8 +329,12 @@ value2|title2</textarea>
|
|||
<div class="form-group">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
|
||||
{if !$Think.config.app_debug}
|
||||
<button type="button" class="btn btn-primary disabled">{:__('Only work at development environment')}</button>
|
||||
{else/}
|
||||
<button type="submit" class="btn btn-primary btn-embossed">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
</style>
|
||||
<div class="row animated fadeInRight">
|
||||
<div class="col-md-4">
|
||||
<div class="box box-success">
|
||||
<div class="box box-primary">
|
||||
<div class="panel-heading">
|
||||
{:__('Profile')}
|
||||
</div>
|
||||
|
|
@ -56,13 +56,16 @@
|
|||
<button type="button" id="faupload-avatar" class="faupload" data-input-id="c-avatar"><i class="fa fa-upload"></i> {:__('Upload')}</button>
|
||||
</div>
|
||||
|
||||
<h3 class="profile-username text-center">{$admin.username|htmlentities}</h3>
|
||||
<h3 class="profile-username text-center">{$admin.nickname|htmlentities}</h3>
|
||||
|
||||
<p class="text-muted text-center">{$admin.email|htmlentities}</p>
|
||||
<div class="form-group">
|
||||
<label for="username" class="control-label">{:__('Username')}:</label>
|
||||
<input type="text" class="form-control" id="username" name="row[username]" value="{$admin.username|htmlentities}" disabled/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mobile" class="control-label">{:__('Mobile')}:</label>
|
||||
<input type="text" class="form-control" id="mobile" name="row[mobile]" value="{$admin.mobile|htmlentities}" disabled/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email" class="control-label">{:__('Email')}:</label>
|
||||
<input type="text" class="form-control" id="email" name="row[email]" value="{$admin.email|htmlentities}" data-rule="required;email"/>
|
||||
|
|
@ -76,7 +79,7 @@
|
|||
<input type="password" class="form-control" id="password" placeholder="{:__('Leave password blank if dont want to change')}" autocomplete="new-password" name="row[password]" value="" data-rule="password"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-success">{:__('Submit')}</button>
|
||||
<button type="submit" class="btn btn-primary">{:__('Submit')}</button>
|
||||
<button type="reset" class="btn btn-default">{:__('Reset')}</button>
|
||||
</div>
|
||||
|
||||
|
|
@ -100,7 +103,7 @@
|
|||
<div id="toolbar" class="toolbar">
|
||||
{:build_toolbar('refresh')}
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover" width="100%">
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap" width="100%">
|
||||
|
||||
</table>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{$config.language}">
|
||||
<html>
|
||||
<head>
|
||||
<!-- 加载样式及META信息 -->
|
||||
{include file="common/meta" /}
|
||||
</head>
|
||||
<body class="hold-transition {$Think.config.fastadmin.adminskin|default='skin-black-green'} sidebar-mini fixed {:$Think.config.fastadmin.multipletab?'multipletab':''} {:$Think.config.fastadmin.multiplenav?'multiplenav':''}" id="tabs">
|
||||
<body class="hold-transition {$Think.config.fastadmin.adminskin|default='skin-black-blue'} sidebar-mini {:$Think.cookie.sidebar_collapse?'sidebar-collapse':''} fixed {:$Think.config.fastadmin.multipletab?'multipletab':''} {:$Think.config.fastadmin.multiplenav?'multiplenav':''}" id="tabs">
|
||||
|
||||
<div class="wrapper">
|
||||
|
||||
|
|
@ -28,12 +28,12 @@
|
|||
<div class="content-wrapper tab-content tab-addtabs">
|
||||
{if $fixedmenu}
|
||||
<div role="tabpanel" class="tab-pane {:$referermenu?'':'active'}" id="con_{$fixedmenu.id}">
|
||||
<iframe src="{$fixedmenu.url}?addtabs=1" width="100%" height="100%" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling-x="no" scrolling-y="auto" allowtransparency="yes"></iframe>
|
||||
<iframe src="{$fixedmenu.url}{:stripos($fixedmenu.url, '?') !== false ? '&' : '?'}addtabs=1" width="100%" height="100%" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling-x="no" scrolling-y="auto" allowtransparency="yes"></iframe>
|
||||
</div>
|
||||
{/if}
|
||||
{if $referermenu}
|
||||
<div role="tabpanel" class="tab-pane active" id="con_{$referermenu.id}">
|
||||
<iframe src="{$referermenu.url}?addtabs=1" width="100%" height="100%" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling-x="no" scrolling-y="auto" allowtransparency="yes"></iframe>
|
||||
<iframe src="{$referermenu.url}{:stripos($referermenu.url, '?') !== false ? '&' : '?'}addtabs=1" width="100%" height="100%" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling-x="no" scrolling-y="auto" allowtransparency="yes"></iframe>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
<footer class="main-footer hide">
|
||||
<div class="pull-right hidden-xs">
|
||||
</div>
|
||||
<strong>Copyright © 2017-2020 <a href="__PUBLIC__">{$site.name}</a>.</strong> All rights reserved.
|
||||
<strong>Copyright © 2017-{:date("Y")} <a href="__PUBLIC__">{$site.name}</a>.</strong> All rights reserved.
|
||||
</footer>
|
||||
|
||||
<!-- 右侧控制栏 -->
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{$config.language}">
|
||||
<html>
|
||||
<head>
|
||||
{include file="common/meta" /}
|
||||
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
box-shadow: 0 0 30px rgba(0, 0, 0, 0.1);
|
||||
background: rgba(255, 255, 255, 1);
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
/*overflow: hidden;*/
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +55,7 @@
|
|||
|
||||
.login-head {
|
||||
background: #899fe1;
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
.login-form {
|
||||
|
|
@ -99,6 +100,7 @@
|
|||
<p id="profile-name" class="profile-name-card"></p>
|
||||
|
||||
<form action="" method="post" id="login-form">
|
||||
<!--@AdminLoginFormBegin-->
|
||||
<div id="errtips" class="hide"></div>
|
||||
{:token()}
|
||||
<div class="input-group">
|
||||
|
|
@ -110,24 +112,29 @@
|
|||
<div class="input-group-addon"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span></div>
|
||||
<input type="password" class="form-control" id="pd-form-password" placeholder="{:__('Password')}" name="password" autocomplete="off" value="" data-rule="{:__('Password')}:required;password"/>
|
||||
</div>
|
||||
<!--@CaptchaBegin-->
|
||||
{if $Think.config.fastadmin.login_captcha}
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><span class="glyphicon glyphicon-option-horizontal" aria-hidden="true"></span></div>
|
||||
<input type="text" name="captcha" class="form-control" placeholder="{:__('Captcha')}" data-rule="{:__('Captcha')}:required;length(4)" autocomplete="off"/>
|
||||
<input type="text" name="captcha" class="form-control" placeholder="{:__('Captcha')}" data-rule="{:__('Captcha')}:required;length({$Think.config.captcha.length})" autocomplete="off"/>
|
||||
<span class="input-group-addon" style="padding:0;border:none;cursor:pointer;">
|
||||
<img src="{:rtrim('__PUBLIC__', '/')}/index.php?s=/captcha" width="100" height="30" onclick="this.src = '{:rtrim('__PUBLIC__', '/')}/index.php?s=/captcha&r=' + Math.random();"/>
|
||||
</span>
|
||||
<img src="{:rtrim('__PUBLIC__', '/')}/index.php?s=/captcha" width="100" height="30" onclick="this.src = '{:rtrim('__PUBLIC__', '/')}/index.php?s=/captcha&r=' + Math.random();"/>
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
<!--@CaptchaEnd-->
|
||||
{if $keeyloginhours>0}
|
||||
<div class="form-group checkbox">
|
||||
<label class="inline" for="keeplogin">
|
||||
<label class="inline" for="keeplogin" data-toggle="tooltip" title="{:__('The duration of the session is %s hours', $keeyloginhours)}">
|
||||
<input type="checkbox" name="keeplogin" id="keeplogin" value="1"/>
|
||||
{:__('Keep login')}
|
||||
</label>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-success btn-lg btn-block" style="background:#708eea;">{:__('Sign in')}</button>
|
||||
</div>
|
||||
<!--@AdminLoginFormEnd-->
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{$config.language}">
|
||||
<html>
|
||||
<head>
|
||||
{include file="common/meta" /}
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
|
||||
{:token()}
|
||||
<input type="hidden" name="row[rules]" value="{$row.rules}" />
|
||||
<input type="hidden" name="row[rules]" value="{$row.rules|htmlentities}" />
|
||||
<div class="form-group">
|
||||
<label for="c-name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover"
|
||||
data-operate-edit="{:$auth->check('user/group/edit')}"
|
||||
data-operate-del="{:$auth->check('user/group/del')}"
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('user/group/edit')}"
|
||||
data-operate-del="{:$auth->check('user/group/del')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
<div class="form-group">
|
||||
<label for="c-weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<input id="c-weigh" class="form-control" name="row[weigh]" type="number" value="{$row.weigh}">
|
||||
<input id="c-weigh" class="form-control" name="row[weigh]" type="number" value="{$row.weigh|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -14,10 +14,11 @@
|
|||
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a href="javascript:;" class="btn btn-danger btn-toggle-all"><i class="fa fa-plus"></i> {:__('Toggle all')}</a>
|
||||
</div>
|
||||
<table id="table" class="table table-striped table-bordered table-hover"
|
||||
data-operate-edit="{:$auth->check('user/rule/edit')}"
|
||||
data-operate-del="{:$auth->check('user/rule/del')}"
|
||||
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
|
||||
data-operate-edit="{:$auth->check('user/rule/edit')}"
|
||||
data-operate-del="{:$auth->check('user/rule/del')}"
|
||||
width="100%">
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
|
||||
{:token()}
|
||||
<input type="hidden" name="row[id]" value="{$row.id}">
|
||||
<input type="hidden" name="row[id]" value="{$row.id|htmlentities}">
|
||||
<div class="form-group">
|
||||
<label for="c-group_id" class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
{$groupList}
|
||||
</div>
|
||||
|
|
@ -22,26 +22,26 @@
|
|||
<div class="form-group">
|
||||
<label for="c-password" class="control-label col-xs-12 col-sm-2">{:__('Password')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-password" data-rule="password" class="form-control" name="row[password]" type="text" value="" placeholder="{:__('Leave password blank if dont want to change')}" autocomplete="new-password" />
|
||||
<input id="c-password" data-rule="password" class="form-control" name="row[password]" type="password" value="" placeholder="{:__('Leave password blank if dont want to change')}" autocomplete="new-password" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-email" class="control-label col-xs-12 col-sm-2">{:__('Email')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-email" data-rule="" class="form-control" name="row[email]" type="text" value="{$row.email|htmlentities}">
|
||||
<input id="c-email" data-rule="email" class="form-control" name="row[email]" type="text" value="{$row.email|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-mobile" class="control-label col-xs-12 col-sm-2">{:__('Mobile')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-mobile" data-rule="" class="form-control" name="row[mobile]" type="text" value="{$row.mobile|htmlentities}">
|
||||
<input id="c-mobile" data-rule="mobile" class="form-control" name="row[mobile]" type="text" value="{$row.mobile|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-avatar" class="control-label col-xs-12 col-sm-2">{:__('Avatar')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="input-group">
|
||||
<input id="c-avatar" data-rule="" class="form-control" size="50" name="row[avatar]" type="text" value="{$row.avatar}">
|
||||
<input id="c-avatar" data-rule="" class="form-control" size="50" name="row[avatar]" type="text" value="{$row.avatar|htmlentities}">
|
||||
<div class="input-group-addon no-border no-padding">
|
||||
<span><button type="button" id="faupload-avatar" class="btn btn-danger faupload" data-input-id="c-avatar" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-avatar"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
|
||||
<span><button type="button" id="fachoose-avatar" class="btn btn-primary fachoose" data-input-id="c-avatar" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
|
||||
|
|
@ -54,11 +54,11 @@
|
|||
<div class="form-group">
|
||||
<label for="c-level" class="control-label col-xs-12 col-sm-2">{:__('Level')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-level" data-rule="required" class="form-control" name="row[level]" type="number" value="{$row.level}">
|
||||
<input id="c-level" data-rule="required" class="form-control" name="row[level]" type="number" value="{$row.level|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-gender" class="control-label col-xs-12 col-sm-2">{:__('Gender')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Gender')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
{:build_radios('row[gender]', ['1'=>__('Male'), '0'=>__('Female')], $row['gender'])}
|
||||
</div>
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
<div class="form-group">
|
||||
<label for="c-birthday" class="control-label col-xs-12 col-sm-2">{:__('Birthday')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-birthday" data-rule="" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-use-current="true" name="row[birthday]" type="text" value="{$row.birthday}">
|
||||
<input id="c-birthday" data-rule="" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-use-current="true" name="row[birthday]" type="text" value="{$row.birthday|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -78,25 +78,25 @@
|
|||
<div class="form-group">
|
||||
<label for="c-money" class="control-label col-xs-12 col-sm-2">{:__('Money')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-money" data-rule="required" class="form-control" name="row[money]" type="number" value="{$row.money}">
|
||||
<input id="c-money" data-rule="required" class="form-control" name="row[money]" type="number" value="{$row.money|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-score" class="control-label col-xs-12 col-sm-2">{:__('Score')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-score" data-rule="required" class="form-control" name="row[score]" type="number" value="{$row.score}">
|
||||
<input id="c-score" data-rule="required" class="form-control" name="row[score]" type="number" value="{$row.score|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-successions" class="control-label col-xs-12 col-sm-2">{:__('Successions')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-successions" data-rule="required" class="form-control" name="row[successions]" type="number" value="{$row.successions}">
|
||||
<input id="c-successions" data-rule="required" class="form-control" name="row[successions]" type="number" value="{$row.successions|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-maxsuccessions" class="control-label col-xs-12 col-sm-2">{:__('Maxsuccessions')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-maxsuccessions" data-rule="required" class="form-control" name="row[maxsuccessions]" type="number" value="{$row.maxsuccessions}">
|
||||
<input id="c-maxsuccessions" data-rule="required" class="form-control" name="row[maxsuccessions]" type="number" value="{$row.maxsuccessions|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -114,19 +114,19 @@
|
|||
<div class="form-group">
|
||||
<label for="c-loginip" class="control-label col-xs-12 col-sm-2">{:__('Loginip')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-loginip" data-rule="required" class="form-control" name="row[loginip]" type="text" value="{$row.loginip}">
|
||||
<input id="c-loginip" data-rule="required" class="form-control" name="row[loginip]" type="text" value="{$row.loginip|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-loginfailure" class="control-label col-xs-12 col-sm-2">{:__('Loginfailure')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-loginfailure" data-rule="required" class="form-control" name="row[loginfailure]" type="number" value="{$row.loginfailure}">
|
||||
<input id="c-loginfailure" data-rule="required" class="form-control" name="row[loginfailure]" type="number" value="{$row.loginfailure|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="c-joinip" class="control-label col-xs-12 col-sm-2">{:__('Joinip')}:</label>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
<input id="c-joinip" data-rule="required" class="form-control" name="row[joinip]" type="text" value="{$row.joinip}">
|
||||
<input id="c-joinip" data-rule="required" class="form-control" name="row[joinip]" type="text" value="{$row.joinip|htmlentities}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -136,7 +136,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="content" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
|
||||
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
|
||||
</div>
|
||||
|
|
@ -144,7 +144,7 @@
|
|||
<div class="form-group layer-footer">
|
||||
<label class="control-label col-xs-12 col-sm-2"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<button type="submit" class="btn btn-success btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use app\common\library\Upload;
|
|||
use app\common\model\Area;
|
||||
use app\common\model\Version;
|
||||
use fast\Random;
|
||||
use think\captcha\Captcha;
|
||||
use think\Config;
|
||||
use think\Hook;
|
||||
|
||||
|
|
@ -16,15 +17,30 @@ use think\Hook;
|
|||
*/
|
||||
class Common extends Api
|
||||
{
|
||||
protected $noNeedLogin = ['init'];
|
||||
protected $noNeedLogin = ['init', 'captcha'];
|
||||
protected $noNeedRight = '*';
|
||||
|
||||
public function _initialize()
|
||||
{
|
||||
|
||||
if (isset($_SERVER['HTTP_ORIGIN'])) {
|
||||
header('Access-Control-Expose-Headers: __token__');//跨域让客户端获取到
|
||||
}
|
||||
//跨域检测
|
||||
check_cors_request();
|
||||
|
||||
if (!isset($_COOKIE['PHPSESSID'])) {
|
||||
Config::set('session.id', $this->request->server("HTTP_SID"));
|
||||
}
|
||||
parent::_initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载初始化
|
||||
*
|
||||
* @param string $version 版本号
|
||||
* @param string $lng 经度
|
||||
* @param string $lat 纬度
|
||||
* @ApiParams (name="version", type="string", required=true, description="版本号")
|
||||
* @ApiParams (name="lng", type="string", required=true, description="经度")
|
||||
* @ApiParams (name="lat", type="string", required=true, description="纬度")
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
|
|
@ -64,7 +80,7 @@ class Common extends Api
|
|||
/**
|
||||
* 上传文件
|
||||
* @ApiMethod (POST)
|
||||
* @param File $file 文件流
|
||||
* @ApiParams (name="file", type="File", required=true, description="文件流")
|
||||
*/
|
||||
public function upload()
|
||||
{
|
||||
|
|
@ -121,10 +137,30 @@ class Common extends Api
|
|||
$attachment = $upload->upload();
|
||||
} catch (UploadException $e) {
|
||||
$this->error($e->getMessage());
|
||||
} catch (\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
|
||||
$this->success(__('Uploaded successful'), ['url' => $attachment->url, 'fullurl' => cdnurl($attachment->url, true)]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
* @ApiParams (name="id", type="string", required=true, description="要生成验证码的标识")
|
||||
* @return \think\Response
|
||||
*/
|
||||
public function captcha($id = "")
|
||||
{
|
||||
\think\Config::set([
|
||||
'captcha' => array_merge(config('captcha'), [
|
||||
'fontSize' => 44,
|
||||
'imageH' => 150,
|
||||
'imageW' => 350,
|
||||
])
|
||||
]);
|
||||
$captcha = new Captcha((array)Config::get('captcha'));
|
||||
return $captcha->entry($id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace app\api\controller;
|
|||
use app\common\controller\Api;
|
||||
use app\common\library\Ems as Emslib;
|
||||
use app\common\model\User;
|
||||
use think\Hook;
|
||||
|
||||
/**
|
||||
* 邮箱验证码接口
|
||||
|
|
@ -17,23 +18,14 @@ class Ems extends Api
|
|||
public function _initialize()
|
||||
{
|
||||
parent::_initialize();
|
||||
\think\Hook::add('ems_send', function ($params) {
|
||||
$obj = \app\common\library\Email::instance();
|
||||
$result = $obj
|
||||
->to($params->email)
|
||||
->subject('验证码')
|
||||
->message("你的验证码是:" . $params->code)
|
||||
->send();
|
||||
return $result;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送验证码
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $email 邮箱
|
||||
* @param string $event 事件名称
|
||||
* @ApiParams (name="email", type="string", required=true, description="邮箱")
|
||||
* @ApiParams (name="event", type="string", required=true, description="事件名称")
|
||||
*/
|
||||
public function send()
|
||||
{
|
||||
|
|
@ -41,10 +33,35 @@ class Ems extends Api
|
|||
$event = $this->request->post("event");
|
||||
$event = $event ? $event : 'register';
|
||||
|
||||
if (!$email || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$this->error(__('邮箱格式错误'));
|
||||
}
|
||||
if (!preg_match("/^[a-z0-9_\-]{3,30}\$/i", $event)) {
|
||||
$this->error(__('事件名称错误'));
|
||||
}
|
||||
|
||||
//发送前验证码
|
||||
if (config('fastadmin.user_api_captcha')) {
|
||||
|
||||
if (!preg_match("/^[a-z0-9]{4,6}\$/i", $captcha)) {
|
||||
$this->error(__('验证码格式错误'));
|
||||
}
|
||||
|
||||
if (!\think\Validate::is($captcha, 'captcha')) {
|
||||
$this->error("验证码不正确");
|
||||
}
|
||||
}
|
||||
|
||||
$last = Emslib::get($email, $event);
|
||||
if ($last && time() - $last['createtime'] < 60) {
|
||||
$this->error(__('发送频繁'));
|
||||
}
|
||||
|
||||
$ipSendTotal = \app\common\model\Ems::where(['ip' => $this->request->ip()])->whereTime('createtime', '-1 hours')->count();
|
||||
if ($ipSendTotal >= 5) {
|
||||
$this->error(__('发送频繁'));
|
||||
}
|
||||
|
||||
if ($event) {
|
||||
$userinfo = User::getByEmail($email);
|
||||
if ($event == 'register' && $userinfo) {
|
||||
|
|
@ -70,9 +87,9 @@ class Ems extends Api
|
|||
* 检测验证码
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $email 邮箱
|
||||
* @param string $event 事件名称
|
||||
* @param string $captcha 验证码
|
||||
* @ApiParams (name="email", type="string", required=true, description="邮箱")
|
||||
* @ApiParams (name="event", type="string", required=true, description="事件名称")
|
||||
* @ApiParams (name="captcha", type="string", required=true, description="验证码")
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
|
|
@ -81,6 +98,17 @@ class Ems extends Api
|
|||
$event = $event ? $event : 'register';
|
||||
$captcha = $this->request->post("captcha");
|
||||
|
||||
if (!$email || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$this->error(__('邮箱格式错误'));
|
||||
}
|
||||
if (!preg_match("/^[a-z0-9_\-]{3,30}\$/i", $event)) {
|
||||
$this->error(__('事件名称错误'));
|
||||
}
|
||||
|
||||
if (!preg_match("/^[a-z0-9]{4,6}\$/i", $captcha)) {
|
||||
$this->error(__('验证码格式错误'));
|
||||
}
|
||||
|
||||
if ($event) {
|
||||
$userinfo = User::getByEmail($email);
|
||||
if ($event == 'register' && $userinfo) {
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ class Sms extends Api
|
|||
* 发送验证码
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $mobile 手机号
|
||||
* @param string $event 事件名称
|
||||
* @ApiParams (name="mobile", type="string", required=true, description="手机号")
|
||||
* @ApiParams (name="event", type="string", required=true, description="事件名称")
|
||||
*/
|
||||
public function send()
|
||||
{
|
||||
|
|
@ -67,9 +67,9 @@ class Sms extends Api
|
|||
* 检测验证码
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $mobile 手机号
|
||||
* @param string $event 事件名称
|
||||
* @param string $captcha 验证码
|
||||
* @ApiParams (name="mobile", type="string", required=true, description="手机号")
|
||||
* @ApiParams (name="event", type="string", required=true, description="事件名称")
|
||||
* @ApiParams (name="captcha", type="string", required=true, description="验证码")
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ class User extends Api
|
|||
* 会员登录
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $account 账号
|
||||
* @param string $password 密码
|
||||
* @ApiParams (name="account", type="string", required=true, description="账号")
|
||||
* @ApiParams (name="password", type="string", required=true, description="密码")
|
||||
*/
|
||||
public function login()
|
||||
{
|
||||
|
|
@ -62,8 +62,8 @@ class User extends Api
|
|||
* 手机验证码登录
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $mobile 手机号
|
||||
* @param string $captcha 验证码
|
||||
* @ApiParams (name="mobile", type="string", required=true, description="手机号")
|
||||
* @ApiParams (name="captcha", type="string", required=true, description="验证码")
|
||||
*/
|
||||
public function mobilelogin()
|
||||
{
|
||||
|
|
@ -101,11 +101,11 @@ class User extends Api
|
|||
* 注册会员
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $username 用户名
|
||||
* @param string $password 密码
|
||||
* @param string $email 邮箱
|
||||
* @param string $mobile 手机号
|
||||
* @param string $code 验证码
|
||||
* @ApiParams (name="username", type="string", required=true, description="用户名")
|
||||
* @ApiParams (name="password", type="string", required=true, description="密码")
|
||||
* @ApiParams (name="email", type="string", required=true, description="邮箱")
|
||||
* @ApiParams (name="mobile", type="string", required=true, description="手机号")
|
||||
* @ApiParams (name="code", type="string", required=true, description="验证码")
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
|
|
@ -153,10 +153,10 @@ class User extends Api
|
|||
* 修改会员个人信息
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $avatar 头像地址
|
||||
* @param string $username 用户名
|
||||
* @param string $nickname 昵称
|
||||
* @param string $bio 个人简介
|
||||
* @ApiParams (name="avatar", type="string", required=true, description="头像地址")
|
||||
* @ApiParams (name="username", type="string", required=true, description="用户名")
|
||||
* @ApiParams (name="nickname", type="string", required=true, description="昵称")
|
||||
* @ApiParams (name="bio", type="string", required=true, description="个人简介")
|
||||
*/
|
||||
public function profile()
|
||||
{
|
||||
|
|
@ -189,8 +189,8 @@ class User extends Api
|
|||
* 修改邮箱
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $email 邮箱
|
||||
* @param string $captcha 验证码
|
||||
* @ApiParams (name="email", type="string", required=true, description="邮箱")
|
||||
* @ApiParams (name="captcha", type="string", required=true, description="验证码")
|
||||
*/
|
||||
public function changeemail()
|
||||
{
|
||||
|
|
@ -224,8 +224,8 @@ class User extends Api
|
|||
* 修改手机号
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $mobile 手机号
|
||||
* @param string $captcha 验证码
|
||||
* @ApiParams (name="mobile", type="string", required=true, description="手机号")
|
||||
* @ApiParams (name="captcha", type="string", required=true, description="验证码")
|
||||
*/
|
||||
public function changemobile()
|
||||
{
|
||||
|
|
@ -259,8 +259,8 @@ class User extends Api
|
|||
* 第三方登录
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $platform 平台名称
|
||||
* @param string $code Code码
|
||||
* @ApiParams (name="platform", type="string", required=true, description="平台名称")
|
||||
* @ApiParams (name="code", type="string", required=true, description="Code码")
|
||||
*/
|
||||
public function third()
|
||||
{
|
||||
|
|
@ -291,13 +291,13 @@ class User extends Api
|
|||
* 重置密码
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $mobile 手机号
|
||||
* @param string $newpassword 新密码
|
||||
* @param string $captcha 验证码
|
||||
* @ApiParams (name="mobile", type="string", required=true, description="手机号")
|
||||
* @ApiParams (name="newpassword", type="string", required=true, description="新密码")
|
||||
* @ApiParams (name="captcha", type="string", required=true, description="验证码")
|
||||
*/
|
||||
public function resetpwd()
|
||||
{
|
||||
$type = $this->request->post("type");
|
||||
$type = $this->request->post("type", "mobile");
|
||||
$mobile = $this->request->post("mobile");
|
||||
$email = $this->request->post("email");
|
||||
$newpassword = $this->request->post("newpassword");
|
||||
|
|
@ -305,6 +305,10 @@ class User extends Api
|
|||
if (!$newpassword || !$captcha) {
|
||||
$this->error(__('Invalid parameters'));
|
||||
}
|
||||
//验证Token
|
||||
if (!Validate::make()->check(['newpassword' => $newpassword], ['newpassword' => 'require|regex:\S{6,30}'])) {
|
||||
$this->error(__('Password must be 6 to 30 characters'));
|
||||
}
|
||||
if ($type == 'mobile') {
|
||||
if (!Validate::regex($mobile, "^1\d{10}$")) {
|
||||
$this->error(__('Mobile is incorrect'));
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ class Validate extends Api
|
|||
* 检测邮箱
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $email 邮箱
|
||||
* @param string $id 排除会员ID
|
||||
* @ApiParams (name="email", type="string", required=true, description="邮箱")
|
||||
* @ApiParams (name="id", type="string", required=true, description="排除会员ID")
|
||||
*/
|
||||
public function check_email_available()
|
||||
{
|
||||
|
|
@ -41,8 +41,8 @@ class Validate extends Api
|
|||
* 检测用户名
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $username 用户名
|
||||
* @param string $id 排除会员ID
|
||||
* @ApiParams (name="username", type="string", required=true, description="用户名")
|
||||
* @ApiParams (name="id", type="string", required=true, description="排除会员ID")
|
||||
*/
|
||||
public function check_username_available()
|
||||
{
|
||||
|
|
@ -59,8 +59,8 @@ class Validate extends Api
|
|||
* 检测昵称
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $nickname 昵称
|
||||
* @param string $id 排除会员ID
|
||||
* @ApiParams (name="nickname", type="string", required=true, description="昵称")
|
||||
* @ApiParams (name="id", type="string", required=true, description="排除会员ID")
|
||||
*/
|
||||
public function check_nickname_available()
|
||||
{
|
||||
|
|
@ -77,8 +77,8 @@ class Validate extends Api
|
|||
* 检测手机
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $mobile 手机号
|
||||
* @param string $id 排除会员ID
|
||||
* @ApiParams (name="mobile", type="string", required=true, description="手机号")
|
||||
* @ApiParams (name="id", type="string", required=true, description="排除会员ID")
|
||||
*/
|
||||
public function check_mobile_available()
|
||||
{
|
||||
|
|
@ -95,7 +95,7 @@ class Validate extends Api
|
|||
* 检测手机
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $mobile 手机号
|
||||
* @ApiParams (name="mobile", type="string", required=true, description="手机号")
|
||||
*/
|
||||
public function check_mobile_exist()
|
||||
{
|
||||
|
|
@ -111,7 +111,7 @@ class Validate extends Api
|
|||
* 检测邮箱
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $mobile 邮箱
|
||||
* @ApiParams (name="email", type="string", required=true, description="邮箱")
|
||||
*/
|
||||
public function check_email_exist()
|
||||
{
|
||||
|
|
@ -127,9 +127,9 @@ class Validate extends Api
|
|||
* 检测手机验证码
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $mobile 手机号
|
||||
* @param string $captcha 验证码
|
||||
* @param string $event 事件
|
||||
* @ApiParams (name="mobile", type="string", required=true, description="手机号")
|
||||
* @ApiParams (name="captcha", type="string", required=true, description="验证码")
|
||||
* @ApiParams (name="event", type="string", required=true, description="事件")
|
||||
*/
|
||||
public function check_sms_correct()
|
||||
{
|
||||
|
|
@ -146,9 +146,9 @@ class Validate extends Api
|
|||
* 检测邮箱验证码
|
||||
*
|
||||
* @ApiMethod (POST)
|
||||
* @param string $email 邮箱
|
||||
* @param string $captcha 验证码
|
||||
* @param string $event 事件
|
||||
* @ApiParams (name="email", type="string", required=true, description="邮箱")
|
||||
* @ApiParams (name="captcha", type="string", required=true, description="验证码")
|
||||
* @ApiParams (name="event", type="string", required=true, description="事件")
|
||||
*/
|
||||
public function check_ems_correct()
|
||||
{
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue