mirror of https://gitee.com/karson/fastadmin.git
Compare commits
145 Commits
v1.3.5.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 |
|
|
@ -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/其他):?
|
||||
- 报错信息:?
|
||||
14
README.md
14
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 1 群(满)、QQ 2 群(满)、QQ 3 群(满)、QQ 4 群(满)、QQ 5 群(满)、QQ 6 群(满)、[QQ 7 群](https://www.fastadmin.net/goto/qun)。
|
||||
问答社区: https://ask.fastadmin.net
|
||||
|
||||
Github: https://github.com/karsonzhang/fastadmin
|
||||
|
||||
|
|
@ -92,6 +88,6 @@ FastAdmin遵循Apache2开源协议发布,并提供免费使用。
|
|||
|
||||
本项目包含的第三方源码和二进制文件之版权信息另行标注。
|
||||
|
||||
版权所有Copyright © 2017-2022 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,7 +15,6 @@ use think\exception\PDOException;
|
|||
|
||||
class Addon extends Command
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
|
|
@ -33,6 +32,7 @@ class Addon extends Command
|
|||
|
||||
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) {
|
||||
|
|
@ -82,7 +82,6 @@ class Addon extends Command
|
|||
$createTableSql = $result[0]['Create Table'];
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
|
||||
}
|
||||
|
||||
$data = [
|
||||
|
|
@ -177,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'));
|
||||
}
|
||||
|
|
@ -340,5 +339,4 @@ class Addon extends Command
|
|||
{
|
||||
return __DIR__ . '/Addon/stubs/' . $name . '.stub';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
return [
|
||||
[
|
||||
//配置唯一标识
|
||||
'name' => 'usernmae',
|
||||
'name' => 'username',
|
||||
//显示的标题
|
||||
'title' => '用户名',
|
||||
//类型
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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'] ?? '',
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ class Crud extends Command
|
|||
/**
|
||||
* JSON后缀
|
||||
*/
|
||||
protected $jsonSuffix = ['json'];
|
||||
protected $jsonSuffix = ['json', 'array'];
|
||||
|
||||
/**
|
||||
* 标签后缀
|
||||
|
|
@ -435,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 = [];
|
||||
//检查关联表
|
||||
|
|
@ -466,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);
|
||||
|
||||
|
|
@ -666,8 +669,8 @@ class Crud extends Command
|
|||
//如果是关联模型
|
||||
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 . ']');
|
||||
|
|
@ -676,8 +679,8 @@ class Crud extends Command
|
|||
throw new Exception('table [' . $modelTableName . '] must be contain field [' . $relationPrimaryKey . ']');
|
||||
}
|
||||
} elseif ($relation['relationMode'] == 'belongsto') {
|
||||
$relationForeignKey = $relation['relationForeignKey'] ? $relation['relationForeignKey'] : Loader::parseName($relation['relationName']) . "_id";
|
||||
$relationPrimaryKey = $relation['relationPrimaryKey'] ? $relation['relationPrimaryKey'] : $relation['relationPriKey'];
|
||||
$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 . ']');
|
||||
}
|
||||
|
|
@ -685,8 +688,8 @@ class Crud extends Command
|
|||
throw new Exception('relation table [' . $relation['relationTableName'] . '] must be contain field [' . $relationPrimaryKey . ']');
|
||||
}
|
||||
} elseif ($relation['relationMode'] == 'hasmany') {
|
||||
$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 . ']');
|
||||
}
|
||||
|
|
@ -712,6 +715,7 @@ class Crud extends Command
|
|||
$headingHtml = '{:build_heading()}';
|
||||
$controllerImport = '';
|
||||
$importHtml = '';
|
||||
$multipleHtml = '';
|
||||
$recyclebinHtml = '';
|
||||
|
||||
if ($import) {
|
||||
|
|
@ -878,7 +882,7 @@ class Crud extends Command
|
|||
$formEditElement = Form::input('text', $fieldName, $editValue, $attrArr);
|
||||
} elseif ($inputType == 'fieldlist') {
|
||||
$itemArr = $this->getItemArray($itemArr, $field, $v['COLUMN_COMMENT']);
|
||||
$templateName = !isset($itemArr['key']) && !isset($itemArr['value']) && count($itemArr) > 0 ? 'fieldlist-template' : 'fieldlist';
|
||||
$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';
|
||||
$theadListArr = $tbodyListArr = [];
|
||||
|
|
@ -900,6 +904,12 @@ class Crud extends Command
|
|||
$cssClassArr[] = 'selectpage';
|
||||
$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";
|
||||
//如果是类型表需要特殊处理下
|
||||
|
|
@ -930,7 +940,6 @@ class Crud extends Command
|
|||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
if (!$selectpageField) {
|
||||
foreach ($this->fieldSelectpageMap as $m => $n) {
|
||||
|
|
@ -957,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) {
|
||||
|
|
@ -987,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;
|
||||
|
|
@ -1041,7 +1056,7 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1069,7 +1084,7 @@ class Crud extends Command
|
|||
}
|
||||
|
||||
//表注释
|
||||
$tableComment = $modelTableInfo['Comment'];
|
||||
$tableComment = $modelTableInfo ? $modelTableInfo['Comment'] : '';
|
||||
$tableComment = mb_substr($tableComment, -1) == '表' ? mb_substr($tableComment, 0, -1) . '管理' : $tableComment;
|
||||
|
||||
$modelInit = '';
|
||||
|
|
@ -1114,6 +1129,7 @@ class Crud extends Command
|
|||
'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))) . "']);" : '',
|
||||
|
|
@ -1461,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) {
|
||||
|
|
@ -1469,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -1526,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) {
|
||||
|
|
@ -1544,7 +1563,7 @@ EOD;
|
|||
return $itemArr;
|
||||
}
|
||||
|
||||
protected function getFieldType(& $v)
|
||||
protected function getFieldType(&$v)
|
||||
{
|
||||
$inputType = 'text';
|
||||
switch ($v['DATA_TYPE']) {
|
||||
|
|
@ -1688,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 = '';
|
||||
|
|
@ -1728,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'";
|
||||
}
|
||||
|
||||
|
|
@ -1740,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";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
<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-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
<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-primary btn-embossed disabled">{:__('OK')}</button>
|
||||
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</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,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>
|
||||
|
|
@ -12,13 +12,7 @@
|
|||
<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>
|
||||
{%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>
|
||||
|
|
|
|||
|
|
@ -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]]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
|
|
|
|||
|
|
@ -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,7 +86,7 @@ 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);
|
||||
|
|
@ -182,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([
|
||||
|
|
@ -309,8 +309,8 @@ class Install extends Command
|
|||
//数据库配置文件
|
||||
$dbConfigFile = APP_PATH . 'database.php';
|
||||
|
||||
if (version_compare(PHP_VERSION, '7.2.0', '<')) {
|
||||
throw new Exception(__("The current version %s is too low, please use PHP 7.2 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 '用户名',
|
||||
|
|
@ -27,19 +26,18 @@ CREATE TABLE `fa_admin` (
|
|||
`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',
|
||||
|
|
@ -52,12 +50,11 @@ CREATE TABLE `fa_admin_log` (
|
|||
`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',
|
||||
|
|
@ -73,20 +70,19 @@ 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 '文件名称',
|
||||
|
|
@ -99,7 +95,7 @@ CREATE TABLE `fa_attachment` (
|
|||
`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
|
||||
|
|
@ -111,7 +107,6 @@ 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 '父组别',
|
||||
|
|
@ -121,7 +116,7 @@ CREATE TABLE `fa_auth_group` (
|
|||
`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
|
||||
|
|
@ -137,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
|
||||
|
|
@ -156,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为权限节点',
|
||||
|
|
@ -180,7 +173,7 @@ CREATE TABLE `fa_auth_rule` (
|
|||
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
|
||||
|
|
@ -273,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',
|
||||
|
|
@ -292,7 +284,7 @@ CREATE TABLE `fa_category` (
|
|||
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
|
||||
|
|
@ -316,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 '变量名',
|
||||
|
|
@ -332,7 +323,7 @@ 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
|
||||
|
|
@ -345,23 +336,22 @@ INSERT INTO `fa_config` VALUES (4, 'version', 'basic', 'Version', '如果静态
|
|||
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 (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 (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', '', '10000@qq.com', '', '', '', '');
|
||||
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 '事件',
|
||||
|
|
@ -371,12 +361,11 @@ CREATE TABLE `fa_ems` (
|
|||
`ip` varchar(30) DEFAULT '' COMMENT 'IP',
|
||||
`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 '事件',
|
||||
|
|
@ -386,12 +375,11 @@ CREATE TABLE `fa_sms` (
|
|||
`ip` varchar(30) DEFAULT '' COMMENT 'IP',
|
||||
`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',
|
||||
|
|
@ -411,7 +399,8 @@ 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 '点击',
|
||||
|
|
@ -429,19 +418,18 @@ CREATE TABLE `fa_test` (
|
|||
`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, 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\":\"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');
|
||||
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',
|
||||
|
|
@ -464,6 +452,7 @@ CREATE TABLE `fa_user` (
|
|||
`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` bigint(16) DEFAULT NULL COMMENT '加入时间',
|
||||
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
|
||||
|
|
@ -475,19 +464,18 @@ 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 '组名',
|
||||
|
|
@ -496,7 +484,7 @@ CREATE TABLE `fa_user_group` (
|
|||
`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
|
||||
|
|
@ -508,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',
|
||||
|
|
@ -518,12 +505,11 @@ CREATE TABLE `fa_user_money_log` (
|
|||
`memo` varchar(255) DEFAULT '' 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',
|
||||
|
|
@ -536,7 +522,7 @@ CREATE TABLE `fa_user_rule` (
|
|||
`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
|
||||
|
|
@ -559,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',
|
||||
|
|
@ -569,24 +554,22 @@ CREATE TABLE `fa_user_score_log` (
|
|||
`memo` varchar(255) DEFAULT '' 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` 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 '旧版本号',
|
||||
|
|
@ -600,6 +583,6 @@ CREATE TABLE `fa_version` (
|
|||
`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;
|
||||
|
|
|
|||
|
|
@ -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 () {
|
||||
|
|
|
|||
|
|
@ -20,14 +20,14 @@ return [
|
|||
'Dashboard' => '进入后台',
|
||||
'Go back' => '返回上一页',
|
||||
'Install Successed' => '安装成功!',
|
||||
'Security tips' => '温馨提示:请将以下后台登录入口添加到你的收藏夹,为了你的安全,不要泄漏或发送给他人!如有泄漏请及时修改!',
|
||||
'Security tips' => '温馨提示:请将以下后台登录入口添加到你的收藏夹,为了你的站点安全,不要泄漏或发送给他人!如有泄漏请及时修改!',
|
||||
'Please input correct database' => '请输入正确的数据库名',
|
||||
'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;
|
||||
}
|
||||
// 生成压缩文件
|
||||
|
|
|
|||
|
|
@ -18,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -39,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>';
|
||||
}
|
||||
|
|
@ -60,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>';
|
||||
}
|
||||
|
|
@ -121,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];
|
||||
|
|
|
|||
|
|
@ -95,19 +95,24 @@ class Addon extends Backend
|
|||
}
|
||||
$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]);
|
||||
}
|
||||
}
|
||||
$groupList['other'] = '其它';
|
||||
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';
|
||||
|
|
@ -230,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'));
|
||||
}
|
||||
|
|
@ -238,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) {
|
||||
|
|
@ -319,9 +325,8 @@ 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));
|
||||
$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();
|
||||
|
|
@ -442,8 +447,11 @@ class Addon extends Backend
|
|||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
$rows = isset($json['rows']) ? $json['rows'] : [];
|
||||
$rows = $json['rows'] ?? [];
|
||||
foreach ($rows as $index => $row) {
|
||||
if (!isset($row['name'])) {
|
||||
continue;
|
||||
}
|
||||
$onlineaddons[$row['name']] = $row;
|
||||
}
|
||||
Cache::set("onlineaddons", $onlineaddons, 600);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use think\Cache;
|
|||
use think\Config;
|
||||
use think\Db;
|
||||
use think\Lang;
|
||||
use think\Loader;
|
||||
use think\Response;
|
||||
use think\Validate;
|
||||
|
||||
|
|
@ -47,9 +48,20 @@ class Ajax extends Backend
|
|||
$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);
|
||||
$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]);
|
||||
}
|
||||
|
||||
|
|
@ -59,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')) {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ class Index extends Backend
|
|||
'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()) {
|
||||
|
|
@ -66,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 = [
|
||||
|
|
@ -95,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]);
|
||||
|
|
@ -113,6 +115,7 @@ class Index extends Backend
|
|||
}
|
||||
$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);
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ class Admin extends Backend
|
|||
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) {
|
||||
|
|
@ -183,7 +183,7 @@ class Admin extends Backend
|
|||
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']);
|
||||
}
|
||||
|
|
@ -192,7 +192,7 @@ class Admin extends Backend
|
|||
$adminValidate->rule([
|
||||
'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,
|
||||
'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) {
|
||||
|
|
|
|||
|
|
@ -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' => '登 录',
|
||||
|
|
@ -123,6 +125,8 @@ return [
|
|||
'%d year%s after' => '%d年后',
|
||||
'Set to normal' => '设为正常',
|
||||
'Set to hidden' => '设为隐藏',
|
||||
'Set status to normal' => '设为正常',
|
||||
'Set status to hidden' => '设为隐藏',
|
||||
'Recycle bin' => '回收站',
|
||||
'Restore' => '还原',
|
||||
'Restore all' => '还原全部',
|
||||
|
|
|
|||
|
|
@ -14,11 +14,8 @@ return [
|
|||
'Refresh addon cache' => '刷新插件缓存',
|
||||
'Userinfo' => '会员信息',
|
||||
'Reload authorization' => '刷新授权',
|
||||
'Online store' => '在线商店',
|
||||
'Local addon' => '本地插件',
|
||||
'Conflict tips' => '此插件中发现和现有系统中部分文件发现冲突!以下文件将会被影响,请备份好相关文件后再继续操作',
|
||||
'Login tips' => '此处登录账号为<a href="https://www.fastadmin.net" target="_blank">FastAdmin官网账号</a>',
|
||||
'Logined tips' => '你好!%s<br />当前你已经登录,将同步保存你的购买记录',
|
||||
'Pay tips' => '扫码支付后如果仍然无法安装,请不要重复支付,请稍后再重试安装!',
|
||||
'Pay successful tips' => '购买成功!请点击继续安装按钮完成安装!',
|
||||
'Pay click tips' => '请点击这里在新窗口中进行支付!',
|
||||
|
|
@ -26,8 +23,7 @@ return [
|
|||
'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 点击查看更新日志',
|
||||
|
|
@ -37,6 +33,7 @@ return [
|
|||
'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' => '立即登录',
|
||||
|
|
@ -80,7 +77,6 @@ return [
|
|||
'Enable' => '启用',
|
||||
'Your username or email' => '你的手机号、用户名或邮箱',
|
||||
'Your password' => '你的密码',
|
||||
'Login FastAdmin' => '登录',
|
||||
'Login' => '登录',
|
||||
'Logout' => '退出登录',
|
||||
'Register' => '注册账号',
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
return [
|
||||
'Url' => '链接',
|
||||
'Userame' => '用户名',
|
||||
'Username' => '用户名',
|
||||
'Createtime' => '操作时间',
|
||||
'Click to edit' => '点击编辑',
|
||||
'Admin log' => '操作日志',
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ return [
|
|||
'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' => '用户名或密码不正确',
|
||||
|
|
@ -60,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',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -12,5 +12,8 @@ return [
|
|||
'Menu tips' => '规则任意,请不可重复,仅做层级显示,无需匹配控制器和方法',
|
||||
'Node tips' => '模块/控制器/方法名',
|
||||
'Weigh' => '权重',
|
||||
'Status' => '状态'
|
||||
'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'] : '';
|
||||
|
|
|
|||
|
|
@ -460,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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,8 +23,10 @@ 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]]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -42,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 = [])
|
||||
|
|
|
|||
|
|
@ -70,13 +70,13 @@
|
|||
{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="c-{$item.name}"></span>
|
||||
<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="c-{$item.name}"></span>
|
||||
<span class="msg-box n-right" for="row[{$item.name}]"></span>
|
||||
{/case}
|
||||
{case value="select" break="0"}{/case}
|
||||
{case value="selects"}
|
||||
|
|
@ -105,6 +105,12 @@
|
|||
<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>
|
||||
|
|
|
|||
|
|
@ -62,6 +62,10 @@
|
|||
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">
|
||||
|
|
@ -152,60 +156,22 @@
|
|||
</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-info-light">
|
||||
<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-cube"></i> {:__('My addons')}</a></div>
|
||||
</form>
|
||||
</div>
|
||||
</script>
|
||||
<script id="uninstalltpl" type="text/html">
|
||||
<div class="">
|
||||
<div class=""><%=#__("Are you sure you want to unstall %s?", addon['title'])%>
|
||||
<p class="text-danger">{:__('Delete all the addon file and cannot be recovered!')} </p>
|
||||
{if config('app_debug')}
|
||||
{if config('app_debug')}
|
||||
<p class="text-danger"><input type="checkbox" name="droptables" id="droptables" data-name="<%=addon['name']%>"/> {:__('Delete all the addon database and cannot be recovered!')} </p>
|
||||
{/if}
|
||||
{/if}
|
||||
<p class="text-danger">{:__('Please backup important data manually before uninstall!')}</p>
|
||||
</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>
|
||||
|
|
|
|||
|
|
@ -39,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">
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@
|
|||
<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="{$row.icon}" id="icon-style"></i></span>
|
||||
<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>
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
<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" />
|
||||
<input type="text" class="form-control" id="weigh" name="row[weigh]" value="{$row.weigh|htmlentities}" data-rule="required" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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,7 +76,7 @@
|
|||
<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">
|
||||
|
|
|
|||
|
|
@ -21,15 +21,6 @@
|
|||
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">
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
@ -122,12 +123,14 @@
|
|||
</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>
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
<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 table-nowrap"
|
||||
data-operate-edit="{:$auth->check('user/rule/edit')}"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -28,20 +28,20 @@
|
|||
<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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ class Ems extends Api
|
|||
* 发送验证码
|
||||
*
|
||||
* @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()
|
||||
{
|
||||
|
|
@ -33,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) {
|
||||
|
|
@ -62,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()
|
||||
{
|
||||
|
|
@ -73,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");
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ return [
|
|||
'You can only upload a maximum of %s files' => '你最多允许上传 %s 个文件',
|
||||
'You can\'t upload files of this type' => '不允许上传的文件类型',
|
||||
'Server responded with %s code' => '服务端响应(Code:%s)',
|
||||
'File is too big (%sMiB), Max filesize: %sMiB' => '当前上传(%sM),最大允许上传文件大小:%sM',
|
||||
'File is too big (%sMiB), Max filesize: %sMiB.' => '当前上传(%sM),最大允许上传文件大小:%sM',
|
||||
'Redirect now' => '立即跳转',
|
||||
'Operation completed' => '操作成功!',
|
||||
'Operation failed' => '操作失败!',
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
// 公共助手函数
|
||||
|
||||
use Symfony\Component\VarExporter\VarExporter;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\Response;
|
||||
|
||||
|
|
@ -11,7 +10,7 @@ if (!function_exists('__')) {
|
|||
/**
|
||||
* 获取语言变量值
|
||||
* @param string $name 语言变量名
|
||||
* @param array $vars 动态变量值
|
||||
* @param string | array $vars 动态变量值
|
||||
* @param string $lang 语言
|
||||
* @return mixed
|
||||
*/
|
||||
|
|
@ -41,7 +40,7 @@ if (!function_exists('format_bytes')) {
|
|||
function format_bytes($size, $delimiter = '', $precision = 2)
|
||||
{
|
||||
$units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB');
|
||||
for ($i = 0; $size >= 1024 && $i < 6; $i++) {
|
||||
for ($i = 0; $size >= 1024 && $i < 5; $i++) {
|
||||
$size /= 1024;
|
||||
}
|
||||
return round($size, $precision) . $delimiter . $units[$i];
|
||||
|
|
@ -89,7 +88,9 @@ if (!function_exists('cdnurl')) {
|
|||
{
|
||||
$regex = "/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/i";
|
||||
$cdnurl = \think\Config::get('upload.cdnurl');
|
||||
$url = preg_match($regex, $url) || ($cdnurl && stripos($url, $cdnurl) === 0) ? $url : $cdnurl . $url;
|
||||
if (is_bool($domain) || stripos($cdnurl, '/') === 0) {
|
||||
$url = preg_match($regex, $url) || ($cdnurl && stripos($url, $cdnurl) === 0) ? $url : $cdnurl . $url;
|
||||
}
|
||||
if ($domain && !preg_match($regex, $url)) {
|
||||
$domain = is_bool($domain) ? request()->domain() : $domain;
|
||||
$url = $domain . $url;
|
||||
|
|
@ -216,7 +217,7 @@ if (!function_exists('addtion')) {
|
|||
} else {
|
||||
foreach ($fields as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
$v['field'] = isset($v['field']) ? $v['field'] : $k;
|
||||
$v['field'] = $v['field'] ?? $k;
|
||||
} else {
|
||||
$v = ['field' => $v];
|
||||
}
|
||||
|
|
@ -225,12 +226,12 @@ if (!function_exists('addtion')) {
|
|||
}
|
||||
foreach ($fieldsArr as $k => &$v) {
|
||||
$v = is_array($v) ? $v : ['field' => $v];
|
||||
$v['display'] = isset($v['display']) ? $v['display'] : str_replace(['_ids', '_id'], ['_names', '_name'], $v['field']);
|
||||
$v['primary'] = isset($v['primary']) ? $v['primary'] : '';
|
||||
$v['column'] = isset($v['column']) ? $v['column'] : 'name';
|
||||
$v['model'] = isset($v['model']) ? $v['model'] : '';
|
||||
$v['table'] = isset($v['table']) ? $v['table'] : '';
|
||||
$v['name'] = isset($v['name']) ? $v['name'] : str_replace(['_ids', '_id'], '', $v['field']);
|
||||
$v['display'] = $v['display'] ?? str_replace(['_ids', '_id'], ['_names', '_name'], $v['field']);
|
||||
$v['primary'] = $v['primary'] ?? '';
|
||||
$v['column'] = $v['column'] ?? 'name';
|
||||
$v['model'] = $v['model'] ?? '';
|
||||
$v['table'] = $v['table'] ?? '';
|
||||
$v['name'] = $v['name'] ?? str_replace(['_ids', '_id'], '', $v['field']);
|
||||
}
|
||||
unset($v);
|
||||
$ids = [];
|
||||
|
|
@ -247,9 +248,10 @@ if (!function_exists('addtion')) {
|
|||
if ($v['model']) {
|
||||
$model = new $v['model'];
|
||||
} else {
|
||||
$model = $v['name'] ? \think\Db::name($v['name']) : \think\Db::table($v['table']);
|
||||
// 优先判断使用table的配置
|
||||
$model = $v['table'] ? \think\Db::table($v['table']) : \think\Db::name($v['name']);
|
||||
}
|
||||
$primary = $v['primary'] ? $v['primary'] : $model->getPk();
|
||||
$primary = $v['primary'] ?: $model->getPk();
|
||||
$result[$v['field']] = isset($ids[$v['field']]) ? $model->where($primary, 'in', $ids[$v['field']])->column($v['column'], $primary) : [];
|
||||
}
|
||||
|
||||
|
|
@ -278,60 +280,6 @@ if (!function_exists('var_export_short')) {
|
|||
function var_export_short($data, $return = true)
|
||||
{
|
||||
return var_export($data, $return);
|
||||
$replaced = [];
|
||||
$count = 0;
|
||||
|
||||
//判断是否是对象
|
||||
if (is_resource($data) || is_object($data)) {
|
||||
return var_export($data, $return);
|
||||
}
|
||||
|
||||
//判断是否有特殊的键名
|
||||
$specialKey = false;
|
||||
array_walk_recursive($data, function (&$value, &$key) use (&$specialKey) {
|
||||
if (is_string($key) && (stripos($key, "\n") !== false || stripos($key, "array (") !== false)) {
|
||||
$specialKey = true;
|
||||
}
|
||||
});
|
||||
if ($specialKey) {
|
||||
return var_export($data, $return);
|
||||
}
|
||||
array_walk_recursive($data, function (&$value, &$key) use (&$replaced, &$count, &$stringcheck) {
|
||||
if (is_object($value) || is_resource($value)) {
|
||||
$replaced[$count] = var_export($value, true);
|
||||
$value = "##<{$count}>##";
|
||||
} else {
|
||||
if (is_string($value) && (stripos($value, "\n") !== false || stripos($value, "array (") !== false)) {
|
||||
$index = array_search($value, $replaced);
|
||||
if ($index === false) {
|
||||
$replaced[$count] = var_export($value, true);
|
||||
$value = "##<{$count}>##";
|
||||
} else {
|
||||
$value = "##<{$index}>##";
|
||||
}
|
||||
}
|
||||
}
|
||||
$count++;
|
||||
});
|
||||
|
||||
$dump = var_export($data, true);
|
||||
|
||||
$dump = preg_replace('#(?:\A|\n)([ ]*)array \(#i', '[', $dump); // Starts
|
||||
$dump = preg_replace('#\n([ ]*)\),#', "\n$1],", $dump); // Ends
|
||||
$dump = preg_replace('#=> \[\n\s+\],\n#', "=> [],\n", $dump); // Empties
|
||||
$dump = preg_replace('#\)$#', "]", $dump); //End
|
||||
|
||||
if ($replaced) {
|
||||
$dump = preg_replace_callback("/'##<(\d+)>##'/", function ($matches) use ($replaced) {
|
||||
return isset($replaced[$matches[1]]) ? $replaced[$matches[1]] : "''";
|
||||
}, $dump);
|
||||
}
|
||||
|
||||
if ($return === true) {
|
||||
return $dump;
|
||||
} else {
|
||||
echo $dump;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -427,7 +375,7 @@ if (!function_exists('check_cors_request')) {
|
|||
*/
|
||||
function check_cors_request()
|
||||
{
|
||||
if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN']) {
|
||||
if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN'] && config('fastadmin.cors_request_domain')) {
|
||||
$info = parse_url($_SERVER['HTTP_ORIGIN']);
|
||||
$domainArr = explode(',', config('fastadmin.cors_request_domain'));
|
||||
$domainArr[] = request()->host(true);
|
||||
|
|
@ -465,6 +413,19 @@ if (!function_exists('xss_clean')) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!function_exists('url_clean')) {
|
||||
/**
|
||||
* 清理URL
|
||||
*/
|
||||
function url_clean($url)
|
||||
{
|
||||
if (!check_url_allowed($url)) {
|
||||
return '';
|
||||
}
|
||||
return xss_clean($url);
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('check_ip_allowed')) {
|
||||
/**
|
||||
* 检测IP是否允许
|
||||
|
|
@ -483,6 +444,40 @@ if (!function_exists('check_ip_allowed')) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!function_exists('check_url_allowed')) {
|
||||
/**
|
||||
* 检测URL是否允许
|
||||
* @param string $url URL
|
||||
* @return bool
|
||||
*/
|
||||
function check_url_allowed($url = '')
|
||||
{
|
||||
//允许的主机列表
|
||||
$allowedHostArr = [
|
||||
strtolower(request()->host())
|
||||
];
|
||||
|
||||
if (empty($url)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//如果是站内相对链接则允许
|
||||
if (preg_match("/^[\/a-z][a-z0-9][a-z0-9\.\/]+((\?|#).*)?\$/i", $url) && substr($url, 0, 2) !== '//') {
|
||||
return true;
|
||||
}
|
||||
|
||||
//如果是站外链接则需要判断HOST是否允许
|
||||
if (preg_match("/((http[s]?:\/\/)+((?>[a-z\-0-9]{2,}\.)+[a-z]{2,8}|((?>([0-9]{1,3}\.)){3}[0-9]{1,3}))(:[0-9]{1,5})?)(?:\s|\/)/i", $url)) {
|
||||
$chkHost = parse_url(strtolower($url), PHP_URL_HOST);
|
||||
if ($chkHost && in_array($chkHost, $allowedHostArr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('build_suffix_image')) {
|
||||
/**
|
||||
* 生成文件后缀图片
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class Common
|
|||
}
|
||||
// 切换多语言
|
||||
if (Config::get('lang_switch_on')) {
|
||||
$lang = $request->get('lang');
|
||||
$lang = $request->get('lang', '');
|
||||
if (preg_match("/^([a-zA-Z\-_]{2,10})\$/i", $lang)) {
|
||||
\think\Cookie::set('think_var', $lang);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,8 +204,8 @@ class Api
|
|||
'time' => Request::instance()->server('REQUEST_TIME'),
|
||||
'data' => $data,
|
||||
];
|
||||
// 如果未设置类型则自动判断
|
||||
$type = $type ? $type : ($this->request->param(config('var_jsonp_handler')) ? 'jsonp' : $this->responseType);
|
||||
// 如果未设置类型则使用默认类型判断
|
||||
$type = $type ? : $this->responseType;
|
||||
|
||||
if (isset($header['statuscode'])) {
|
||||
$code = $header['statuscode'];
|
||||
|
|
|
|||
|
|
@ -123,10 +123,10 @@ class Backend extends Controller
|
|||
$path = str_replace('.', '/', $controllername) . '/' . $actionname;
|
||||
|
||||
// 定义是否Addtabs请求
|
||||
!defined('IS_ADDTABS') && define('IS_ADDTABS', input("addtabs") ? true : false);
|
||||
!defined('IS_ADDTABS') && define('IS_ADDTABS', (bool)input("addtabs"));
|
||||
|
||||
// 定义是否Dialog请求
|
||||
!defined('IS_DIALOG') && define('IS_DIALOG', input("dialog") ? true : false);
|
||||
!defined('IS_DIALOG') && define('IS_DIALOG', (bool)input("dialog"));
|
||||
|
||||
// 定义是否AJAX请求
|
||||
!defined('IS_AJAX') && define('IS_AJAX', $this->request->isAjax());
|
||||
|
|
@ -268,12 +268,13 @@ class Backend extends Controller
|
|||
$op = $this->request->get("op", '', 'trim');
|
||||
$sort = $this->request->get("sort", !empty($this->model) && $this->model->getPk() ? $this->model->getPk() : 'id');
|
||||
$order = $this->request->get("order", "DESC");
|
||||
$offset = $this->request->get("offset/d", 0);
|
||||
$limit = $this->request->get("limit/d", 999999);
|
||||
$offset = max(0, $this->request->get("offset/d", 0));
|
||||
$limit = max(0, $this->request->get("limit/d", 0));
|
||||
$limit = $limit ?: 999999;
|
||||
//新增自动计算页码
|
||||
$page = $limit ? intval($offset / $limit) + 1 : 1;
|
||||
if ($this->request->has("page")) {
|
||||
$page = $this->request->get("page/d", 1);
|
||||
$page = max(0, $this->request->get("page/d", 1));
|
||||
}
|
||||
$this->request->get([config('paginate.var_page') => $page]);
|
||||
$filter = (array)json_decode($filter, true);
|
||||
|
|
@ -284,7 +285,7 @@ class Backend extends Controller
|
|||
$bind = [];
|
||||
$name = '';
|
||||
$aliasName = '';
|
||||
if (!empty($this->model) && $this->relationSearch) {
|
||||
if (!empty($this->model) && $relationSearch) {
|
||||
$name = $this->model->getTable();
|
||||
$alias[$name] = Loader::parseName(basename(str_replace('\\', '/', get_class($this->model))));
|
||||
$aliasName = $alias[$name] . '.';
|
||||
|
|
@ -312,12 +313,12 @@ class Backend extends Controller
|
|||
if (!preg_match('/^[a-zA-Z0-9_\-\.]+$/', $k)) {
|
||||
continue;
|
||||
}
|
||||
$sym = isset($op[$k]) ? $op[$k] : '=';
|
||||
$sym = $op[$k] ?? '=';
|
||||
if (stripos($k, ".") === false) {
|
||||
$k = $aliasName . $k;
|
||||
}
|
||||
$v = !is_array($v) ? trim($v) : $v;
|
||||
$sym = strtoupper(isset($op[$k]) ? $op[$k] : $sym);
|
||||
$sym = strtoupper($op[$k] ?? $sym);
|
||||
//null和空字符串特殊处理
|
||||
if (!is_array($v)) {
|
||||
if (in_array(strtoupper($v), ['NULL', 'NOT NULL'])) {
|
||||
|
|
@ -367,8 +368,8 @@ class Backend extends Controller
|
|||
case 'NOT BETWEEN':
|
||||
$arr = array_slice(explode(',', $v), 0, 2);
|
||||
if (stripos($v, ',') === false || !array_filter($arr, function ($v) {
|
||||
return $v != '' && $v !== false && $v !== null;
|
||||
})) {
|
||||
return $v != '' && $v !== false && $v !== null;
|
||||
})) {
|
||||
continue 2;
|
||||
}
|
||||
//当出现一边为空时改变操作符
|
||||
|
|
@ -397,7 +398,8 @@ class Backend extends Controller
|
|||
$arr = $arr[0];
|
||||
}
|
||||
$tableArr = explode('.', $k);
|
||||
if (count($tableArr) > 1 && $tableArr[0] != $name && !in_array($tableArr[0], $alias) && !empty($this->model)) {
|
||||
if (count($tableArr) > 1 && $tableArr[0] != $name && !in_array($tableArr[0], $alias)
|
||||
&& !empty($this->model) && $this->relationSearch) {
|
||||
//修复关联模型下时间无法搜索的BUG
|
||||
$relation = Loader::parseName($tableArr[0], 1, false);
|
||||
$alias[$this->model->$relation()->getTable()] = $tableArr[0];
|
||||
|
|
@ -568,8 +570,8 @@ class Backend extends Controller
|
|||
unset($item['password'], $item['salt']);
|
||||
if ($this->selectpageFields == '*') {
|
||||
$result = [
|
||||
$primarykey => isset($item[$primarykey]) ? $item[$primarykey] : '',
|
||||
$field => isset($item[$field]) ? $item[$field] : '',
|
||||
$primarykey => $item[$primarykey] ?? '',
|
||||
$field => $item[$field] ?? '',
|
||||
];
|
||||
} else {
|
||||
$result = array_intersect_key(($item instanceof Model ? $item->toArray() : (array)$item), array_flip($fields));
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ class Auth
|
|||
'avatar' => '',
|
||||
];
|
||||
$params = array_merge($data, [
|
||||
'nickname' => preg_match("/^1[3-9]{1}\d{9}$/",$username) ? substr_replace($username,'****',3,4) : $username,
|
||||
'nickname' => preg_match("/^1[3-9]{1}\d{9}$/", $username) ? substr_replace($username, '****', 3, 4) : $username,
|
||||
'salt' => Random::alnum(),
|
||||
'jointime' => $time,
|
||||
'joinip' => $ip,
|
||||
|
|
@ -221,7 +221,13 @@ class Auth
|
|||
$this->setError('Account is locked');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($user->loginfailure >= 10 && time() - $user->loginfailuretime < 86400) {
|
||||
$this->setError('Please try again after 1 day');
|
||||
}
|
||||
|
||||
if ($user->password != $this->getEncryptPassword($password, $user->salt)) {
|
||||
$user->save(['loginfailure' => $user->loginfailure + 1, 'loginfailuretime' => time()]);
|
||||
$this->setError('Password is incorrect');
|
||||
return false;
|
||||
}
|
||||
|
|
@ -356,7 +362,7 @@ class Auth
|
|||
}
|
||||
$url = ($module ? $module : request()->module()) . '/' . (is_null($path) ? $this->getRequestUri() : $path);
|
||||
$url = strtolower(str_replace('.', '/', $url));
|
||||
return in_array($url, $rules) ? true : false;
|
||||
return in_array($url, $rules);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -394,7 +400,7 @@ class Auth
|
|||
|
||||
/**
|
||||
* 获取会员组别规则列表
|
||||
* @return array
|
||||
* @return array|bool|\PDOStatement|string|\think\Collection
|
||||
*/
|
||||
public function getRuleList()
|
||||
{
|
||||
|
|
@ -547,7 +553,7 @@ class Auth
|
|||
}
|
||||
}
|
||||
foreach ($datalist as $k => &$v) {
|
||||
$v[$renderkey] = isset($list[$v[$fieldkey]]) ? $list[$v[$fieldkey]] : null;
|
||||
$v[$renderkey] = $list[$v[$fieldkey]] ?? null;
|
||||
}
|
||||
unset($v);
|
||||
return $datalist;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class Email
|
|||
}
|
||||
$this->options = array_merge($this->options, $options);
|
||||
$secureArr = [0 => '', 1 => 'tls', 2 => 'ssl'];
|
||||
$secure = isset($secureArr[$this->options['mail_verify_type']]) ? $secureArr[$this->options['mail_verify_type']] : '';
|
||||
$secure = $secureArr[$this->options['mail_verify_type']] ?? '';
|
||||
|
||||
$logger = isset($this->options['debug']) && $this->options['debug'] ? new Log : null;
|
||||
$this->mail = new Mailer($logger);
|
||||
|
|
@ -217,8 +217,8 @@ class Email
|
|||
$this->setError($e->getCode() . $e->getMessage());
|
||||
} catch (CodeException $e) {
|
||||
preg_match_all("/Expected: (\d+)\, Got: (\d+)( \| (.*))?\$/i", $e->getMessage(), $matches);
|
||||
$code = isset($matches[2][3]) ? $matches[2][3] : 0;
|
||||
$message = isset($matches[2][0]) ? $matches[4][0] : $e->getMessage();
|
||||
$code = $matches[2][0] ?? 0;
|
||||
$message = isset($matches[2][0]) && isset($matches[4][0]) ? $matches[4][0] : $e->getMessage();
|
||||
$message = mb_convert_encoding($message, 'UTF-8', 'GBK,GB2312,BIG5');
|
||||
$this->setError($message);
|
||||
} catch (\Exception $e) {
|
||||
|
|
|
|||
|
|
@ -28,16 +28,15 @@ class Ems
|
|||
*
|
||||
* @param int $email 邮箱
|
||||
* @param string $event 事件
|
||||
* @return Ems
|
||||
* @return Ems|null
|
||||
*/
|
||||
public static function get($email, $event = 'default')
|
||||
{
|
||||
$ems = \app\common\model\Ems::
|
||||
where(['email' => $email, 'event' => $event])
|
||||
$ems = \app\common\model\Ems::where(['email' => $email, 'event' => $event])
|
||||
->order('id', 'DESC')
|
||||
->find();
|
||||
Hook::listen('ems_get', $ems, null, true);
|
||||
return $ems ? $ems : null;
|
||||
return $ems ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -103,7 +102,7 @@ class Ems
|
|||
});
|
||||
}
|
||||
$result = Hook::listen('ems_notice', $params, null, true);
|
||||
return $result ? true : false;
|
||||
return (bool)$result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -150,8 +149,7 @@ class Ems
|
|||
*/
|
||||
public static function flush($email, $event = 'default')
|
||||
{
|
||||
\app\common\model\Ems::
|
||||
where(['email' => $email, 'event' => $event])
|
||||
\app\common\model\Ems::where(['email' => $email, 'event' => $event])
|
||||
->delete();
|
||||
Hook::listen('ems_flush');
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ class Log extends AbstractLogger
|
|||
/**
|
||||
* Logs with an arbitrary level.
|
||||
*
|
||||
* @param mixed $level
|
||||
* @param string $message
|
||||
* @param mixed[] $context
|
||||
* @param mixed $level
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class Menu
|
|||
if ($ids) {
|
||||
//旧版本的菜单需要做删除处理
|
||||
$config = Service::config($name);
|
||||
$menus = isset($config['menus']) ? $config['menus'] : [];
|
||||
$menus = $config['menus'] ?? [];
|
||||
$where = ['id' => ['in', $ids]];
|
||||
if ($menus) {
|
||||
//必须是旧版本中的菜单,可排除用户自主创建的菜单
|
||||
|
|
@ -182,14 +182,14 @@ class Menu
|
|||
} else {
|
||||
$pid = $parent;
|
||||
}
|
||||
$allow = array_flip(['file', 'name', 'title', 'url', 'icon', 'condition', 'remark', 'ismenu', 'menutype', 'extend', 'weigh']);
|
||||
$allow = array_flip(['file', 'name', 'title', 'url', 'icon', 'condition', 'remark', 'ismenu', 'menutype', 'extend', 'weigh', 'status']);
|
||||
foreach ($newMenu as $k => $v) {
|
||||
$hasChild = isset($v['sublist']) && $v['sublist'] ? true : false;
|
||||
$hasChild = isset($v['sublist']) && $v['sublist'];
|
||||
$data = array_intersect_key($v, $allow);
|
||||
$data['ismenu'] = isset($data['ismenu']) ? $data['ismenu'] : ($hasChild ? 1 : 0);
|
||||
$data['icon'] = isset($data['icon']) ? $data['icon'] : ($hasChild ? 'fa fa-list' : 'fa fa-circle-o');
|
||||
$data['ismenu'] = $data['ismenu'] ?? ($hasChild ? 1 : 0);
|
||||
$data['icon'] = $data['icon'] ?? ($hasChild ? 'fa fa-list' : 'fa fa-circle-o');
|
||||
$data['pid'] = $pid;
|
||||
$data['status'] = 'normal';
|
||||
$data['status'] = $data['status'] ?? 'normal';
|
||||
if (!isset($oldMenu[$data['name']])) {
|
||||
$menu = AuthRule::create($data);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ use Exception;
|
|||
*/
|
||||
class Security
|
||||
{
|
||||
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
|
|
@ -420,7 +419,7 @@ class Security
|
|||
*/
|
||||
public function get_random_bytes($length)
|
||||
{
|
||||
if (empty($length) OR !ctype_digit((string)$length)) {
|
||||
if (empty($length) or !ctype_digit((string)$length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -485,8 +484,8 @@ class Security
|
|||
|
||||
static $_entities;
|
||||
|
||||
isset($charset) OR $charset = $this->charset;
|
||||
isset($_entities) OR $_entities = array_map('strtolower', get_html_translation_table(HTML_ENTITIES, ENT_COMPAT | ENT_HTML5, $charset));
|
||||
isset($charset) or $charset = $this->charset;
|
||||
isset($_entities) or $_entities = array_map('strtolower', get_html_translation_table(HTML_ENTITIES, ENT_COMPAT | ENT_HTML5, $charset));
|
||||
|
||||
do {
|
||||
$str_compare = $str;
|
||||
|
|
@ -698,7 +697,7 @@ class Security
|
|||
// Is it indeed an "evil" attribute?
|
||||
preg_match($is_evil_pattern, $attribute['name'][0])
|
||||
// Or does it have an equals sign, but no value and not quoted? Strip that too!
|
||||
OR (trim($attribute['value'][0]) === '')
|
||||
or (trim($attribute['value'][0]) === '')
|
||||
) {
|
||||
$attributes[] = 'xss=removed';
|
||||
} else {
|
||||
|
|
@ -870,5 +869,4 @@ class Security
|
|||
|
||||
return $str;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,12 +32,11 @@ class Sms
|
|||
*/
|
||||
public static function get($mobile, $event = 'default')
|
||||
{
|
||||
$sms = \app\common\model\Sms::
|
||||
where(['mobile' => $mobile, 'event' => $event])
|
||||
$sms = \app\common\model\Sms::where(['mobile' => $mobile, 'event' => $event])
|
||||
->order('id', 'DESC')
|
||||
->find();
|
||||
Hook::listen('sms_get', $sms, null, true);
|
||||
return $sms ? $sms : null;
|
||||
return $sms ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -78,7 +77,7 @@ class Sms
|
|||
'template' => $template
|
||||
];
|
||||
$result = Hook::listen('sms_notice', $params, null, true);
|
||||
return $result ? true : false;
|
||||
return (bool)$result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -125,8 +124,7 @@ class Sms
|
|||
*/
|
||||
public static function flush($mobile, $event = 'default')
|
||||
{
|
||||
\app\common\model\Sms::
|
||||
where(['mobile' => $mobile, 'event' => $event])
|
||||
\app\common\model\Sms::where(['mobile' => $mobile, 'event' => $event])
|
||||
->delete();
|
||||
Hook::listen('sms_flush');
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ class Token
|
|||
/**
|
||||
* 清除Token
|
||||
* @access public
|
||||
* @param int user_id 会员ID
|
||||
* @param int $user_id 会员ID
|
||||
* @return boolean
|
||||
*/
|
||||
public static function clear($user_id = null)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use think\Hook;
|
|||
*/
|
||||
class Upload
|
||||
{
|
||||
|
||||
protected $merging = false;
|
||||
|
||||
protected $chunkDir = null;
|
||||
|
|
@ -130,8 +129,8 @@ class Upload
|
|||
if (!$imgInfo || !isset($imgInfo[0]) || !isset($imgInfo[1])) {
|
||||
throw new UploadException(__('Uploaded file is not a valid image'));
|
||||
}
|
||||
$this->fileInfo['imagewidth'] = isset($imgInfo[0]) ? $imgInfo[0] : 0;
|
||||
$this->fileInfo['imageheight'] = isset($imgInfo[1]) ? $imgInfo[1] : 0;
|
||||
$this->fileInfo['imagewidth'] = $imgInfo[0] ?? 0;
|
||||
$this->fileInfo['imageheight'] = $imgInfo[1] ?? 0;
|
||||
return true;
|
||||
} else {
|
||||
return !$force;
|
||||
|
|
@ -148,11 +147,13 @@ class Upload
|
|||
$size = $matches ? $matches[1] : $this->config['maxsize'];
|
||||
$type = $matches ? strtolower($matches[2]) : 'b';
|
||||
$typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
|
||||
$size = (int)($size * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0));
|
||||
$size = (int)($size * pow(1024, $typeDict[$type] ?? 0));
|
||||
if ($this->fileInfo['size'] > $size) {
|
||||
throw new UploadException(__('File is too big (%sMiB), Max filesize: %sMiB.',
|
||||
throw new UploadException(__(
|
||||
'File is too big (%sMiB), Max filesize: %sMiB.',
|
||||
round($this->fileInfo['size'] / pow(1024, 2), 2),
|
||||
round($size / pow(1024, 2), 2)));
|
||||
round($size / pow(1024, 2), 2)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -304,7 +305,7 @@ class Upload
|
|||
|
||||
$attachment = $this->upload();
|
||||
} catch (\Exception $e) {
|
||||
@unlink($destFile);
|
||||
@unlink($uploadPath);
|
||||
throw new UploadException($e->getMessage());
|
||||
}
|
||||
return $attachment;
|
||||
|
|
@ -316,7 +317,6 @@ class Upload
|
|||
*/
|
||||
public function chunk($chunkid, $chunkindex, $chunkcount, $chunkfilesize = null, $chunkfilename = null, $direct = false)
|
||||
{
|
||||
|
||||
if ($this->fileInfo['type'] != 'application/octet-stream') {
|
||||
throw new UploadException(__('Uploaded file format is limited'));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ abstract class Driver
|
|||
protected function getEncryptedToken($token)
|
||||
{
|
||||
$config = \think\Config::get('token');
|
||||
$token = $token ?? ''; // 为兼容 php8
|
||||
return hash_hmac($config['hashalgo'], $token, $config['key']);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ class Redis extends Driver
|
|||
protected function getEncryptedToken($token)
|
||||
{
|
||||
$config = \think\Config::get('token');
|
||||
$token = $token ?? ''; // 为兼容 php8
|
||||
return $this->options['tokenprefix'] . hash_hmac($config['hashalgo'], $token, $config['key']);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ class Area extends Model
|
|||
{
|
||||
$namearr = [1 => 'geo:province', 2 => 'geo:city', 3 => 'geo:district'];
|
||||
$rangearr = [1 => 15000, 2 => 1000, 3 => 200];
|
||||
$geoname = isset($namearr[$level]) ? $namearr[$level] : $namearr[3];
|
||||
$georange = isset($rangearr[$level]) ? $rangearr[$level] : $rangearr[3];
|
||||
$geoname = $namearr[$level] ?? $namearr[3];
|
||||
$georange = $rangearr[$level] ?? $rangearr[3];
|
||||
// 读取范围内的ID
|
||||
$redis = Cache::store('redis')->handler();
|
||||
$georadiuslist = [];
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ class Category extends Model
|
|||
protected static function init()
|
||||
{
|
||||
self::afterInsert(function ($row) {
|
||||
$row->save(['weigh' => $row['id']]);
|
||||
if (!$row['weigh']) {
|
||||
$row->save(['weigh' => $row['id']]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +52,7 @@ class Category extends Model
|
|||
{
|
||||
$value = $value ? $value : $data['type'];
|
||||
$list = $this->getTypeList();
|
||||
return isset($list[$value]) ? $list[$value] : '';
|
||||
return $list[$value] ?? '';
|
||||
}
|
||||
|
||||
public function getFlagList()
|
||||
|
|
|
|||
|
|
@ -115,8 +115,8 @@ class Config extends Model
|
|||
$data = $result;
|
||||
}
|
||||
$fieldarr = $valuearr = [];
|
||||
$field = isset($data['field']) ? $data['field'] : (isset($data['key']) ? $data['key'] : []);
|
||||
$value = isset($data['value']) ? $data['value'] : [];
|
||||
$field = $data['field'] ?? ($data['key'] ?? []);
|
||||
$value = $data['value'] ?? [];
|
||||
foreach ($field as $m => $n) {
|
||||
if ($n != '') {
|
||||
$fieldarr[] = $field[$m];
|
||||
|
|
@ -175,7 +175,7 @@ class Config extends Model
|
|||
if (!preg_match("/^((?:[a-z]+:)?\/\/)(.*)/i", $uploadurl) && substr($uploadurl, 0, 1) !== '/') {
|
||||
$uploadurl = url($uploadurl, '', false);
|
||||
}
|
||||
$uploadcfg['fullmode'] = isset($uploadcfg['fullmode']) && $uploadcfg['fullmode'] ? true : false;
|
||||
$uploadcfg['fullmode'] = isset($uploadcfg['fullmode']) && $uploadcfg['fullmode'];
|
||||
$uploadcfg['thumbstyle'] = $uploadcfg['thumbstyle'] ?? '';
|
||||
|
||||
$upload = [
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use think\Model;
|
|||
/**
|
||||
* 邮箱验证码
|
||||
*/
|
||||
class Ems Extends Model
|
||||
class Ems extends Model
|
||||
{
|
||||
|
||||
// 开启自动写入时间戳字段
|
||||
|
|
@ -18,5 +18,4 @@ class Ems Extends Model
|
|||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use think\Model;
|
|||
/**
|
||||
* 会员余额日志模型
|
||||
*/
|
||||
class MoneyLog Extends Model
|
||||
class MoneyLog extends Model
|
||||
{
|
||||
|
||||
// 表名
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use think\Model;
|
|||
/**
|
||||
* 会员积分日志模型
|
||||
*/
|
||||
class ScoreLog Extends Model
|
||||
class ScoreLog extends Model
|
||||
{
|
||||
|
||||
// 表名
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use think\Model;
|
|||
/**
|
||||
* 短信验证码
|
||||
*/
|
||||
class Sms Extends Model
|
||||
class Sms extends Model
|
||||
{
|
||||
|
||||
// 开启自动写入时间戳字段
|
||||
|
|
@ -18,5 +18,4 @@ class Sms Extends Model
|
|||
// 追加属性
|
||||
protected $append = [
|
||||
];
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
页面未找到
|
||||
|
|
@ -19,7 +19,7 @@ if (isset($_GET['lang'])) {
|
|||
$langSet = strtolower($_COOKIE['think_var']);
|
||||
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
||||
preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
|
||||
$langSet = strtolower($matches[1]);
|
||||
$langSet = strtolower($matches[1] ?? '');
|
||||
}
|
||||
$langSet = $langSet && in_array($langSet, ['zh-cn', 'en']) ? $langSet : 'zh-cn';
|
||||
$langSet == 'en' && $lang = array_combine(array_keys($lang), array_keys($lang));
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ return [
|
|||
// 默认时区
|
||||
'default_timezone' => 'PRC',
|
||||
// 是否开启多语言
|
||||
'lang_switch_on' => true,
|
||||
'lang_switch_on' => false,
|
||||
// 默认全局过滤方法 用逗号分隔多个
|
||||
'default_filter' => '',
|
||||
// 默认语言
|
||||
|
|
@ -151,6 +151,11 @@ return [
|
|||
// +----------------------------------------------------------------------
|
||||
// 异常页面的模板文件
|
||||
'exception_tmpl' => APP_PATH . 'common' . DS . 'view' . DS . 'tpl' . DS . 'think_exception.tpl',
|
||||
// 自定义错误码模板
|
||||
'http_exception_template' => [
|
||||
// 定义404错误的模板渲染
|
||||
// 404 => APP_PATH . 'common/view/tpl/404.tpl',
|
||||
],
|
||||
// 错误显示信息,非调试模式有效
|
||||
'error_message' => '你所浏览的页面暂时无法访问',
|
||||
// 显示错误信息
|
||||
|
|
@ -297,7 +302,7 @@ return [
|
|||
//允许跨域的域名,多个以,分隔
|
||||
'cors_request_domain' => 'localhost,127.0.0.1',
|
||||
//版本号
|
||||
'version' => '1.3.5.20221214',
|
||||
'version' => '1.5.2.20240906',
|
||||
//API接口地址
|
||||
'api_url' => 'https://api.fastadmin.net',
|
||||
],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
return [
|
||||
'connector' => 'Redis', // Redis 驱动
|
||||
'expire' => 0, // 任务的过期时间,默认为60秒; 若要禁用,则设置为 null
|
||||
'default' => 'default', // 默认的队列名称
|
||||
'host' => '127.0.0.1', // redis 主机ip
|
||||
'port' => 6379, // redis 端口
|
||||
'password' => '', // redis 密码
|
||||
'select' => 0, // 使用哪一个 db,默认为 db0
|
||||
'timeout' => 0, // redis连接的超时时间
|
||||
'persistent' => false,
|
||||
];
|
||||
|
|
@ -33,8 +33,8 @@ return [
|
|||
'mail_type' => '1',
|
||||
'mail_smtp_host' => 'smtp.qq.com',
|
||||
'mail_smtp_port' => '465',
|
||||
'mail_smtp_user' => '10000',
|
||||
'mail_smtp_pass' => 'password',
|
||||
'mail_smtp_user' => '',
|
||||
'mail_smtp_pass' => '',
|
||||
'mail_verify_type' => '2',
|
||||
'mail_from' => '10000@qq.com',
|
||||
'mail_from' => '',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace app\index\controller;
|
|||
|
||||
use app\common\controller\Frontend;
|
||||
use think\Lang;
|
||||
use think\Loader;
|
||||
use think\Response;
|
||||
|
||||
/**
|
||||
|
|
@ -31,8 +32,20 @@ class Ajax extends Frontend
|
|||
$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);
|
||||
$className = Loader::parseClass($this->request->module(), 'controller', $controllername, false);
|
||||
|
||||
//存在对应的类才加载
|
||||
if (class_exists($className)) {
|
||||
$this->loadlang($controllername);
|
||||
}
|
||||
|
||||
//强制输出JSON Object
|
||||
return jsonp(Lang::get(), 200, $header, ['json_encode_param' => JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,13 +65,13 @@ class User extends Frontend
|
|||
*/
|
||||
public function register()
|
||||
{
|
||||
$url = $this->request->request('url', '', 'trim');
|
||||
$url = $this->request->request('url', '', 'url_clean');
|
||||
if ($this->auth->id) {
|
||||
$this->success(__('You\'ve logged in, do not login again'), $url ? $url : url('user/index'));
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$username = $this->request->post('username');
|
||||
$password = $this->request->post('password');
|
||||
$password = $this->request->post('password', '', null);
|
||||
$email = $this->request->post('email');
|
||||
$mobile = $this->request->post('mobile', '');
|
||||
$captcha = $this->request->post('captcha');
|
||||
|
|
@ -128,9 +128,8 @@ class User extends Frontend
|
|||
}
|
||||
}
|
||||
//判断来源
|
||||
$referer = $this->request->server('HTTP_REFERER');
|
||||
if (!$url && (strtolower(parse_url($referer, PHP_URL_HOST)) == strtolower($this->request->host()))
|
||||
&& !preg_match("/(user\/login|user\/register|user\/logout)/i", $referer)) {
|
||||
$referer = $this->request->server('HTTP_REFERER', '', 'url_clean');
|
||||
if (!$url && $referer && !preg_match("/(user\/login|user\/register|user\/logout)/i", $referer)) {
|
||||
$url = $referer;
|
||||
}
|
||||
$this->view->assign('captchaType', config('fastadmin.user_register_captcha'));
|
||||
|
|
@ -144,13 +143,13 @@ class User extends Frontend
|
|||
*/
|
||||
public function login()
|
||||
{
|
||||
$url = $this->request->request('url', '', 'trim');
|
||||
$url = $this->request->request('url', '', 'url_clean');
|
||||
if ($this->auth->id) {
|
||||
$this->success(__('You\'ve logged in, do not login again'), $url ? $url : url('user/index'));
|
||||
$this->success(__('You\'ve logged in, do not login again'), $url ?: url('user/index'));
|
||||
}
|
||||
if ($this->request->isPost()) {
|
||||
$account = $this->request->post('account');
|
||||
$password = $this->request->post('password');
|
||||
$password = $this->request->post('password', '', null);
|
||||
$keeplogin = (int)$this->request->post('keeplogin');
|
||||
$token = $this->request->post('__token__');
|
||||
$rule = [
|
||||
|
|
@ -174,7 +173,6 @@ class User extends Frontend
|
|||
$result = $validate->check($data);
|
||||
if (!$result) {
|
||||
$this->error(__($validate->getError()), null, ['token' => $this->request->token()]);
|
||||
return false;
|
||||
}
|
||||
if ($this->auth->login($account, $password)) {
|
||||
$this->success(__('Logged in successful'), $url ? $url : url('user/index'));
|
||||
|
|
@ -183,9 +181,8 @@ class User extends Frontend
|
|||
}
|
||||
}
|
||||
//判断来源
|
||||
$referer = $this->request->server('HTTP_REFERER');
|
||||
if (!$url && (strtolower(parse_url($referer, PHP_URL_HOST)) == strtolower($this->request->host()))
|
||||
&& !preg_match("/(user\/login|user\/register|user\/logout)/i", $referer)) {
|
||||
$referer = $this->request->server('HTTP_REFERER', '', 'url_clean');
|
||||
if (!$url && $referer && !preg_match("/(user\/login|user\/register|user\/logout)/i", $referer)) {
|
||||
$url = $referer;
|
||||
}
|
||||
$this->view->assign('url', $url);
|
||||
|
|
@ -225,9 +222,9 @@ class User extends Frontend
|
|||
public function changepwd()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$oldpassword = $this->request->post("oldpassword");
|
||||
$newpassword = $this->request->post("newpassword");
|
||||
$renewpassword = $this->request->post("renewpassword");
|
||||
$oldpassword = $this->request->post("oldpassword", '', null);
|
||||
$newpassword = $this->request->post("newpassword", '', null);
|
||||
$renewpassword = $this->request->post("renewpassword", '', null);
|
||||
$token = $this->request->post('__token__');
|
||||
$rule = [
|
||||
'oldpassword' => 'require|regex:\S{6,30}',
|
||||
|
|
@ -254,7 +251,6 @@ class User extends Frontend
|
|||
$result = $validate->check($data);
|
||||
if (!$result) {
|
||||
$this->error(__($validate->getError()), null, ['token' => $this->request->token()]);
|
||||
return false;
|
||||
}
|
||||
|
||||
$ret = $this->auth->changepwd($newpassword, $oldpassword);
|
||||
|
|
|
|||
|
|
@ -24,26 +24,21 @@
|
|||
<a href="{:url('user/profile')}" class="btn btn-primary pull-right"><i class="fa fa-pencil"></i> {:__('Profile')}</a>
|
||||
</h2>
|
||||
<div class="row user-baseinfo">
|
||||
<div class="col-md-3 col-sm-3 col-xs-2 text-center user-center">
|
||||
<div class="col-md-3 col-sm-3 col-xs-3 text-center user-center">
|
||||
<a href="{:url('user/profile')}" title="{:__('Click to edit')}">
|
||||
<span class="avatar-img"><img src="{$user.avatar|htmlentities|cdnurl}" alt=""></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-9 col-sm-9 col-xs-10">
|
||||
<!-- Content -->
|
||||
<div class="col-md-9 col-sm-9 col-xs-9">
|
||||
<div class="ui-content">
|
||||
<!-- Heading -->
|
||||
<h4><a href="{:url('user/profile')}">{$user.nickname|htmlentities}</a></h4>
|
||||
<!-- Paragraph -->
|
||||
<p class="text-muted">
|
||||
{$user.bio|default=__("This guy hasn't written anything yet")|htmlentities}
|
||||
</p>
|
||||
<!-- Success -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-9 col-sm-9 col-xs-12">
|
||||
<!-- Content -->
|
||||
<div class="ui-content">
|
||||
<div class="basicinfo">
|
||||
<div class="row">
|
||||
|
|
@ -56,12 +51,6 @@
|
|||
<a href="javascript:;" class="viewscore">{$user.score}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-md-2">{:__('Successions')}</div>
|
||||
<div class="col-xs-8 col-md-4">{$user.successions} {:__('Day')}</div>
|
||||
<div class="col-xs-4 col-md-2">{:__('Maxsuccessions')}</div>
|
||||
<div class="col-xs-8 col-md-4">{$user.maxsuccessions} {:__('Day')}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-md-2">{:__('Logintime')}</div>
|
||||
<div class="col-xs-8 col-md-4">{$user.logintime|date="Y-m-d H:i:s",###}</div>
|
||||
|
|
|
|||
|
|
@ -86,8 +86,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group form-footer">
|
||||
<label class="control-label col-xs-12 col-sm-3"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="col-xs-12 col-sm-8 col-sm-offset-3">
|
||||
<button type="submit" class="btn btn-md btn-primary">{:__('Ok')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -132,8 +132,7 @@
|
|||
</div>
|
||||
<div class="form-footer">
|
||||
<div class="form-group" style="margin-bottom:0;">
|
||||
<label class="control-label col-xs-12 col-sm-3"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="col-xs-12 col-sm-8 col-sm-offset-3">
|
||||
<button type="submit" class="btn btn-md btn-primary">{:__('Submit')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -166,8 +165,7 @@
|
|||
</div>
|
||||
<div class="form-footer">
|
||||
<div class="form-group" style="margin-bottom:0;">
|
||||
<label class="control-label col-xs-12 col-sm-3"></label>
|
||||
<div class="col-xs-12 col-sm-8">
|
||||
<div class="col-xs-12 col-sm-8 col-sm-offset-3">
|
||||
<button type="submit" class="btn btn-md btn-primary">{:__('Submit')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"homepage": "https://www.fastadmin.net",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"jquery": "^2.1.4",
|
||||
"jquery": "^3.7.0",
|
||||
"bootstrap": "^3.3.7",
|
||||
"font-awesome": "^4.6.1",
|
||||
"bootstrap-table": "fastadmin-bootstraptable#~1.11.5",
|
||||
|
|
@ -20,14 +20,14 @@
|
|||
"jquery-slimscroll": "~1.3.8",
|
||||
"jquery.cookie": "~1.4.1",
|
||||
"Sortable": "~1.10.0",
|
||||
"nice-validator": "~1.1.1",
|
||||
"nice-validator": "karsonzhang/fastadmin-nicevalidator#~1.1.6",
|
||||
"art-template": "~3.1.3",
|
||||
"bootstrap-daterangepicker": "~2.1.25",
|
||||
"fastadmin-citypicker": "~1.3.1",
|
||||
"fastadmin-cxselect": "~1.4.0",
|
||||
"fastadmin-dragsort": "~1.0.0",
|
||||
"fastadmin-addtabs": "~1.0.5",
|
||||
"fastadmin-selectpage": "~1.0.6",
|
||||
"fastadmin-addtabs": "~1.0.8",
|
||||
"fastadmin-selectpage": "~1.0.12",
|
||||
"fastadmin-layer": "~3.5.1",
|
||||
"bootstrap-slider": "*"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,17 +15,16 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2.0",
|
||||
"php": ">=7.4.0",
|
||||
"topthink/framework": "dev-master",
|
||||
"topthink/think-captcha": "^1.0",
|
||||
"topthink/think-captcha": "^1.0.9",
|
||||
"topthink/think-installer": "^1.0.14",
|
||||
"topthink/think-queue": "1.1.6",
|
||||
"topthink/think-helper": "^1.0.7",
|
||||
"karsonzhang/fastadmin-addons": "~1.3.2",
|
||||
"karsonzhang/fastadmin-addons": "~1.4.0",
|
||||
"overtrue/pinyin": "^3.0",
|
||||
"phpoffice/phpspreadsheet": "1.19",
|
||||
"phpoffice/phpspreadsheet": "^1.29.1",
|
||||
"overtrue/wechat": "^4.6",
|
||||
"nelexa/zip": "^3.3",
|
||||
"ext-json": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-pdo": "*",
|
||||
|
|
@ -33,12 +32,25 @@
|
|||
"txthinking/mailer": "^2.0"
|
||||
},
|
||||
"config": {
|
||||
"preferred-install": "dist"
|
||||
"preferred-install": "dist",
|
||||
"allow-plugins": {
|
||||
"topthink/think-installer": true,
|
||||
"easywechat-composer/easywechat-composer": true
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"addons\\": "addons/"
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://gitee.com/fastadminnet/framework.git"
|
||||
},
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://gitee.com/fastadminnet/think-captcha.git"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,10 +194,14 @@ class Date
|
|||
$time = $position ? $_timestamp : mktime(23, 59, 59, $month + $offset, self::days_in_month(date("m", $_timestamp), date("Y", $_timestamp)), $year);
|
||||
break;
|
||||
case 'quarter':
|
||||
$_month = date("m", mktime(0, 0, 0, (ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) * 3, $day, $year));
|
||||
$quarter = ceil(date('n', $baseTime) / 3) + $offset;
|
||||
$month = $quarter * 3;
|
||||
$offset_year = ceil($month/12) - 1;
|
||||
$year = $year + $offset_year;
|
||||
$month = $month - ($offset_year * 12);
|
||||
$time = $position ?
|
||||
mktime(0, 0, 0, 1 + ((ceil(date('n', $baseTime) / 3) + $offset) - 1) * 3, 1, $year) :
|
||||
mktime(23, 59, 59, (ceil(date('n', $baseTime) / 3) + $offset) * 3, self::days_in_month((ceil(date('n', $baseTime) / 3) + $offset) * 3, $year), $year);
|
||||
mktime(0, 0, 0, $month-2, 1, $year) :
|
||||
mktime(23, 59, 59, $month, self::days_in_month($month, $year), $year);
|
||||
break;
|
||||
case 'year':
|
||||
$time = $position ? mktime(0, 0, 0, 1, 1, $year + $offset) : mktime(23, 59, 59, 12, 31, $year + $offset);
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@ use ArrayAccess;
|
|||
* @method static string checkboxs(string $name, array $list = [], string $checked = null, array $options = []) 一组复选框
|
||||
* @method static string radio(string $name, string $value = null, string $checked = null, array $options = [])) 单个单选框
|
||||
* @method static string radios(string $name, array $list = [], string $checked = null, array $options = [])) 一组单选框
|
||||
* @method static string image(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传图片组件
|
||||
* @method static string images(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传图片组件(多图))
|
||||
* @method static string upload(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传文件组件
|
||||
* @method static string uploads(string $name = null, string $value, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传文件组件(多文件))
|
||||
* @method static string image(string $name = null, string $value = null, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传图片组件
|
||||
* @method static string images(string $name = null, string $value = null, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传图片组件(多图))
|
||||
* @method static string upload(string $name = null, string $value = null, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传文件组件
|
||||
* @method static string uploads(string $name = null, string $value = null, array $inputAttr = [], array $uploadAttr = [], array $chooseAttr = [], array $previewAttr = []) 上传文件组件(多文件))
|
||||
* @method static string button(string $value = null, array $options = []) 表单button
|
||||
*/
|
||||
class Form
|
||||
|
|
@ -870,7 +870,7 @@ EOD;
|
|||
$checked = is_array($checked) ? $checked : explode(',', $checked);
|
||||
foreach ($list as $k => $v) {
|
||||
$options['id'] = "{$name}-{$k}";
|
||||
$html[] = sprintf(Form::label("{$name}-{$k}", "%s {$v}"), Form::checkbox("{$name}[{$k}]", $k, in_array($k, $checked), $options));
|
||||
$html[] = sprintf(Form::label("{$name}-{$k}", "%s " . str_replace('%', '%%', $v)), Form::checkbox("{$name}[{$k}]", $k, in_array($k, $checked), $options));
|
||||
}
|
||||
return '<div class="checkbox">' . implode(' ', $html) . '</div>';
|
||||
}
|
||||
|
|
@ -913,7 +913,7 @@ EOD;
|
|||
$checked = is_array($checked) ? $checked : explode(',', $checked);
|
||||
foreach ($list as $k => $v) {
|
||||
$options['id'] = "{$name}-{$k}";
|
||||
$html[] = sprintf(Form::label("{$name}-{$k}", "%s {$v}"), Form::radio($name, $k, in_array($k, $checked), $options));
|
||||
$html[] = sprintf(Form::label("{$name}-{$k}", "%s " . str_replace('%', '%%', $v)), Form::radio($name, $k, in_array($k, $checked), $options));
|
||||
}
|
||||
return '<div class="radio">' . implode(' ', $html) . '</div>';
|
||||
}
|
||||
|
|
@ -1002,8 +1002,8 @@ EOD;
|
|||
{
|
||||
$domname = str_replace(['[', ']', '.'], '', $name);
|
||||
$options = [
|
||||
'id' => "plupload-{$domname}",
|
||||
'class' => "btn btn-danger plupload",
|
||||
'id' => "faupload-{$domname}",
|
||||
'class' => "btn btn-danger faupload",
|
||||
'data-input-id' => "c-{$domname}",
|
||||
];
|
||||
$upload = $uploadAttr === false ? false : true;
|
||||
|
|
@ -1023,7 +1023,7 @@ EOD;
|
|||
}
|
||||
$chooseBtn = $choose ? $this->button('<i class="fa fa-list"></i> ' . __('Choose'), array_merge($options, $chooseAttr)) : '';
|
||||
$previewAttrHtml = $this->attributes($previewAttr);
|
||||
$previewArea = $preview ? '<ul class="row list-inline plupload-preview" id="p-' . $domname . '" ' . $previewAttrHtml . '></ul>' : '';
|
||||
$previewArea = $preview ? '<ul class="row list-inline faupload-preview" id="p-' . $domname . '" ' . $previewAttrHtml . '></ul>' : '';
|
||||
$input = $this->text($name, $value, array_merge(['size' => 50, 'id' => "c-{$domname}"], $inputAttr));
|
||||
$html = <<<EOD
|
||||
<div class="input-group">
|
||||
|
|
|
|||
|
|
@ -60,15 +60,15 @@ class Http
|
|||
} else {
|
||||
$defaults[CURLOPT_CUSTOMREQUEST] = $method;
|
||||
}
|
||||
$defaults[CURLOPT_POSTFIELDS] = $params;
|
||||
$defaults[CURLOPT_POSTFIELDS] = is_array($params) && count(array_filter($params, 'is_array')) > 0 ? $query_string : $params;
|
||||
}
|
||||
|
||||
$defaults[CURLOPT_HEADER] = false;
|
||||
$defaults[CURLOPT_USERAGENT] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.98 Safari/537.36";
|
||||
$defaults[CURLOPT_FOLLOWLOCATION] = true;
|
||||
$defaults[CURLOPT_RETURNTRANSFER] = true;
|
||||
$defaults[CURLOPT_CONNECTTIMEOUT] = 3;
|
||||
$defaults[CURLOPT_TIMEOUT] = 3;
|
||||
$defaults[CURLOPT_CONNECTTIMEOUT] = 10;
|
||||
$defaults[CURLOPT_TIMEOUT] = 10;
|
||||
|
||||
// disable 100-continue
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
|
||||
|
|
@ -133,12 +133,12 @@ class Http
|
|||
}
|
||||
$parts['query'] = isset($parts['query']) && $parts['query'] ? '?' . $parts['query'] : '';
|
||||
//发送socket请求,获得连接句柄
|
||||
$fp = fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80, $errno, $errstr, 3);
|
||||
$fp = fsockopen($parts['host'], $parts['port'] ?? 80, $errno, $errstr, 10);
|
||||
if (!$fp) {
|
||||
return false;
|
||||
}
|
||||
//设置超时时间
|
||||
stream_set_timeout($fp, 3);
|
||||
stream_set_timeout($fp, 10);
|
||||
$out = "{$method} {$parts['path']}{$parts['query']} HTTP/1.1\r\n";
|
||||
$out .= "Host: {$parts['host']}\r\n";
|
||||
$out .= "Content-Type: application/x-www-form-urlencoded\r\n";
|
||||
|
|
|
|||
|
|
@ -89,67 +89,6 @@ class Random
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据数组元素的概率获得键名
|
||||
*
|
||||
* @param array $ps array('p1'=>20, 'p2'=>30, 'p3'=>50);
|
||||
* @param int $num 默认为1,即随机出来的数量
|
||||
* @param bool $unique 默认为true,即当num>1时,随机出的数量是否唯一
|
||||
* @return mixed 当num为1时返回键名,反之返回一维数组
|
||||
*/
|
||||
public static function lottery($ps, $num = 1, $unique = true)
|
||||
{
|
||||
if (!$ps) {
|
||||
return $num == 1 ? '' : [];
|
||||
}
|
||||
if ($num >= count($ps) && $unique) {
|
||||
$res = array_keys($ps);
|
||||
return $num == 1 ? $res[0] : $res;
|
||||
}
|
||||
$max_exp = 0;
|
||||
$res = [];
|
||||
foreach ($ps as $key => $value) {
|
||||
$value = substr($value, 0, stripos($value, ".") + 6);
|
||||
$exp = strlen(strchr($value, '.')) - 1;
|
||||
if ($exp > $max_exp) {
|
||||
$max_exp = $exp;
|
||||
}
|
||||
}
|
||||
$pow_exp = pow(10, $max_exp);
|
||||
if ($pow_exp > 1) {
|
||||
reset($ps);
|
||||
foreach ($ps as $key => $value) {
|
||||
$ps[$key] = $value * $pow_exp;
|
||||
}
|
||||
}
|
||||
$pro_sum = array_sum($ps);
|
||||
if ($pro_sum < 1) {
|
||||
return $num == 1 ? '' : [];
|
||||
}
|
||||
for ($i = 0; $i < $num; $i++) {
|
||||
$rand_num = mt_rand(1, $pro_sum);
|
||||
reset($ps);
|
||||
foreach ($ps as $key => $value) {
|
||||
if ($rand_num <= $value) {
|
||||
break;
|
||||
} else {
|
||||
$rand_num -= $value;
|
||||
}
|
||||
}
|
||||
if ($num == 1) {
|
||||
$res = $key;
|
||||
break;
|
||||
} else {
|
||||
$res[$i] = $key;
|
||||
}
|
||||
if ($unique) {
|
||||
$pro_sum -= $value;
|
||||
unset($ps[$key]);
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全球唯一标识
|
||||
* @return string
|
||||
|
|
|
|||
4860
public/api.html
4860
public/api.html
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue