Merge remote-tracking branch 'upstream/develop' into develop

pull/466/head
gtlee 2024-08-01 15:07:27 +08:00
commit d12f549396
15 changed files with 105 additions and 44 deletions

View File

@ -8,15 +8,15 @@
<title>{$config.title}</title> <title>{$config.title}</title>
<!-- Bootstrap Core CSS --> <!-- 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 --> <!-- 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 --> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="https://cdn.staticfile.org/html5shiv/3.7.3/html5shiv.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://cdn.staticfile.org/respond.js/1.4.2/respond.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]--> <![endif]-->
<style type="text/css"> <style type="text/css">
@ -401,10 +401,10 @@
</div> <!-- /container --> </div> <!-- /container -->
<!-- jQuery --> <!-- 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 --> <!-- 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"> <script type="text/javascript">
function syntaxHighlight(json) { function syntaxHighlight(json) {

View File

@ -435,16 +435,19 @@ class Crud extends Command
$modelName = $table = stripos($table, $prefix) === 0 ? substr($table, strlen($prefix)) : $table; $modelName = $table = stripos($table, $prefix) === 0 ? substr($table, strlen($prefix)) : $table;
$modelTableType = 'table'; $modelTableType = 'table';
$modelTableTypeName = $modelTableName = $modelName; $modelTableTypeName = $modelTableName = $modelName;
$modelTableInfo = $dbconnect->query("SHOW TABLE STATUS LIKE '{$modelTableName}'", [], true); $modelTableInfo = null;
if (!$modelTableInfo) { if (!$input->getOption('delete')) {
$modelTableType = 'name';
$modelTableName = $prefix . $modelName;
$modelTableInfo = $dbconnect->query("SHOW TABLE STATUS LIKE '{$modelTableName}'", [], true); $modelTableInfo = $dbconnect->query("SHOW TABLE STATUS LIKE '{$modelTableName}'", [], true);
if (!$modelTableInfo) { 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 = []; $relations = [];
//检查关联表 //检查关联表
@ -1081,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; $tableComment = mb_substr($tableComment, -1) == '表' ? mb_substr($tableComment, 0, -1) . '管理' : $tableComment;
$modelInit = ''; $modelInit = '';

View File

@ -93,7 +93,7 @@ class Install extends Command
*/ */
public function index() 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(); $this->request = Request::instance();
define('INSTALL_PATH', APP_PATH . 'admin' . DS . 'command' . DS . 'Install' . DS); define('INSTALL_PATH', APP_PATH . 'admin' . DS . 'command' . DS . 'Install' . DS);

View File

@ -254,7 +254,7 @@
</form> </form>
<!-- jQuery --> <!-- 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> <script>
$(function () { $(function () {

View File

@ -20,7 +20,7 @@ return [
'Dashboard' => '进入后台', 'Dashboard' => '进入后台',
'Go back' => '返回上一页', 'Go back' => '返回上一页',
'Install Successed' => '安装成功!', 'Install Successed' => '安装成功!',
'Security tips' => '温馨提示:请将以下后台登录入口添加到你的收藏夹,为了你的安全,不要泄漏或发送给他人!如有泄漏请及时修改!', 'Security tips' => '温馨提示:请将以下后台登录入口添加到你的收藏夹,为了你的站点安全,不要泄漏或发送给他人!如有泄漏请及时修改!',
'Please input correct database' => '请输入正确的数据库名', 'Please input correct database' => '请输入正确的数据库名',
'Please input correct username' => '用户名只能由3-30位数字、字母、下划线组合', 'Please input correct username' => '用户名只能由3-30位数字、字母、下划线组合',
'Please input correct password' => '密码长度必须在6-30位之间不能包含空格', 'Please input correct password' => '密码长度必须在6-30位之间不能包含空格',

View File

@ -2,7 +2,7 @@
return [ return [
'Url' => '链接', 'Url' => '链接',
'Userame' => '用户名', 'Username' => '用户名',
'Createtime' => '操作时间', 'Createtime' => '操作时间',
'Click to edit' => '点击编辑', 'Click to edit' => '点击编辑',
'Admin log' => '操作日志', 'Admin log' => '操作日志',

View File

@ -472,7 +472,7 @@ class Auth extends \fast\Auth
->column('name,pid'); ->column('name,pid');
$pidArr = array_unique(array_filter(array_column($ruleList, 'pid'))); $pidArr = array_unique(array_filter(array_column($ruleList, 'pid')));
foreach ($ruleList as $k => &$v) { foreach ($ruleList as $k => &$v) {
if (!in_array($v['name'], $userRule)) { if (!in_array(strtolower($v['name']), $userRule)) {
unset($ruleList[$k]); unset($ruleList[$k]);
continue; continue;
} }

View File

@ -28,12 +28,12 @@
<div class="content-wrapper tab-content tab-addtabs"> <div class="content-wrapper tab-content tab-addtabs">
{if $fixedmenu} {if $fixedmenu}
<div role="tabpanel" class="tab-pane {:$referermenu?'':'active'}" id="con_{$fixedmenu.id}"> <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> </div>
{/if} {/if}
{if $referermenu} {if $referermenu}
<div role="tabpanel" class="tab-pane active" id="con_{$referermenu.id}"> <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> </div>
{/if} {/if}
</div> </div>

View File

@ -34,8 +34,20 @@ class Ems extends Api
$event = $this->request->post("event"); $event = $this->request->post("event");
$event = $event ? $event : 'register'; $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 (config('fastadmin.user_api_captcha')) {
if (!preg_match("/^[a-z0-9]{4,6}\$/i", $captcha)) {
$this->error(__('验证码格式错误'));
}
if (!\think\Validate::is($captcha, 'captcha')) { if (!\think\Validate::is($captcha, 'captcha')) {
$this->error("验证码不正确"); $this->error("验证码不正确");
} }
@ -87,6 +99,17 @@ class Ems extends Api
$event = $event ? $event : 'register'; $event = $event ? $event : 'register';
$captcha = $this->request->post("captcha"); $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) { if ($event) {
$userinfo = User::getByEmail($email); $userinfo = User::getByEmail($email);
if ($event == 'register' && $userinfo) { if ($event == 'register' && $userinfo) {

View File

@ -241,6 +241,27 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie']
Layer.close(index); Layer.close(index);
}); });
return false; return false;
} else if (ret && ret.code === -3) {
//插件目录发现影响全局的文件
Layer.open({
content: Template("conflicttpl", ret.data),
shade: 0.8,
area: area,
title: __('Warning'),
btn: [__('Continue install'), __('Cancel')],
end: function () {
},
yes: function (index) {
up.removeFile(file);
file.force = true;
up.uploadFile(file);
Layer.close(index);
}
});
} else {
Layer.alert(ret.msg, {title: __('Warning'), icon: 0});
} }
}); });

View File

@ -167,7 +167,7 @@ define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefin
{ {
field: 'operate', title: __('Operate'), width: 85, events: { field: 'operate', title: __('Operate'), width: 85, events: {
'click .btn-chooseone': function (e, value, row, index) { 'click .btn-chooseone': function (e, value, row, index) {
Fast.api.close({url: row.url, multiple: multiple}); Fast.api.close($.extend({multiple: multiple}, row));
}, },
}, formatter: function () { }, formatter: function () {
return '<a href="javascript:;" class="btn btn-danger btn-chooseone btn-xs"><i class="fa fa-check"></i> ' + __('Choose') + '</a>'; return '<a href="javascript:;" class="btn btn-danger btn-chooseone btn-xs"><i class="fa fa-check"></i> ' + __('Choose') + '</a>';

View File

@ -138,7 +138,7 @@ require(['jquery', 'bootstrap'], function ($, undefined) {
window.Config = Config; window.Config = Config;
// 配置语言包的路径 // 配置语言包的路径
var paths = {}; var paths = {};
paths['lang'] = Config.moduleurl + '/ajax/lang?callback=define&controllername=' + Config.controllername + '&lang=' + Config.language + '&v=' + Config.site.version; paths['lang'] = Config.moduleurl + '/ajax/lang?callback=define&controllername=' + Config.controllername + '&lang=' + Config.language;
// 避免目录冲突 // 避免目录冲突
paths['backend/'] = 'backend/'; paths['backend/'] = 'backend/';
// 如果是英文,则移除默认的定义 // 如果是英文,则移除默认的定义

View File

@ -265,7 +265,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
var url = $(this).data("url") ? $(this).data("url") : (typeof Backend !== 'undefined' ? "general/attachment/select" : "user/attachment"); var url = $(this).data("url") ? $(this).data("url") : (typeof Backend !== 'undefined' ? "general/attachment/select" : "user/attachment");
parent.Fast.api.open(url + "?element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mimetype=" + mimetype + "&admin_id=" + admin_id + "&user_id=" + user_id, __('Choose'), { parent.Fast.api.open(url + "?element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mimetype=" + mimetype + "&admin_id=" + admin_id + "&user_id=" + user_id, __('Choose'), {
callback: function (data) { callback: function (data) {
var button = $("#" + $(that).attr("id")); var button = $(that);
var maxcount = $(button).data("maxcount"); var maxcount = $(button).data("maxcount");
var input_id = $(button).data("input-id") ? $(button).data("input-id") : ""; var input_id = $(button).data("input-id") ? $(button).data("input-id") : "";
maxcount = typeof maxcount !== "undefined" ? maxcount : 0; maxcount = typeof maxcount !== "undefined" ? maxcount : 0;
@ -295,6 +295,9 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
var url = Config.upload.fullmode ? Fast.api.cdnurl(data.url) : data.url; var url = Config.upload.fullmode ? Fast.api.cdnurl(data.url) : data.url;
$("#" + input_id).val(url).trigger("change").trigger("validate"); $("#" + input_id).val(url).trigger("change").trigger("validate");
} }
// 触发选择文件自定义事件
button.trigger("fa.event.selectedfile", data);
} }
}); });
return false; return false;
@ -510,7 +513,11 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
autocomplete: function (form) { autocomplete: function (form) {
if ($("[data-role='autocomplete']", form).length > 0) { if ($("[data-role='autocomplete']", form).length > 0) {
require(['autocomplete'], function () { require(['autocomplete'], function () {
$("[data-role='autocomplete']").autocomplete(); $("[data-role='autocomplete']").autocomplete({
onSelect: function () {
$(this).trigger('change').trigger('validate');
}
});
}); });
} }
}, },

View File

@ -138,7 +138,7 @@ require(['jquery', 'bootstrap'], function ($, undefined) {
window.Config = Config; window.Config = Config;
// 配置语言包的路径 // 配置语言包的路径
var paths = {}; var paths = {};
paths['lang'] = Config.moduleurl + '/ajax/lang?callback=define&controllername=' + Config.controllername + '&lang=' + Config.language + '&v=' + Config.site.version; paths['lang'] = Config.moduleurl + '/ajax/lang?callback=define&controllername=' + Config.controllername + '&lang=' + Config.language;
// 避免目录冲突 // 避免目录冲突
paths['frontend/'] = 'frontend/'; paths['frontend/'] = 'frontend/';
// 如果是英文,则移除默认的定义 // 如果是英文,则移除默认的定义

View File

@ -469,8 +469,10 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
toolbar.on('click', Table.config.delbtn, function () { toolbar.on('click', Table.config.delbtn, function () {
var that = this; var that = this;
var ids = Table.api.selectedids(table); var ids = Table.api.selectedids(table);
var confirm = $(this).data("confirm");
var message = typeof confirm === 'function' ? confirm.call(this, ids) : (typeof confirm !== 'undefined' ? __(confirm, ids.length) : '');
Layer.confirm( Layer.confirm(
__('Are you sure you want to delete the %s selected item?', ids.length), message || __('Are you sure you want to delete the %s selected item?', ids.length),
{icon: 3, title: __('Warning'), offset: 0, shadeClose: true, btn: [__('OK'), __('Cancel')]}, {icon: 3, title: __('Warning'), offset: 0, shadeClose: true, btn: [__('OK'), __('Cancel')]},
function (index) { function (index) {
Table.api.multi("del", ids, table, that); Table.api.multi("del", ids, table, that);
@ -692,7 +694,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
top = left = undefined; top = left = undefined;
} }
Layer.confirm( Layer.confirm(
__('Are you sure you want to delete this item?'), $(that).data("confirm") || __('Are you sure you want to delete this item?'),
{icon: 3, title: __('Warning'), offset: [top, left], shadeClose: true, btn: [__('OK'), __('Cancel')]}, {icon: 3, title: __('Warning'), offset: [top, left], shadeClose: true, btn: [__('OK'), __('Cancel')]},
function (index) { function (index) {
var table = $(that).closest('table'); var table = $(that).closest('table');
@ -753,7 +755,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
return html.join(' '); return html.join(' ');
}, },
file: function (value, row, index) { file: function (value, row, index) {
Table.api.formatter.files.call(this, value, row, index); return Table.api.formatter.files.call(this, value, row, index);
}, },
files: function (value, row, index) { files: function (value, row, index) {
value = value == null || value.length === 0 ? '' : value.toString(); value = value == null || value.length === 0 ? '' : value.toString();
@ -915,23 +917,28 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
var table = this.table; var table = this.table;
// 操作配置 // 操作配置
var options = table ? table.bootstrapTable('getOptions') : {}; var options = table ? table.bootstrapTable('getOptions') : {};
// 默认按钮组 var buttons = [];
var buttons = $.extend([], this.buttons || []); var existBtn = [];
// 所有按钮名称 var defaultBtn = ['dragsort', 'edit', 'del'];
var names = []; var tempButton = $.extend({}, Table.button, {});
buttons.forEach(function (item) { (this.buttons || []).forEach(function (item, index) {
names.push(item.name); if (defaultBtn.indexOf(item.name) > -1) {
$.extend(tempButton[item.name], item, Table.button[item.name], item.name === 'edit' ? {url: options.extend.edit_url} : {});
if (item.keep) {
if (options.extend[item.name + "_url"] !== '') {
buttons.push(tempButton[item.name]);
}
existBtn.push(item.name);
}
} else {
buttons.push(item);
}
});
defaultBtn.forEach(function (value, index) {
if (existBtn.indexOf(value) === -1) {
buttons.push(tempButton[value]);
}
}); });
if (options.extend.dragsort_url !== '' && names.indexOf('dragsort') === -1) {
buttons.push(Table.button.dragsort);
}
if (options.extend.edit_url !== '' && names.indexOf('edit') === -1) {
Table.button.edit.url = options.extend.edit_url;
buttons.push(Table.button.edit);
}
if (options.extend.del_url !== '' && names.indexOf('del') === -1) {
buttons.push(Table.button.del);
}
return Table.api.buttonlink(this, buttons, value, row, index, 'operate'); return Table.api.buttonlink(this, buttons, value, row, index, 'operate');
} }
, ,