Pre Merge pull request !493 from amplam/1.x

pull/493/MERGE
amplam 2025-04-25 03:01:03 +00:00 committed by Gitee
commit da98ed1bd6
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
92 changed files with 13026 additions and 39978 deletions

14
.bowerrc 100644
View File

@ -0,0 +1,14 @@
{
"directory": "public/assets/libs",
"ignoredDependencies": [
"es6-promise",
"file-saver",
"html2canvas",
"jspdf",
"jspdf-autotable",
"pdfmake"
],
"scripts":{
"postinstall": "node bower-cleanup.js"
}
}

1
.gitignore vendored
View File

@ -6,6 +6,7 @@
/public/assets/libs/
/public/assets/addons/*
/public/uploads/*
.DS_Store
.idea
composer.lock
*.log

4
.npmrc 100644
View File

@ -0,0 +1,4 @@
# 使用自定义镜像源
registry=http://mirrors.tencent.com/npm/
#关闭SSL验证
strict-ssl=false

View File

@ -14,7 +14,7 @@ module.exports = function (grunt) {
compile: {
options: type === 'js' ? {
optimizeCss: "standard",
optimize: "none", //可使用uglify|closure|none
optimize: "uglify", //可使用uglify|closure|none
preserveLicenseComments: true,
removeCombined: false,
baseUrl: "./public/assets/js/", //JS文件所在的基础目录
@ -23,7 +23,7 @@ module.exports = function (grunt) {
} : {
optimizeCss: "default",
optimize: "uglify", //可使用uglify|closure|none
cssIn: "./public/assets/css/" + module + ".css", //JS文件所在的基础目录
cssIn: "./public/assets/css/" + module + ".css", //CSS文件所在的基础目录
out: "./public/assets/css/" + module + ".min.css" //目标文件
}
}
@ -110,11 +110,25 @@ module.exports = function (grunt) {
let dists = mainPackage.dists || [];
let files = [];
// 兼容旧版本bower使用的目录
let specialKey = {
'fastadmin-bootstraptable': 'bootstrap-table',
'sortablejs': 'Sortable',
'tableexport.jquery.plugin': 'tableExport.jquery.plugin',
};
Object.keys(dists).forEach(key => {
let src = ["**/*LICENSE*", "**/*license*"];
src = src.concat(Array.isArray(dists[key]) ? dists[key] : [dists[key]]);
files.push({expand: true, cwd: nodeModulesDir + "/" + key, src: src, dest: 'public/assets/libs/' + key + "/"});
files.push({expand: true, cwd: nodeModulesDir + "/" + key, src: src, dest: 'public/assets/libs/' + (specialKey[key] || key) + "/"});
});
// 兼容bower历史路径文件
files = [...files,
{src: nodeModulesDir + "/toastr/build/toastr.min.css", dest: "public/assets/libs/toastr/toastr.min.css"},
{src: nodeModulesDir + "/bootstrap-slider/dist/css/bootstrap-slider.css", dest: "public/assets/libs/bootstrap-slider/slider.css"},
{expand: true, cwd: nodeModulesDir + "/bootstrap-slider/dist", src: ["*.js"], dest: "public/assets/libs/bootstrap-slider/"}
]
grunt.config.set('copy.main.files', files);
grunt.task.run("copy:main");
});

View File

@ -24,11 +24,9 @@ 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、又拍云)功能,支持云储存分片上传
* 无缝整合第三方云存储(七牛云、阿里云OSS、腾讯云存储、又拍云)功能,支持云储存分片上传
* 第三方富文本编辑器支持(Summernote、百度编辑器)
* 第三方登录(QQ、微信、微博)整合
* 第三方支付(微信、支付宝)无缝整合微信支持PC端扫码支付
@ -57,9 +55,9 @@ https://demo.fastadmin.net
问答社区: https://ask.fastadmin.net
Github: https://github.com/karsonzhang/fastadmin
Github: https://github.com/fastadminnet/fastadmin
Gitee: https://gitee.com/karson/fastadmin
Gitee: https://gitee.com/fastadminnet/fastadmin
## 特别鸣谢

View File

@ -98,13 +98,19 @@ class Api extends Command
foreach ($files as $name => $file) {
if (!$file->isDir() && $file->getExtension() == 'php') {
$filePath = $file->getRealPath();
$classes[] = $this->getClassFromFile($filePath);
$className = $this->getClassFromFile($filePath);
if ($className) {
$classes[] = $className;
}
}
}
} else {
foreach ($controller as $index => $item) {
$filePath = $moduleDir . Config::get('url_controller_layer') . DS . $item . '.php';
$classes[] = $this->getClassFromFile($filePath);
$className = $this->getClassFromFile($filePath);
if ($className) {
$classes[] = $className;
}
}
}
@ -183,7 +189,7 @@ class Api extends Command
}
}
}
return $namespace . '\\' . $class;
$className = $namespace . '\\' . $class;
return preg_match('/([a-z0-9_\\]+)([a-z0-9_]+)$/i', $className) ? $className : '';
}
}

View File

@ -90,14 +90,15 @@ class Builder
$typeArr = [
'integer' => 'number',
'file' => 'file',
'file' => 'file',
];
$paramslist = array();
foreach ($docs['ApiParams'] as $params) {
$inputtype = $params['type'] && isset($typeArr[$params['type']]) ? $typeArr[$params['type']] : ($params['name'] == 'password' ? 'password' : 'text');
$type = strtolower($params['type'] ?? 'string');
$inputtype = $typeArr[$type] ?? ($params['name'] == 'password' ? 'password' : 'text');
$tr = array(
'name' => $params['name'],
'type' => $params['type'] ?? 'string',
'type' => $type,
'inputtype' => $inputtype,
'sample' => $params['sample'] ?? '',
'required' => $params['required'] ?? true,
@ -162,7 +163,7 @@ class Builder
'OPTIONS' => 'label-info'
);
return isset($labes[$method]) ? $labes[$method] : $labes['GET'];
return $labes[$method] ?? $labes['GET'];
}
public function parse()
@ -230,7 +231,7 @@ class Builder
foreach ($docsList as $index => &$methods) {
$methodSectorArr = [];
foreach ($methods as $name => $method) {
$methodSectorArr[$name] = isset($method['weigh']) ? $method['weigh'] : 0;
$methodSectorArr[$name] = $method['weigh'] ?? 0;
}
arsort($methodSectorArr);
$methods = array_merge(array_flip(array_keys($methodSectorArr)), $methods);
@ -253,7 +254,6 @@ class Builder
public function render($template, $vars = [])
{
$docsList = $this->parse();
return $this->view->display(file_get_contents($template), array_merge($vars, ['docsList' => $docsList]));
}
}

View File

@ -154,8 +154,8 @@
<div id="sidebar">
<div class="list-group panel">
{foreach name="docsList" id="docs"}
<a href="#{$key}" class="list-group-item" data-toggle="collapse" data-parent="#sidebar">{$key} <i class="fa fa-caret-down"></i></a>
<div class="child collapse" id="{$key}">
<a href="#{$key|md5|substr=0,8}" class="list-group-item" data-toggle="collapse" data-parent="#sidebar">{$key} <i class="fa fa-caret-down"></i></a>
<div class="child collapse" id="{$key|md5|substr=0,8}">
{foreach name="docs" id="api" }
<a href="javascript:;" data-id="{$api.id}" class="list-group-item">{$api.title}
<span class="tag">

View File

@ -1,6 +1,6 @@
/*
FastAdmin Install SQL
Date: 2023-06-07 15:17:57
Date: 2024-09-03 15:05:25
*/
SET FOREIGN_KEY_CHECKS = 0;
@ -32,7 +32,7 @@ CREATE TABLE `fa_admin` (
-- 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;
-- ----------------------------
@ -81,8 +81,8 @@ CREATE TABLE `fa_attachment` (
`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 '文件名称',
@ -452,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 '创建时间',
@ -469,7 +470,7 @@ CREATE TABLE `fa_user` (
-- Records of fa_user
-- ----------------------------
BEGIN;
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, '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;
-- ----------------------------

File diff suppressed because one or more lines are too long

View File

@ -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;
@ -46,9 +47,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]);
}
@ -162,18 +174,18 @@ class Ajax extends Backend
$weighdata[$v[$prikey]] = $v[$field];
}
$position = array_search($changeid, $ids);
$desc_id = isset($sour[$position]) ? $sour[$position] : end($sour); //移动到目标的ID值,取出所处改变前位置的值
$desc_id = $sour[$position] ?? end($sour); //移动到目标的ID值,取出所处改变前位置的值
$sour_id = $changeid;
$weighids = array();
$weighids = [];
$temp = array_values(array_diff_assoc($ids, $sour));
foreach ($temp as $m => $n) {
if ($n == $sour_id) {
$offset = $desc_id;
} else {
if ($sour_id == $temp[0]) {
$offset = isset($temp[$m + 1]) ? $temp[$m + 1] : $sour_id;
$offset = $temp[$m + 1] ?? $sour_id;
} else {
$offset = isset($temp[$m - 1]) ? $temp[$m - 1] : $sour_id;
$offset = $temp[$m - 1] ?? $sour_id;
}
}
if (!isset($weighdata[$offset])) {

View File

@ -32,7 +32,7 @@ class Index extends Backend
*/
public function index()
{
$cookieArr = ['adminskin' => "/^skin\-([a-z\-]+)\$/i", 'simplenav' => "/^(0|1)\$/", 'multiplenav' => "/^(0|1)\$/", 'multipletab' => "/^(0|1)\$/", 'show_submenu' => "/^(0|1)\$/"];
$cookieArr = ['adminskin' => "/^skin\-([a-z\-]+)\$/i", 'multiplenav' => "/^(0|1)\$/", 'multipletab' => "/^(0|1)\$/", 'show_submenu' => "/^(0|1)\$/"];
foreach ($cookieArr as $key => $regex) {
$cookieValue = $this->request->cookie($key);
if (!is_null($cookieValue) && preg_match($regex, $cookieValue)) {

View File

@ -18,21 +18,13 @@ class Adminlog extends Backend
* @var \app\admin\model\AdminLog
*/
protected $model = null;
protected $childrenGroupIds = [];
protected $childrenAdminIds = [];
public function _initialize()
{
parent::_initialize();
$this->model = model('AdminLog');
$this->childrenAdminIds = $this->auth->getChildrenAdminIds(true);
$this->childrenGroupIds = $this->auth->getChildrenGroupIds(true);
$groupName = AuthGroup::where('id', 'in', $this->childrenGroupIds)
->column('id,name');
$this->view->assign('groupdata', $groupName);
}
/**

View File

@ -82,7 +82,6 @@ class Rule extends Backend
if ($result === false) {
$this->error($this->model->getError());
}
Cache::rm('__menu__');
$this->success();
}
$this->error();
@ -124,7 +123,6 @@ class Rule extends Backend
if ($result === false) {
$this->error($row->getError());
}
Cache::rm('__menu__');
$this->success();
}
$this->error();

View File

@ -16,8 +16,6 @@ return [
'Toggle between slide over content and push content effects' => '切换右侧操作栏覆盖或独占',
'Toggle Right Sidebar Skin' => '切换右侧操作栏背景',
'Toggle between dark and light skins for the right sidebar' => '将右侧操作栏背景亮色或深色切换',
'Simple nav' => '简洁导航模式',
'Simple nav tips' => '启用后顶部导航将不再显示,同时每次点击菜单都会刷新右侧内容',
'Multiple nav' => '多级菜单导航',
'Toggle the top menu state (multiple or single)' => '切换顶部菜单为多级菜单导航模式',
'Multiple tab' => '多选项卡',

View File

@ -327,10 +327,7 @@ class Auth extends \fast\Auth
{
//取出当前管理员所有的分组
$groups = $this->getGroups();
$groupIds = [];
foreach ($groups as $k => $v) {
$groupIds[] = $v['id'];
}
$groupIds = array_column($groups, 'id');
$originGroupIds = $groupIds;
foreach ($groups as $k => $v) {
if (in_array($v['pid'], $originGroupIds)) {
@ -371,12 +368,8 @@ class Auth extends \fast\Auth
$childrenAdminIds = [];
if (!$this->isSuperAdmin()) {
$groupIds = $this->getChildrenGroupIds(false);
$authGroupList = \app\admin\model\AuthGroupAccess::field('uid,group_id')
->where('group_id', 'in', $groupIds)
->select();
foreach ($authGroupList as $k => $v) {
$childrenAdminIds[] = $v['uid'];
}
$childrenAdminIds = \app\admin\model\AuthGroupAccess::where('group_id', 'in', $groupIds)
->column('uid');
} else {
//超级管理员拥有所有人的权限
$childrenAdminIds = Admin::column('id');

View File

@ -2,9 +2,9 @@
{if $addon.tips && $addon.tips.value}
<div class="alert {$addon.tips.extend|default='alert-info-light'}" style="margin-bottom:10px;">
{if $addon.tips.title}
<b>{$addon.tips.title}</b><br>
<b>{$addon.tips.title|htmlentities}</b><br>
{/if}
{$addon.tips.value}
{$addon.tips.value|htmlentities}
</div>
{/if}
@ -14,7 +14,7 @@
<ul class="nav nav-tabs nav-group">
<li class="active"><a href="#all" data-toggle="tab">全部</a></li>
{foreach name="groupList" id="tab"}
<li><a href="#tab-{$key}" title="{$tab}" data-toggle="tab">{$tab}</a></li>
<li><a href="#tab-{$key|htmlentities}" title="{$tab|htmlentities}" data-toggle="tab">{$tab|htmlentities}</a></li>
{/foreach}
</ul>
</div>
@ -23,99 +23,99 @@
<div class="panel-body no-padding">
<div id="myTabContent" class="tab-content">
{foreach name="groupList" id="group" key="groupName"}
<div class="tab-pane fade active in" id="tab-{$groupName}">
<div class="tab-pane fade active in" id="tab-{$groupName|htmlentities}">
<table class="table table-striped table-config mb-0">
<tbody>
{foreach name="$addon.config" id="item"}
{if ((!isset($item['group']) || $item['group']=='') && $groupName=='other') || (isset($item['group']) && $item['group']==$group)}
<tr data-favisible="{$item.visible|default=''|htmlentities}" data-name="{$item.name}" class="{if $item.visible??''}hidden{/if}">
<td width="15%">{$item.title}</td>
<tr data-favisible="{$item.visible|default=''|htmlentities}" data-name="{$item.name|htmlentities}" class="{if $item.visible??''}hidden{/if}">
<td width="15%">{$item.title|htmlentities}</td>
<td>
<div class="row">
<div class="col-sm-8 col-xs-12">
{switch $item.type}
{case string}
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}"/>
<input {$item.extend} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule|htmlentities}" data-tip="{$item.tip|htmlentities}"/>
{/case}
{case password}
<input {$item.extend} type="password" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}"/>
<input {$item.extend} type="password" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule|htmlentities}" data-tip="{$item.tip|htmlentities}"/>
{/case}
{case text}
<textarea {$item.extend} name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
<textarea {$item.extend} name="row[{$item.name|htmlentities}]" class="form-control" data-rule="{$item.rule|htmlentities}" rows="5" data-tip="{$item.tip|htmlentities}">{$item.value|htmlentities}</textarea>
{/case}
{case array}
<dl class="fieldlist" data-name="row[{$item.name}]">
<dl class="fieldlist" data-name="row[{$item.name|htmlentities}]">
<dd>
<ins>{:__('Array key')}</ins>
<ins>{:__('Array value')}</ins>
</dd>
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
<textarea name="row[{$item.name}]" cols="30" rows="5" class="hide">{$item.value|json_encode|htmlentities}</textarea>
<textarea name="row[{$item.name|htmlentities}]" cols="30" rows="5" class="hide">{$item.value|json_encode|htmlentities}</textarea>
</dl>
{/case}
{case date}
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case time}
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case datetime}
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case number}
<input {$item.extend} type="number" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend} type="number" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case checkbox}
{foreach name="item.content" item="vo"}
<label for="row[{$item.name}][]-{$key}"><input id="row[{$item.name}][]-{$key}" name="row[{$item.name}][]" type="checkbox" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value" }checked{/in} /> {$vo}</label>
<label for="row[{$item.name|htmlentities}][]-{$key|htmlentities}"><input id="row[{$item.name|htmlentities}][]-{$key|htmlentities}" name="row[{$item.name|htmlentities}][]" type="checkbox" value="{$key|htmlentities}" data-tip="{$item.tip|htmlentities}" {in name="key" value="$item.value" }checked{/in} /> {$vo|htmlentities}</label>
{/foreach}
<span class="msg-box n-right" for="row[{$item.name}]"></span>
<span class="msg-box n-right" for="row[{$item.name|htmlentities}]"></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>
<label for="row[{$item.name|htmlentities}]-{$key|htmlentities}"><input id="row[{$item.name|htmlentities}]-{$key|htmlentities}" name="row[{$item.name|htmlentities}]" type="radio" value="{$key|htmlentities}" data-tip="{$item.tip|htmlentities}" {in name="key" value="$item.value" }checked{/in} /> {$vo|htmlentities}</label>
{/foreach}
<span class="msg-box n-right" for="row[{$item.name}]"></span>
<span class="msg-box n-right" for="row[{$item.name|htmlentities}]"></span>
{/case}
{case value="select" break="0"}{/case}
{case value="selects"}
<select {$item.extend} name="row[{$item.name}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip}" {$item.type=='selects'?'multiple':''}>
<select {$item.extend} name="row[{$item.name|htmlentities}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip|htmlentities}" {$item.type=='selects'?'multiple':''}>
{foreach name="item.content" item="vo"}
<option value="{$key}" {in name="key" value="$item.value" }selected{/in}>{$vo}</option>
<option value="{$key|htmlentities}" {in name="key" value="$item.value" }selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
{/case}
{case value="image" break="0"}{/case}
{case value="images"}
<div class="form-inline">
<input id="c-{$item.name}" class="form-control" size="28" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
<span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<ul class="row list-inline plupload-preview" id="p-{$item.name}"></ul>
<span class="msg-box n-right" for="c-{$item.name}"></span>
<input id="c-{$item.name|htmlentities}" class="form-control" size="28" name="row[{$item.name|htmlentities}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip|htmlentities}">
<span><button type="button" id="plupload-{$item.name|htmlentities}" class="btn btn-danger plupload" data-input-id="c-{$item.name|htmlentities}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name|htmlentities}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name|htmlentities}" class="btn btn-primary fachoose" data-input-id="c-{$item.name|htmlentities}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<ul class="row list-inline plupload-preview" id="p-{$item.name|htmlentities}"></ul>
<span class="msg-box n-right" for="c-{$item.name|htmlentities}"></span>
</div>
{/case}
{case value="file" break="0"}{/case}
{case value="files"}
<div class="form-inline">
<input id="c-{$item.name}" class="form-control" size="28" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
<span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<span class="msg-box n-right" for="c-{$item.name}"></span>
<input id="c-{$item.name|htmlentities}" class="form-control" size="28" name="row[{$item.name|htmlentities}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip|htmlentities}">
<span><button type="button" id="plupload-{$item.name|htmlentities}" class="btn btn-danger plupload" data-input-id="c-{$item.name|htmlentities}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name|htmlentities}" class="btn btn-primary fachoose" data-input-id="c-{$item.name|htmlentities}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<span class="msg-box n-right" for="c-{$item.name|htmlentities}"></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">
<input id="c-{$item.name|htmlentities}" name="row[{$item.name|htmlentities}]" type="hidden" value="{:$item.value?1:0}">
<a href="javascript:;" data-toggle="switcher" class="btn-switcher" data-input-id="c-{$item.name|htmlentities}" 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>
<label for="row[{$item.name|htmlentities}]-yes"><input id="row[{$item.name|htmlentities}]-yes" name="row[{$item.name|htmlentities}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip|htmlentities}" /> {:__('Yes')}</label>
<label for="row[{$item.name|htmlentities}]-no"><input id="row[{$item.name|htmlentities}]-no" name="row[{$item.name|htmlentities}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip|htmlentities}" /> {:__('No')}</label>
{/case}
{default /}{$item.value}
{default /}{$item.value|htmlentities}
{/switch}
</div>
<div class="col-sm-4"></div>

View File

@ -136,7 +136,7 @@
<div class="form-group">
<label class="control-label">{:__('Version')}</label>
<input type="hidden" class="operate" data-name="faversion" value="="/>
<input class="form-control" name="faversion" type="text" value="{$Think.config.fastadmin.version}">
<input class="form-control" name="faversion" type="text" value="{$Think.config.fastadmin.version|htmlentities}">
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-3">

View File

@ -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">

View File

@ -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">

View File

@ -10,7 +10,7 @@
<select id="c-type" data-rule="required" class="form-control selectpicker" name="row[type]">
{foreach name="typeList" item="vo"}
<option value="{$key}" {in name="key" value=""}selected{/in}>{$vo}</option>
<option value="{$key|htmlentities}" {in name="key" value=""}selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
@ -22,7 +22,7 @@
<select id="c-pid" data-rule="required" class="form-control selectpicker" name="row[pid]">
{foreach name="parentList" item="vo"}
<option data-type="{$vo.type}" value="{$key}" {in name="key" value=""}selected{/in}>{$vo.name}</option>
<option data-type="{$vo.type|htmlentities}" value="{$key|htmlentities}" {in name="key" value=""}selected{/in}>{$vo.name|htmlentities}</option>
{/foreach}
</select>
@ -46,7 +46,7 @@
<select id="c-flag" class="form-control selectpicker" multiple="" name="row[flag][]">
{foreach name="flagList" item="vo"}
<option value="{$key}" {in name="key" value=""}selected{/in}>{$vo}</option>
<option value="{$key|htmlentities}" {in name="key" value=""}selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>

View File

@ -6,7 +6,7 @@
<select id="c-type" data-rule="required" class="form-control selectpicker" name="row[type]">
{foreach name="typeList" item="vo"}
<option value="{$key}" {in name="key" value="$row.type"}selected{/in}>{$vo}</option>
<option value="{$key|htmlentities}" {in name="key" value="$row.type"}selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
@ -18,7 +18,7 @@
<select id="c-pid" data-rule="required" class="form-control selectpicker" name="row[pid]">
{foreach name="parentList" item="vo"}
<option data-type="{$vo.type}" class="{:$vo.type==$row.type||$vo.type=='all'?'':'hide'}" value="{$key}" {in name="key" value="$row.pid"}selected{/in}>{$vo.name}</option>
<option data-type="{$vo.type|htmlentities}" class="{:$vo.type==$row.type||$vo.type=='all'?'':'hide'}" value="{$key|htmlentities}" {in name="key" value="$row.pid"}selected{/in}>{$vo.name|htmlentities}</option>
{/foreach}
</select>
@ -42,7 +42,7 @@
<select id="c-flag" class="form-control selectpicker" multiple="" name="row[flag][]">
{foreach name="flagList" item="vo"}
<option value="{$key}" {in name="key" value="$row.flag"}selected{/in}>{$vo}</option>
<option value="{$key|htmlentities}" {in name="key" value="$row.flag"}selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
@ -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">

View File

@ -4,7 +4,7 @@
<ul class="nav nav-tabs">
<li class="active"><a href="#all" data-toggle="tab">{:__('All')}</a></li>
{foreach name="typeList" item="vo"}
<li><a href="#{$key}" data-toggle="tab">{$vo}</a></li>
<li><a href="#{$key|htmlentities}" data-toggle="tab">{$vo|htmlentities}</a></li>
{/foreach}
</ul>

View File

@ -30,9 +30,8 @@
<!-- Home tab content -->
<div class="tab-pane active" id="control-sidebar-setting-tab">
<h4 class="control-sidebar-heading">{:__('Layout Options')}</h4>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-config="simplenav" {if $Think.config.fastadmin.simplenav}checked{/if} class="pull-right"> {:__('Simple Nav')}</label><p>{:__("Simple nav tips")}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-config="multiplenav" {if $Think.config.fastadmin.simplenav}disabled{/if} {if $Think.config.fastadmin.multiplenav}checked{/if} class="pull-right"> {:__('Multiple Nav')}</label><p>{:__("Toggle the top menu state (multiple or single)")}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-config="multipletab" {if !$Think.config.fastadmin.multiplenav}disabled{/if} {if $Think.config.fastadmin.multipletab}checked{/if} class="pull-right"> {:__('Multiple Tab')}</label><p>{:__("Always show multiple tab when multiple nav is set")}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-config="multiplenav" {if $Think.config.fastadmin.multiplenav}checked{/if} class="pull-right"> {:__('Multiple Nav')}</label><p>{:__("Toggle the top menu state (multiple or single)")}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-config="multipletab" {if $Think.config.fastadmin.multipletab}checked{/if} class="pull-right"> {:__('Multiple Tab')}</label><p>{:__("Always show multiple tab when multiple nav is set")}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-layout="sidebar-collapse" class="pull-right"> {:__('Toggle Sidebar')}</label><p>{:__("Toggle the left sidebar's state (open or collapse)")}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-enable="expandOnHover" class="pull-right"> {:__('Sidebar Expand on Hover')}</label><p>{:__('Let the sidebar mini expand on hover')}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-menu="show-submenu" class="pull-right"> {:__('Show sub menu')}</label><p>{:__('Always show sub menu')}</p></div>

View File

@ -18,9 +18,7 @@
<!--如果不想在顶部显示角标,则给ul加上disable-top-badge类即可-->
<ul class="nav nav-tabs nav-addtabs disable-top-badge hidden-xs" role="tablist">
{if !$Think.config.fastadmin.simplenav}
{$navlist}
{/if}
</ul>
<div class="navbar-custom-menu">
@ -119,10 +117,10 @@
<div id="secondnav">
<ul class="nav nav-tabs nav-addtabs disable-top-badge" role="tablist">
{if $fixedmenu}
<li role="presentation" id="tab_{$fixedmenu.id}" class="{:$referermenu?'':'active'}"><a href="#con_{$fixedmenu.id}" node-id="{$fixedmenu.id}" aria-controls="{$fixedmenu.id}" role="tab" data-toggle="tab"><i class="fa fa-dashboard fa-fw"></i> <span>{$fixedmenu.title}</span> <span class="pull-right-container"> </span></a></li>
<li role="presentation" id="tab_{$fixedmenu.id|htmlentities}" class="{:$referermenu?'':'active'}"><a href="#con_{$fixedmenu.id|htmlentities}" node-id="{$fixedmenu.id|htmlentities}" aria-controls="{$fixedmenu.id|htmlentities}" role="tab" data-toggle="tab"><i class="fa fa-dashboard fa-fw"></i> <span>{$fixedmenu.title|htmlentities}</span> <span class="pull-right-container"> </span></a></li>
{/if}
{if $referermenu}
<li role="presentation" id="tab_{$referermenu.id}" class="active"><a href="#con_{$referermenu.id}" node-id="{$referermenu.id}" aria-controls="{$referermenu.id}" role="tab" data-toggle="tab"><i class="fa fa-list fa-fw"></i> <span>{$referermenu.title}</span> <span class="pull-right-container"> </span></a> <i class="close-tab fa fa-remove"></i></li>
<li role="presentation" id="tab_{$referermenu.id|htmlentities}" class="active"><a href="#con_{$referermenu.id|htmlentities}" node-id="{$referermenu.id|htmlentities}" aria-controls="{$referermenu.id|htmlentities}" role="tab" data-toggle="tab"><i class="fa fa-list fa-fw"></i> <span>{$referermenu.title|htmlentities}</span> <span class="pull-right-container"> </span></a> <i class="close-tab fa fa-remove"></i></li>
{/if}
</ul>
</div>

View File

@ -7,10 +7,10 @@
<link rel="shortcut icon" href="__CDN__/assets/img/favicon.ico" />
<!-- Loading Bootstrap -->
<link href="__CDN__/assets/css/backend{$Think.config.app_debug?'':'.min'}.css?v={$Think.config.site.version}" rel="stylesheet">
<link href="__CDN__/assets/css/backend{$Think.config.app_debug?'':'.min'}.css?v={$Think.config.site.version|htmlentities}" rel="stylesheet">
{if $Think.config.fastadmin.adminskin}
<link href="__CDN__/assets/css/skins/{$Think.config.fastadmin.adminskin}.css?v={$Think.config.site.version}" rel="stylesheet">
<link href="__CDN__/assets/css/skins/{$Think.config.fastadmin.adminskin|htmlentities}.css?v={$Think.config.site.version|htmlentities}" rel="stylesheet">
{/if}
<!-- HTML5 shim, for IE6-8 support of HTML5 elements. All other JS at the end of file. -->

View File

@ -176,7 +176,7 @@
<div class="sm-st clearfix">
<span class="sm-st-icon st-red"><i class="fa fa-users"></i></span>
<div class="sm-st-info">
<span>{$totaluser}</span>
<span>{$totaluser|htmlentities}</span>
{:__('Total user')}
</div>
</div>
@ -185,7 +185,7 @@
<div class="sm-st clearfix">
<span class="sm-st-icon st-violet"><i class="fa fa-magic"></i></span>
<div class="sm-st-info">
<span>{$totaladdon}</span>
<span>{$totaladdon|htmlentities}</span>
{:__('Total addon')}
</div>
</div>
@ -194,7 +194,7 @@
<div class="sm-st clearfix">
<span class="sm-st-icon st-blue"><i class="fa fa-leaf"></i></span>
<div class="sm-st-info">
<span>{$attachmentnums}</span>
<span>{$attachmentnums|htmlentities}</span>
{:__('Total attachment')}
</div>
</div>
@ -203,7 +203,7 @@
<div class="sm-st clearfix">
<span class="sm-st-icon st-green"><i class="fa fa-user"></i></span>
<div class="sm-st-info">
<span>{$totaladmin}</span>
<span>{$totaladmin|htmlentities}</span>
{:__('Total admin')}
</div>
</div>
@ -221,7 +221,7 @@
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-rocket"></i></div>
<div class="stat">
<div class="value"> {$todayusersignup}</div>
<div class="value"> {$todayusersignup|htmlentities}</div>
<div class="name"> {:__('Today user signup')}</div>
</div>
<div class="progress">
@ -231,7 +231,7 @@
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-vcard"></i></div>
<div class="stat">
<div class="value"> {$todayuserlogin}</div>
<div class="value"> {$todayuserlogin|htmlentities}</div>
<div class="name"> {:__('Today user login')}</div>
</div>
<div class="progress">
@ -241,7 +241,7 @@
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-calendar"></i></div>
<div class="stat">
<div class="value"> {$threednu}</div>
<div class="value"> {$threednu|htmlentities}</div>
<div class="name"> {:__('Three dnu')}</div>
</div>
<div class="progress">
@ -251,7 +251,7 @@
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-calendar-plus-o"></i></div>
<div class="stat">
<div class="value"> {$sevendnu}</div>
<div class="value"> {$sevendnu|htmlentities}</div>
<div class="name"> {:__('Seven dnu')}</div>
</div>
<div class="progress">
@ -261,7 +261,7 @@
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-user-circle"></i></div>
<div class="stat">
<div class="value"> {$sevendau}</div>
<div class="value"> {$sevendau|htmlentities}</div>
<div class="name"> {:__('Seven dau')}</div>
</div>
<div class="progress">
@ -271,7 +271,7 @@
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-user-circle-o"></i></div>
<div class="stat">
<div class="value"> {$thirtydau}</div>
<div class="value"> {$thirtydau|htmlentities}</div>
<div class="name"> {:__('Thirty dau')}</div>
</div>
<div class="progress">
@ -298,7 +298,7 @@
<div class="panel-content">
<div class="row">
<div class="col-md-12">
<h1 class="no-margins">{$totalworkingaddon}</h1>
<h1 class="no-margins">{$totalworkingaddon|htmlentities}</h1>
<div class="font-bold"><i class="fa fa-magic"></i>
<small>{:__('Working addon count tips')}</small>
</div>
@ -318,7 +318,7 @@
<div class="ibox-content">
<div class="row">
<div class="col-md-6">
<h1 class="no-margins">{$dbtablenums}</h1>
<h1 class="no-margins">{$dbtablenums|htmlentities}</h1>
<div class="font-bold"><i class="fa fa-database"></i>
<small>{:__('Database table nums')}</small>
</div>
@ -346,7 +346,7 @@
<div class="row">
<div class="col-md-6">
<h1 class="no-margins">{$attachmentnums}</h1>
<h1 class="no-margins">{$attachmentnums|htmlentities}</h1>
<div class="font-bold"><i class="fa fa-files-o"></i>
<small>{:__('Attachment nums')}</small>
</div>
@ -373,7 +373,7 @@
<div class="row">
<div class="col-md-6">
<h1 class="no-margins">{$picturenums}</h1>
<h1 class="no-margins">{$picturenums|htmlentities}</h1>
<div class="font-bold"><i class="fa fa-picture-o"></i>
<small>{:__('Picture nums')}</small>
</div>

View File

@ -15,7 +15,7 @@
<select name="category-third" id="category-third" class="form-control selectpicker">
<option value="">{:__('Please select category')}</option>
{foreach name="categoryList" id="item"}
<option value="{$key}">{$item}</option>
<option value="{$key|htmlentities}">{$item|htmlentities}</option>
{/foreach}
</select>
</div>
@ -42,7 +42,7 @@
<select name="category-local" id="category-local" class="form-control selectpicker">
<option value="">{:__('Please select category')}</option>
{foreach name="categoryList" id="item"}
<option value="{$key}">{$item}</option>
<option value="{$key|htmlentities}">{$item|htmlentities}</option>
{/foreach}
</select>
</div>

View File

@ -8,7 +8,7 @@
<select name="row[category]" class="form-control">
<option value="">{:__('Please select category')}</option>
{foreach name="categoryList" id="item"}
<option value="{$key}" {if $key==$row.category}selected{/if}>{$item}</option>
<option value="{$key|htmlentities}" {if $key==$row.category}selected{/if}>{$item|htmlentities}</option>
{/foreach}
</select>
</div>
@ -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">

View File

@ -5,14 +5,14 @@
<ul class="nav nav-tabs" data-field="category">
<li class="active"><a href="#t-all" data-value="" data-toggle="tab">{:__('All')}</a></li>
{foreach name="categoryList" item="vo"}
<li><a href="#t-{$key}" data-value="{$key}" data-toggle="tab">{$vo}</a></li>
<li><a href="#t-{$key|htmlentities}" data-value="{$key|htmlentities}" data-toggle="tab">{$vo|htmlentities}</a></li>
{/foreach}
<li class="pull-right dropdown filter-type">
<a href="javascript:" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-filter"></i> {:__('Filter Type')}</a>
<ul class="dropdown-menu text-left" role="menu">
<li class="active"><a href="javascript:" data-value="">{:__('All')}</a></li>
{foreach name="mimetypeList" id="item"}
<li><a href="javascript:" data-value="{$key}">{$item}</a></li>
<li><a href="javascript:" data-value="{$key|htmlentities}">{$item|htmlentities}</a></li>
{/foreach}
</ul>
</li>
@ -45,7 +45,7 @@
<select name="category" class="form-control">
<option value="">{:__('Please select category')}</option>
{foreach name="categoryList" id="item"}
<option value="{$key}">{$item}</option>
<option value="{$key|htmlentities}">{$item|htmlentities}</option>
{/foreach}
</select>
</div>

View File

@ -9,7 +9,7 @@
<ul class="nav nav-tabs" data-field="category">
<li class="active"><a href="#t-all" data-value="" data-toggle="tab">{:__('All')}</a></li>
{foreach name="categoryList" item="vo"}
<li><a href="#t-{$key}" data-value="{$key}" data-toggle="tab">{$vo}</a></li>
<li><a href="#t-{$key|htmlentities}" data-value="{$key|htmlentities}" data-toggle="tab">{$vo|htmlentities}</a></li>
{/foreach}
{if stripos(request()->get('mimetype'),'image/')===false}
<li class="pull-right dropdown filter-type">
@ -17,7 +17,7 @@
<ul class="dropdown-menu text-left" role="menu">
<li class="active"><a href="javascript:" data-value="">{:__('All')}</a></li>
{foreach name="mimetypeList" id="item"}
<li><a href="javascript:" data-value="{$key}">{$item}</a></li>
<li><a href="javascript:" data-value="{$key|htmlentities}">{$item|htmlentities}</a></li>
{/foreach}
</ul>
</li>

View File

@ -27,7 +27,7 @@
{:build_heading(null, false)}
<ul class="nav nav-tabs">
{foreach $siteList as $index=>$vo}
<li class="{$vo.active?'active':''}"><a href="#tab-{$vo.name}" data-toggle="tab">{:__($vo.title)}</a></li>
<li class="{$vo.active?'active':''}"><a href="#tab-{$vo.name|htmlentities}" data-toggle="tab">{:__(htmlentities($vo.title))}</a></li>
{/foreach}
{if $Think.config.app_debug}
<li data-toggle="tooltip" title="{:__('Add new config')}">
@ -41,9 +41,9 @@
<div id="myTabContent" class="tab-content">
<!--@formatter:off-->
{foreach $siteList as $index=>$vo}
<div class="tab-pane fade {$vo.active ? 'active in' : ''}" id="tab-{$vo.name}">
<div class="tab-pane fade {$vo.active ? 'active in' : ''}" id="tab-{$vo.name|htmlentities}">
<div class="widget-body no-padding">
<form id="{$vo.name}-form" class="edit-form form-horizontal" role="form" data-toggle="validator" method="POST" action="{:url('general.config/edit')}">
<form id="{$vo.name|htmlentities}-form" class="edit-form form-horizontal" role="form" data-toggle="validator" method="POST" action="{:url('general.config/edit')}">
{:token()}
<table class="table table-striped">
<thead>
@ -58,111 +58,111 @@
</thead>
<tbody>
{foreach $vo.list as $item}
<tr data-favisible="{$item.visible|default=''|htmlentities}" data-name="{$item.name}" class="{if $item.visible??''}hidden{/if}">
<td>{$item.title}</td>
<tr data-favisible="{$item.visible|default=''|htmlentities}" data-name="{$item.name|htmlentities}" class="{if $item.visible??''}hidden{/if}">
<td>{$item.title|htmlentities}</td>
<td>
<div class="row">
<div class="col-sm-8 col-xs-12">
{switch $item.type}
{case string}
<input {$item.extend_html} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}"/>
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule|htmlentities}" data-tip="{$item.tip|htmlentities}"/>
{/case}
{case password}
<input {$item.extend_html} type="password" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}"/>
<input {$item.extend_html|htmlentities} type="password" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule|htmlentities}" data-tip="{$item.tip|htmlentities}"/>
{/case}
{case text}
<textarea {$item.extend_html} name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
<textarea {$item.extend_html|htmlentities} name="row[{$item.name|htmlentities}]" class="form-control" data-rule="{$item.rule|htmlentities}" rows="5" data-tip="{$item.tip|htmlentities}">{$item.value|htmlentities}</textarea>
{/case}
{case editor}
<textarea {$item.extend_html} name="row[{$item.name}]" id="editor-{$item.name}" class="form-control editor" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
<textarea {$item.extend_html|htmlentities} name="row[{$item.name|htmlentities}]" id="editor-{$item.name|htmlentities}" class="form-control editor" data-rule="{$item.rule|htmlentities}" rows="5" data-tip="{$item.tip|htmlentities}">{$item.value|htmlentities}</textarea>
{/case}
{case array}
<dl {$item.extend_html} class="fieldlist" data-name="row[{$item.name}]">
<dl {$item.extend_html|htmlentities} class="fieldlist" data-name="row[{$item.name|htmlentities}]">
<dd>
<ins>{:isset($item["setting"]["key"])&&$item["setting"]["key"]?$item["setting"]["key"]:__('Array key')}</ins>
<ins>{:isset($item["setting"]["value"])&&$item["setting"]["value"]?$item["setting"]["value"]:__('Array value')}</ins>
</dd>
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
<textarea name="row[{$item.name}]" class="form-control hide" cols="30" rows="5">{$item.value|htmlentities}</textarea>
<textarea name="row[{$item.name|htmlentities}]" class="form-control hide" cols="30" rows="5">{$item.value|htmlentities}</textarea>
</dl>
{/case}
{case date}
<input {$item.extend_html} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case time}
<input {$item.extend_html} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case datetime}
<input {$item.extend_html} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case datetimerange}
<input {$item.extend_html} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control datetimerange" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimerange" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case number}
<input {$item.extend_html} type="number" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend_html|htmlentities} type="number" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case checkbox}
<div class="checkbox">
{foreach name="item.content" item="vo"}
<label for="row[{$item.name}][]-{$key}"><input id="row[{$item.name}][]-{$key}" name="row[{$item.name}][]" type="checkbox" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value" }checked{/in} /> {$vo}</label>
<label for="row[{$item.name|htmlentities}][]-{$key|htmlentities}"><input id="row[{$item.name|htmlentities}][]-{$key|htmlentities}" name="row[{$item.name|htmlentities}][]" type="checkbox" value="{$key|htmlentities}" data-tip="{$item.tip|htmlentities}" {in name="key" value="$item.value" }checked{/in} /> {$vo|htmlentities}</label>
{/foreach}
</div>
{/case}
{case radio}
<div class="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>
<label for="row[{$item.name|htmlentities}]-{$key|htmlentities}"><input id="row[{$item.name|htmlentities}]-{$key|htmlentities}" name="row[{$item.name|htmlentities}]" type="radio" value="{$key|htmlentities}" data-tip="{$item.tip|htmlentities}" {in name="key" value="$item.value" }checked{/in} /> {$vo|htmlentities}</label>
{/foreach}
</div>
{/case}
{case value="select" break="0"}{/case}
{case value="selects"}
<select {$item.extend_html} name="row[{$item.name}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip}" {$item.type=='selects'?'multiple':''}>
<select {$item.extend_html|htmlentities} name="row[{$item.name|htmlentities}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip|htmlentities}" {$item.type=='selects'?'multiple':''}>
{foreach name="item.content" item="vo"}
<option value="{$key}" {in name="key" value="$item.value" }selected{/in}>{$vo}</option>
<option value="{$key|htmlentities}" {in name="key" value="$item.value" }selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
{/case}
{case value="image" break="0"}{/case}
{case value="images"}
<div class="form-inline">
<input id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
<span><button type="button" id="faupload-{$item.name}" class="btn btn-danger faupload" data-input-id="c-{$item.name}" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<span class="msg-box n-right" for="c-{$item.name}"></span>
<ul class="row list-inline faupload-preview" id="p-{$item.name}"></ul>
<input id="c-{$item.name|htmlentities}" class="form-control" size="50" name="row[{$item.name|htmlentities}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip|htmlentities}">
<span><button type="button" id="faupload-{$item.name|htmlentities}" class="btn btn-danger faupload" data-input-id="c-{$item.name|htmlentities}" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name|htmlentities}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name|htmlentities}" class="btn btn-primary fachoose" data-input-id="c-{$item.name|htmlentities}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<span class="msg-box n-right" for="c-{$item.name|htmlentities}"></span>
<ul class="row list-inline faupload-preview" id="p-{$item.name|htmlentities}"></ul>
</div>
{/case}
{case value="file" break="0"}{/case}
{case value="files"}
<div class="form-inline">
<input id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
<span><button type="button" id="faupload-{$item.name}" class="btn btn-danger faupload" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<span class="msg-box n-right" for="c-{$item.name}"></span>
<input id="c-{$item.name|htmlentities}" class="form-control" size="50" name="row[{$item.name|htmlentities}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip|htmlentities}">
<span><button type="button" id="faupload-{$item.name|htmlentities}" class="btn btn-danger faupload" data-input-id="c-{$item.name|htmlentities}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name|htmlentities}" class="btn btn-primary fachoose" data-input-id="c-{$item.name|htmlentities}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<span class="msg-box n-right" for="c-{$item.name|htmlentities}"></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">
<input id="c-{$item.name|htmlentities}" name="row[{$item.name|htmlentities}]" type="hidden" value="{:$item.value?1:0}">
<a href="javascript:;" data-toggle="switcher" class="btn-switcher" data-input-id="c-{$item.name|htmlentities}" 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>
<label for="row[{$item.name|htmlentities}]-yes"><input id="row[{$item.name|htmlentities}]-yes" name="row[{$item.name|htmlentities}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip|htmlentities}" /> {:__('Yes')}</label>
<label for="row[{$item.name|htmlentities}]-no"><input id="row[{$item.name|htmlentities}]-no" name="row[{$item.name|htmlentities}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip|htmlentities}" /> {:__('No')}</label>
{/case}
{case city}
<div style="position:relative">
<input {$item.extend_html} type="text" name="row[{$item.name}]" id="c-{$item.name}" value="{$item.value|htmlentities}" class="form-control" data-toggle="city-picker" data-tip="{$item.tip}" data-rule="{$item.rule}" />
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" id="c-{$item.name|htmlentities}" value="{$item.value|htmlentities}" class="form-control" data-toggle="city-picker" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}" />
</div>
{/case}
{case value="selectpage" break="0"}{/case}
{case value="selectpages"}
<input {$item.extend_html} type="text" name="row[{$item.name}]" id="c-{$item.name}" value="{$item.value|htmlentities}" class="form-control selectpage" data-source="{:url('general.config/selectpage')}?id={$item.id}" data-primary-key="{$item.setting.primarykey}" data-field="{$item.setting.field}" data-multiple="{$item.type=='selectpage'?'false':'true'}" data-tip="{$item.tip}" data-rule="{$item.rule}" />
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" id="c-{$item.name|htmlentities}" value="{$item.value|htmlentities}" class="form-control selectpage" data-source="{:url('general.config/selectpage')}?id={$item.id|htmlentities}" data-primary-key="{$item.setting.primarykey|htmlentities}" data-field="{$item.setting.field|htmlentities}" data-multiple="{$item.type=='selectpage'?'false':'true'}" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}" />
{/case}
{case custom}
{$item.extend_html}
{$item.extend_html|htmlentities}
{/case}
{/switch}
</div>
@ -172,7 +172,7 @@
</td>
{if $Think.config.app_debug}
<td>{php}echo "{\$site.". $item['name'] . "}";{/php}</td>
<td>{if $item['id']>18}<a href="javascript:;" class="btn-delcfg text-muted" data-name="{$item.name}"><i class="fa fa-times"></i></a>{/if}</td>
<td>{if $item['id']>18}<a href="javascript:;" class="btn-delcfg text-muted" data-name="{$item.name|htmlentities}"><i class="fa fa-times"></i></a>{/if}</td>
{/if}
</tr>
{/foreach}
@ -205,7 +205,7 @@
<div class="col-xs-12 col-sm-4">
<select name="row[group]" class="form-control selectpicker">
{foreach name="groupList" item="vo"}
<option value="{$key}" {in name="key" value="basic" }selected{/in}>{$vo}</option>
<option value="{$key|htmlentities}" {in name="key" value="basic" }selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
</div>
@ -215,7 +215,7 @@
<div class="col-xs-12 col-sm-4">
<select name="row[type]" id="c-type" class="form-control selectpicker">
{foreach name="typeList" item="vo"}
<option value="{$key}" {in name="key" value="string" }selected{/in}>{$vo}</option>
<option value="{$key|htmlentities}" {in name="key" value="string" }selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
</div>
@ -306,7 +306,7 @@ value2|title2</textarea>
<button class="btn btn-primary dropdown-toggle" data-toggle="dropdown" type="button">{:__('Choose')}</button>
<ul class="dropdown-menu pull-right rulelist">
{volist name="ruleList" id="item"}
<li><a href="javascript:;" data-value="{$key}">{$item}<span class="text-muted">({$key})</span></a></li>
<li><a href="javascript:;" data-value="{$key|htmlentities}">{$item|htmlentities}<span class="text-muted">({$key|htmlentities})</span></a></li>
{/volist}
</ul>
</span>

View File

@ -27,13 +27,13 @@
<!-- 主体内容区域 -->
<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}{: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 role="tabpanel" class="tab-pane {:$referermenu?'':'active'}" id="con_{$fixedmenu.id|htmlentities}">
<iframe src="{$fixedmenu.url|htmlentities}{: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}{: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 role="tabpanel" class="tab-pane active" id="con_{$referermenu.id|htmlentities}">
<iframe src="{$referermenu.url|htmlentities}{:stripos($referermenu.url, '?') !== false ? '&' : '?'}addtabs=1" width="100%" height="100%" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling-x="no" scrolling-y="auto" allowtransparency="yes"></iframe>
</div>
{/if}
</div>
@ -42,7 +42,7 @@
<footer class="main-footer hide">
<div class="pull-right hidden-xs">
</div>
<strong>Copyright &copy; 2017-{:date("Y")} <a href="__PUBLIC__">{$site.name}</a>.</strong> All rights reserved.
<strong>Copyright &copy; 2017-{:date("Y")} <a href="__PUBLIC__">{$site.name|htmlentities}</a>.</strong> All rights reserved.
</footer>
<!-- 右侧控制栏 -->

View File

@ -81,7 +81,7 @@
{if $background}
<style type="text/css">
body{
background-image: url('{$background}');
background-image: url('{$background|htmlentities}');
}
</style>
{/if}
@ -116,7 +116,7 @@
{if $Think.config.fastadmin.login_captcha}
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-option-horizontal" aria-hidden="true"></span></div>
<input type="text" name="captcha" class="form-control" placeholder="{:__('Captcha')}" data-rule="{:__('Captcha')}:required;length({$Think.config.captcha.length})" autocomplete="off"/>
<input type="text" name="captcha" class="form-control" placeholder="{:__('Captcha')}" data-rule="{:__('Captcha')}:required;length({$Think.config.captcha.length|htmlentities})" autocomplete="off"/>
<span class="input-group-addon" style="padding:0;border:none;cursor:pointer;">
<img src="{:rtrim('__PUBLIC__', '/')}/index.php?s=/captcha" width="100" height="30" onclick="this.src = '{:rtrim('__PUBLIC__', '/')}/index.php?s=/captcha&r=' + Math.random();"/>
</span>

View File

@ -26,7 +26,7 @@
</ol>
<ol class="breadcrumb pull-right">
{foreach $breadcrumb as $vo}
<li><a href="javascript:;" data-url="{$vo.url}">{$vo.title}</a></li>
<li><a href="javascript:;" data-url="{$vo.url|htmlentities}">{$vo.title|htmlentities}</a></li>
{/foreach}
</ol>
</div>

View File

@ -22,7 +22,7 @@
<div class="radio">
{foreach name="statusList" item="vo"}
<label for="row[status]-{$key}"><input id="row[status]-{$key}" name="row[status]" type="radio" value="{$key}" {in name="key" value="normal"}checked{/in} /> {$vo}</label>
<label for="row[status]-{$key|htmlentities}"><input id="row[status]-{$key|htmlentities}" name="row[status]" type="radio" value="{$key|htmlentities}" {in name="key" value="normal"}checked{/in} /> {$vo|htmlentities}</label>
{/foreach}
</div>

View File

@ -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">
@ -22,7 +22,7 @@
<div class="radio">
{foreach name="statusList" item="vo"}
<label for="row[status]-{$key}"><input id="row[status]-{$key}" name="row[status]" type="radio" value="{$key}" {in name="key" value="$row.status"}checked{/in} /> {$vo}</label>
<label for="row[status]-{$key|htmlentities}"><input id="row[status]-{$key|htmlentities}" name="row[status]" type="radio" value="{$key|htmlentities}" {in name="key" value="$row.status"}checked{/in} /> {$vo|htmlentities}</label>
{/foreach}
</div>

View File

@ -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">

View File

@ -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[id]" value="{$row.id}">
<input type="hidden" name="row[id]" value="{$row.id|htmlentities}">
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
<div class="col-xs-12 col-sm-4">
@ -41,7 +41,7 @@
<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,7 +54,7 @@
<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">
@ -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">

View File

@ -38,9 +38,9 @@ class Common extends Api
/**
* 加载初始化
*
* @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()
{
@ -80,7 +80,7 @@ class Common extends Api
/**
* 上传文件
* @ApiMethod (POST)
* @param File $file 文件流
* @ApiParams (name="file", type="file", required=true, description="文件流")
*/
public function upload()
{
@ -148,7 +148,7 @@ class Common extends Api
/**
* 验证码
* @param $id
* @ApiParams (name="id", type="string", required=true, description="要生成验证码的标识")
* @return \think\Response
*/
public function captcha($id = "")

View File

@ -24,13 +24,12 @@ 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()
{
$email = $this->request->post("email");
$captcha = $this->request->post("captcha");
$event = $this->request->post("event");
$event = $event ? $event : 'register';
@ -88,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()
{

View File

@ -19,22 +19,15 @@ 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()
{
$mobile = $this->request->post("mobile");
$captcha = $this->request->post("captcha");
$event = $this->request->post("event");
$event = $event ? $event : 'register';
//发送前验证码
if (config('fastadmin.user_api_captcha')) {
if (!\think\Validate::is($captcha, 'captcha')) {
$this->error("验证码不正确");
}
}
if (!$mobile || !\think\Validate::regex($mobile, "^1\d{10}$")) {
$this->error(__('手机号不正确'));
}
@ -74,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()
{

View File

@ -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 $captcha 验证码
* @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()
{
@ -113,8 +113,7 @@ class User extends Api
$password = $this->request->post('password');
$email = $this->request->post('email');
$mobile = $this->request->post('mobile');
$captcha = $this->request->post("captcha", $this->request->post('code'));
$code = $this->request->post('code');
if (!$username || !$password) {
$this->error(__('Invalid parameters'));
}
@ -124,7 +123,7 @@ class User extends Api
if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) {
$this->error(__('Mobile is incorrect'));
}
$ret = Sms::check($mobile, $captcha, 'register');
$ret = Sms::check($mobile, $code, 'register');
if (!$ret) {
$this->error(__('Captcha is incorrect'));
}
@ -154,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()
{
@ -190,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()
{
@ -225,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()
{
@ -260,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()
{
@ -292,9 +291,9 @@ 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()
{

View File

@ -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()
{

View File

@ -80,8 +80,8 @@ if (!function_exists('cdnurl')) {
/**
* 获取上传资源的CDN的地址
* @param string $url 资源相对地址
* @param boolean|string $domain 是否显示域名 或者直接传入域名
* @param string $url 资源相对地址
* @param boolean $domain 是否显示域名 或者直接传入域名
* @return string
*/
function cdnurl($url, $domain = false)

View File

@ -577,6 +577,7 @@ class Backend extends Controller
$result = array_intersect_key(($item instanceof Model ? $item->toArray() : (array)$item), array_flip($fields));
}
$result['pid'] = isset($item['pid']) ? $item['pid'] : (isset($item['parent_id']) ? $item['parent_id'] : 0);
$result = array_map("htmlentities", $result);
$list[] = $result;
}
if ($istree && !$primaryvalue) {

View File

@ -221,7 +221,14 @@ 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');
return false;
}
if ($user->password != $this->getEncryptPassword($password, $user->salt)) {
$user->save(['loginfailure' => $user->loginfailure + 1, 'loginfailuretime' => time()]);
$this->setError('Password is incorrect');
return false;
}

View File

@ -218,7 +218,7 @@ class Email
} catch (CodeException $e) {
preg_match_all("/Expected: (\d+)\, Got: (\d+)( \| (.*))?\$/i", $e->getMessage(), $matches);
$code = $matches[2][0] ?? 0;
$message = $matches[4][0] ?? $e->getMessage();
$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) {

View File

@ -86,6 +86,11 @@ class Upload
*/
protected function checkExecutable()
{
//禁止上传以.开头的文件
if (substr($this->fileInfo['name'], 0, 1) === '.') {
throw new UploadException(__('Uploaded file format is limited'));
}
//禁止上传PHP和HTML文件
if (in_array($this->fileInfo['type'], ['text/x-php', 'text/html']) || in_array($this->fileInfo['suffix'], ['php', 'html', 'htm', 'phar', 'phtml']) || preg_match("/^php(.*)/i", $this->fileInfo['suffix'])) {
throw new UploadException(__('Uploaded file format is limited'));
@ -107,8 +112,7 @@ class Upload
throw new UploadException(__('Uploaded file format is limited'));
}
//验证文件后缀
if ($this->config['mimetype'] === '*'
|| in_array($this->fileInfo['suffix'], $mimetypeArr) || in_array('.' . $this->fileInfo['suffix'], $mimetypeArr)
if (in_array($this->fileInfo['suffix'], $mimetypeArr) || in_array('.' . $this->fileInfo['suffix'], $mimetypeArr)
|| in_array($typeArr[0] . "/*", $mimetypeArr) || (in_array($this->fileInfo['type'], $mimetypeArr) && stripos($this->fileInfo['type'], '/') !== false)) {
return true;
}

View File

@ -7,6 +7,10 @@ use think\Model;
/**
* 会员模型
* @method static mixed getByUsername($str) 通过用户名查询用户
* @method static mixed getByNickname($str) 通过昵称查询用户
* @method static mixed getByMobile($str) 通过手机查询用户
* @method static mixed getByEmail($str) 通过邮箱查询用户
*/
class User extends Model
{
@ -29,7 +33,7 @@ class User extends Model
*/
public function getUrlAttr($value, $data)
{
return str_replace("{uid}", $data['id'], config('fastadmin.user_home_url') ?: "/u/{uid}");
return "/u/" . $data['id'];
}
/**
@ -41,9 +45,11 @@ class User extends Model
public function getAvatarAttr($value, $data)
{
if (!$value) {
$value = config('fastadmin.user_letter_avatar') ? letter_avatar($data['nickname']) : '/assets/img/avatar.png';
//如果不需要启用首字母头像,请使用
//$value = '/assets/img/avatar.png';
$value = letter_avatar($data['nickname']);
}
return cdnurl($value, true);
return $value;
}
/**
@ -118,16 +124,9 @@ class User extends Model
if ($user && $score != 0) {
$before = $user->score;
$after = $user->score + $score;
$data = ['score' => $after];
$levelrule = config('fastadmin.user_level_rule');
if (in_array($levelrule, ['auto', 'up'])) {
$level = self::nextlevel($after);
if ($levelrule == 'auto' || $level > $user['level']) {
$data['level'] = $level;
}
}
$level = self::nextlevel($after);
//更新会员信息
$user->save($data);
$user->save(['score' => $after, 'level' => $level]);
//写入日志
ScoreLog::create(['user_id' => $user_id, 'score' => $score, 'before' => $before, 'after' => $after, 'memo' => $memo]);
}
@ -144,8 +143,7 @@ class User extends Model
*/
public static function nextlevel($score = 0)
{
$lv = config('fastadmin.user_level_dict');
$lv = $lv ?: [];
$lv = array(1 => 0, 2 => 30, 3 => 100, 4 => 500, 5 => 1000, 6 => 2000, 7 => 3000, 8 => 5000, 9 => 8000, 10 => 10000);
$level = 1;
foreach ($lv as $key => $value) {
if ($score >= $value) {

View File

@ -41,18 +41,19 @@
<p class="clearfix">
<a href="__PUBLIC__" class="btn btn-grey">{:__('Go back')}</a>
{if $url}
<a href="{$url|htmlentities}" class="btn btn-primary">{:__('Jump now')}</a>
<a id="href" href="{$url|htmlentities}" class="btn btn-primary">{:__('Jump now')}</a>
{/if}
</p>
</div>
{if $url}
<script type="text/javascript">
(function () {
var wait = document.getElementById('wait');
var wait = document.getElementById('wait'),
href = document.getElementById('href').href;
var interval = setInterval(function () {
var time = --wait.innerHTML;
if (time <= 0) {
location.href = "{$url|htmlentities}";
location.href = href;
clearInterval(interval);
}
}, 1000);
@ -60,4 +61,4 @@
</script>
{/if}
</body>
</html>
</html>

View File

@ -237,8 +237,6 @@ return [
'captcha' => [
// 验证码字符集合
'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
// 验证码过期时间s
'expire' => 600,
// 验证码字体大小(px)
'fontSize' => 18,
// 是否画混淆曲线
@ -272,17 +270,7 @@ return [
//是否开启前台会员中心
'usercenter' => true,
//会员注册验证码类型email/mobile/wechat/text/false
'user_register_captcha' => 'mobile',
//是否启用发送前验证码(用于短信和邮件发送)
'user_api_captcha' => true,
//会员主页URL规则
'user_home_url' => '/u/{uid}',
//是否启用会员字母头像
'user_letter_avatar' => true,
//是否启用会员等级规则none/auto/up
'user_level_rule' => '',
//会员等级积分字典
'user_level_dict' => [1 => 0, 2 => 30, 3 => 100, 4 => 500, 5 => 1000, 6 => 2000, 7 => 3000, 8 => 5000, 9 => 8000, 10 => 10000],
'user_register_captcha' => 'text',
//登录验证码
'login_captcha' => true,
//登录失败超过10次则1天后重试
@ -293,8 +281,6 @@ return [
'loginip_check' => true,
//登录页默认背景图
'login_background' => "",
//是否启用简洁导航
'simplenav' => true,
//是否启用多级菜单导航
'multiplenav' => false,
//是否开启多选项卡(仅在开启多级菜单时起作用)
@ -316,7 +302,7 @@ return [
//允许跨域的域名,多个以,分隔
'cors_request_domain' => 'localhost,127.0.0.1',
//版本号
'version' => '1.6.0.20240401',
'version' => '1.6.0.20250331',
//API接口地址
'api_url' => 'https://api.fastadmin.net',
],

View File

@ -20,6 +20,7 @@ return [
'maxsize' => '10mb',
/**
* 可上传的文件类型
* 如配置允许 pdf,ppt,docx,svg 等可能含有脚本的文件时,请先从服务器配置此类文件直接下载而不是预览
*/
'mimetype' => 'jpg,png,bmp,jpeg,gif,webp,zip,rar,wav,mp4,mp3,webm',
/**

View File

@ -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]);
}

View File

@ -7,7 +7,6 @@ use app\common\controller\Frontend;
use app\common\library\Ems;
use app\common\library\Sms;
use app\common\model\Attachment;
use fast\Random;
use think\Config;
use think\Cookie;
use think\Hook;
@ -20,7 +19,7 @@ use think\Validate;
class User extends Frontend
{
protected $layout = 'default';
protected $noNeedLogin = ['login', 'mobilelogin', 'register', 'third'];
protected $noNeedLogin = ['login', 'register', 'third'];
protected $noNeedRight = ['*'];
public function _initialize()
@ -191,53 +190,6 @@ class User extends Frontend
return $this->view->fetch();
}
/**
* 手机号验证码登录
*/
public function mobilelogin()
{
$url = $this->request->request('url', '', 'url_clean');
if ($this->request->isPost()) {
$mobile = $this->request->post('mobile');
$captcha = $this->request->post('captcha');
if (!$mobile || !$captcha) {
$this->error(__('Invalid parameters'));
}
if (!Validate::regex($mobile, "^1\d{10}$")) {
$this->error(__('Mobile is incorrect'));
}
if (!Sms::check($mobile, $captcha, 'mobilelogin')) {
$this->error(__('Captcha is incorrect'));
}
$user = \app\common\model\User::getByMobile($mobile);
if ($user) {
if ($user->status != 'normal') {
$this->error(__('Account is locked'));
}
//如果已经有账号则直接登录
$ret = $this->auth->direct($user->id);
} else {
$ret = $this->auth->register($mobile, Random::alnum(), '', $mobile, []);
}
if ($ret) {
Sms::flush($mobile, 'mobilelogin');
$data = ['userinfo' => $this->auth->getUserinfo()];
$this->success(__('Logged in successful'), $url);
} else {
$this->error($this->auth->getError());
}
}
//判断来源
$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)) {
$url = $referer;
}
$this->view->assign('url', $url);
$this->view->assign('title', __('Login'));
return $this->view->fetch();
}
/**
* 退出登录
*/

View File

@ -19,12 +19,8 @@ return [
'Change' => '修改',
'Click to edit' => '点击编辑',
'Email/Mobile/Username' => '邮箱/手机/用户名',
'Sign in with account' => '使用账号密码登录',
'Sign in with mobile phone' => '使用手机验证码登录',
'Sign up successful' => '注册成功',
'Email active successful' => '邮箱激活成功',
'Please enter your mobile phone number' => '请输入你的手机号',
'Please enter %s numbers' => '请输入%s位数字',
'Username can not be empty' => '用户名不能为空',
'Username must be 3 to 30 characters' => '用户名必须3-30个字符',
'Username must be 6 to 30 characters' => '用户名必须6-30个字符',
@ -61,6 +57,7 @@ return [
'Change password successful' => '修改密码成功',
'Password and confirm password don\'t match' => '两次输入的密码不一致',
'Captcha is incorrect' => '验证码不正确',
'Please try again after 1 day' => '请于1天后再尝试登录',
'Logged in successful' => '登录成功',
'Logout successful' => '退出成功',
'User center already closed' => '会员中心已经关闭',

View File

@ -1,19 +1,19 @@
<!--@formatter:off-->
{if "[type]" == 'email'}
<input type="text" name="captcha" class="form-control" placeholder="{:__('Please enter %s numbers', $Think.config.captcha.length)}" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_ems_correct')}, event=[event], email:#email)" />
<input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_ems_correct')}, event=[event], email:#email)" />
<span class="input-group-btn" style="padding:0;border:none;">
<a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/ems/send')}" data-type="email" data-event="[event]">{:__('Send verification code')}</a>
<a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/ems/send')}" data-type="email" data-event="[event]">发送验证码</a>
</span>
{elseif "[type]" == 'mobile'/}
<input type="text" name="captcha" class="form-control" placeholder="{:__('Please enter %s numbers', $Think.config.captcha.length)}" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_sms_correct')}, event=[event], mobile:#mobile)" />
<input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});digits;remote({:url('api/validate/check_sms_correct')}, event=[event], mobile:#mobile)" />
<span class="input-group-btn" style="padding:0;border:none;">
<a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/sms/send')}" data-type="mobile" data-event="[event]">{:__('Send verification code')}</a>
<a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/sms/send')}" data-type="mobile" data-event="[event]">发送验证码</a>
</span>
{elseif "[type]" == 'wechat'/}
{if get_addon_info('wechat')}
<input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length});remote({:addon_url('wechat/captcha/check')}, event=[event])" />
<span class="input-group-btn" style="padding:0;border:none;">
<a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:addon_url('wechat/captcha/send')}" data-type="wechat" data-event="[event]">{:__('Send verification code')}</a>
<a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:addon_url('wechat/captcha/send')}" data-type="wechat" data-event="[event]">获取验证码</a>
</span>
{else/}
请在后台插件管理中安装《微信管理插件》
@ -24,4 +24,4 @@
<img src="{:captcha_src()}" width="100" height="32" onclick="this.src = '{:captcha_src()}?r=' + Math.random();"/>
</span>
{/if}
<!--@formatter:on-->
<!--@formatter:on-->

View File

@ -1,24 +1 @@
{if $Think.config.fastadmin.user_api_captcha}
<script type="text/html" id="captchatpl">
<div class="p-4 form-section">
<form name="captcha-form" class="form-vertical" action="" method="post">
<div class="form-group mb-4">
<label class="control-label hidden">{:__('Captcha')}</label>
<div class="controls">
<div class="input-group">
<input type="text" name="captcha" class="form-control" data-rule="required;length({$Think.config.captcha.length})" />
<span class="input-group-btn" style="padding:0;border:none;">
<img src="{:captcha_src()}" width="107" height="32" class="captcha-img" onclick="this.src = '{:captcha_src()}?r=' + Math.random();"/>
</span>
</div>
<span class="msg-box n-right" style="left:0;top:33px;text-align: left;" for="captcha"></span>
</div>
</div>
<div class="form-group">
<button class="btn btn-primary btn-block" type="submit">{:__('Submit')}</button>
</div>
</form>
</div>
</script>
{/if}
<script src="__CDN__/assets/js/require.min.js" data-main="__CDN__/assets/js/require-frontend{$Think.config.app_debug?'':'.min'}.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/js/require{$Think.config.app_debug?'':'.min'}.js" data-main="__CDN__/assets/js/require-frontend{$Think.config.app_debug?'':'.min'}.js?v={$site.version|htmlentities}"></script>

View File

@ -1,4 +1,4 @@
<link rel="stylesheet" href="__CDN__/assets/libs/fastadmin-bootstraptable/dist/bootstrap-table.min.css">
<link rel="stylesheet" href="__CDN__/assets/libs/bootstrap-table/dist/bootstrap-table.min.css">
{if $Think.get.dialog}
<style>
body {

View File

@ -1,40 +1,19 @@
<div id="content-container" class="container">
<div class="user-section login-section">
<div class="logon-tab clearfix"><a class="active">{:__('Sign in')}</a> <a href="{:url('user/register')}?url={$url|xss_clean|urlencode}">{:__('Sign up')}</a></div>
<div class="logon-tab clearfix"><a class="active">{:__('Sign in')}</a> <a href="{:url('user/register')}?url={$url|urlencode|htmlentities}">{:__('Sign up')}</a></div>
<div class="login-main">
<form name="form" id="login-form" class="form-vertical" method="POST" action="{:url('user/mobilelogin')}">
<form name="form" id="login-form" class="form-vertical" method="POST" action="">
<!--@IndexLoginFormBegin-->
<input type="hidden" name="url" value="{$url|htmlentities}"/>
{:token()}
<div class="form-group" data-login="mobile">
<label class="control-label">{:__('Mobile')}</label>
<div class="controls">
<input type="text" id="mobile" name="mobile" data-rule="required;mobile" class="form-control" placeholder="{:__('Please enter your mobile phone number')}">
<p class="help-block"></p>
</div>
</div>
<div class="form-group" data-login="mobile">
<label class="control-label">{:__('Captcha')}</label>
<div class="controls">
<div class="input-group">
<input type="text" name="captcha" class="form-control" placeholder="{:__('Please enter %s numbers', $Think.config.captcha.length)}" maxlength="{$Think.config.captcha.length}" data-rule="required;length({$Think.config.captcha.length});integer[+]"/>
<span class="input-group-btn" style="padding:0;border:none;">
<a href="javascript:;" class="btn btn-info btn-captcha" data-url="{:url('api/sms/send')}" data-type="mobile" data-event="mobilelogin">{:__('Send verification code')}</a>
</span>
</div>
<p class="help-block"></p>
</div>
</div>
<div class="form-group hidden" data-login="account">
<div class="form-group">
<label class="control-label" for="account">{:__('Account')}</label>
<div class="controls">
<input class="form-control" id="account" type="text" name="account" value="" data-rule="required" placeholder="{:__('Email/Mobile/Username')}" autocomplete="off">
<div class="help-block"></div>
</div>
</div>
<div class="form-group hidden" data-login="account">
<div class="form-group">
<label class="control-label" for="password">{:__('Password')}</label>
<div class="controls">
<input class="form-control" id="password" type="password" name="password" data-rule="required;password" placeholder="{:__('Password')}" autocomplete="off">
@ -52,18 +31,7 @@
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-lg btn-block">{:__('Sign in')}</button>
<div class="row">
<div class="col-xs-6 text-left py-2">
<a href="javascript:" class="btn-switchlogin" data-type="mobile"
data-account-action="{:url('user/login')}"
data-mobile-action="{:url('user/mobilelogin')}"
data-account-text='{:__("Sign in with account")}'
data-mobile-text='{:__("Sign in with mobile phone")}'>{:__("Sign in with account")}</a>
</div>
<div class="col-xs-6 text-right py-2">
<a href="{:url('user/register')}?url={$url|xss_clean|urlencode}">{:__("Don't have an account? Sign up")}</a>
</div>
</div>
<a href="{:url('user/register')}?url={$url|urlencode|htmlentities}" class="btn btn-default btn-lg btn-block mt-3 no-border">{:__("Don't have an account? Sign up")}</a>
</div>
<!--@IndexLoginFormEnd-->
</form>

View File

@ -1,11 +1,11 @@
<div id="content-container" class="container">
<div class="user-section login-section">
<div class="logon-tab clearfix"><a href="{:url('user/login')}?url={$url|xss_clean|urlencode}">{:__('Sign in')}</a> <a class="active">{:__('Sign up')}</a></div>
<div class="logon-tab clearfix"><a href="{:url('user/login')}?url={$url|urlencode|htmlentities}">{:__('Sign in')}</a> <a class="active">{:__('Sign up')}</a></div>
<div class="login-main">
<form name="form1" id="register-form" class="form-vertical" method="POST" action="">
<!--@IndexRegisterFormBegin-->
<input type="hidden" name="invite_user_id" value="0"/>
<input type="hidden" name="url" value="{$url|xss_clean}"/>
<input type="hidden" name="url" value="{$url|htmlentities}"/>
{:token()}
<div class="form-group">
<label class="control-label required">{:__('Email')}<span class="text-success"></span></label>
@ -31,7 +31,7 @@
<div class="form-group">
<label class="control-label">{:__('Mobile')}</label>
<div class="controls">
<input type="text" id="mobile" name="mobile" data-rule="required;mobile" class="form-control" placeholder="{:__('Mobile')}" value="">
<input type="text" id="mobile" name="mobile" data-rule="required;mobile" class="form-control" placeholder="{:__('Mobile')}">
<p class="help-block"></p>
</div>
</div>
@ -52,7 +52,7 @@
<div class="form-group">
<button type="submit" class="btn btn-primary btn-lg btn-block">{:__('Sign up')}</button>
<a href="{:url('user/login')}?url={$url|xss_clean|urlencode}" class="btn btn-default btn-lg btn-block mt-3 no-border">{:__('Already have an account? Sign in')}</a>
<a href="{:url('user/login')}?url={$url|urlencode|htmlentities}" class="btn btn-default btn-lg btn-block mt-3 no-border">{:__('Already have an account? Sign in')}</a>
</div>
<!--@IndexRegisterFormEnd-->
</form>

View File

@ -1,5 +1,5 @@
{
"name": "karsonzhang/fastadmin",
"name": "fastadminnet/fastadmin",
"description": "the fastest admin framework",
"type": "project",
"keywords": [
@ -15,21 +15,21 @@
}
],
"require": {
"php": ">=7.2.0",
"php": ">=7.4.0",
"topthink/framework": "dev-master",
"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.4.0",
"fastadminnet/fastadmin-addons": "~1.4.0",
"fastadminnet/fastadmin-mailer": "^2.0.0",
"overtrue/pinyin": "^3.0",
"phpoffice/phpspreadsheet": "1.19.0",
"overtrue/wechat": "^4.6.0",
"phpoffice/phpspreadsheet": "^1.29.1",
"overtrue/wechat": "^4.6",
"ext-json": "*",
"ext-curl": "*",
"ext-pdo": "*",
"ext-bcmath": "*",
"txthinking/mailer": "^2.0"
"ext-bcmath": "*"
},
"config": {
"preferred-install": "dist",
@ -38,6 +38,11 @@
"easywechat-composer/easywechat-composer": true
}
},
"autoload": {
"psr-4": {
"addons\\": "addons/"
}
},
"repositories": [
{
"type": "git",

View File

@ -11,11 +11,11 @@ class Http
/**
* 发送一个POST请求
* @param string $url 请求URL
* @param array $params 请求参数
* @param array $options 扩展参数
* @param array $params 请求参数
* @param array $options 扩展参数
* @return mixed|string
*/
public static function post(string $url, array $params = [], array $options = [])
public static function post($url, $params = [], $options = [])
{
$req = self::sendRequest($url, $params, 'POST', $options);
return $req['ret'] ? $req['msg'] : '';
@ -24,11 +24,11 @@ class Http
/**
* 发送一个GET请求
* @param string $url 请求URL
* @param array $params 请求参数
* @param array $options 扩展参数
* @param array $params 请求参数
* @param array $options 扩展参数
* @return mixed|string
*/
public static function get(string $url, array $params = [], array $options = [])
public static function get($url, $params = [], $options = [])
{
$req = self::sendRequest($url, $params, 'GET', $options);
return $req['ret'] ? $req['msg'] : '';
@ -42,7 +42,7 @@ class Http
* @param mixed $options CURL的参数
* @return array
*/
public static function sendRequest(string $url, $params = [], string $method = 'POST', $options = []): array
public static function sendRequest($url, $params = [], $method = 'POST', $options = [])
{
$method = strtoupper($method);
$protocol = substr($url, 0, 5);
@ -108,7 +108,7 @@ class Http
* @param string $method 请求的方法
* @return boolean TRUE
*/
public static function sendAsyncRequest(string $url, $params = [], string $method = 'POST'): bool
public static function sendAsyncRequest($url, $params = [], $method = 'POST')
{
$method = strtoupper($method);
$method = $method == 'POST' ? 'POST' : 'GET';
@ -157,10 +157,10 @@ class Http
/**
* 发送文件到客户端
* @param string $file
* @param bool $deleteAfterSend
* @param bool $exitAfterSend
* @param bool $delaftersend
* @param bool $exitaftersend
*/
public static function sendToBrowser(string $file, bool $deleteAfterSend = true, bool $exitAfterSend = true)
public static function sendToBrowser($file, $delaftersend = true, $exitaftersend = true)
{
if (file_exists($file) && is_readable($file)) {
header('Content-Description: File Transfer');
@ -174,10 +174,10 @@ class Http
ob_clean();
flush();
readfile($file);
if ($deleteAfterSend) {
if ($delaftersend) {
unlink($file);
}
if ($exitAfterSend) {
if ($exitaftersend) {
exit;
}
}

2943
package-lock.json generated 100644

File diff suppressed because it is too large Load Diff

View File

@ -3,36 +3,40 @@
"version": "1.6.0",
"description": "FastAdmin是一款基于ThinkPHP+Bootstrap的极速后台开发框架。",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"build": "grunt"
},
"repository": {
"type": "git",
"url": "git@gitee.com:karson/fastadmin.git"
},
"dependencies": {
"art-template": "^3.1.3",
"bootstrap": "^3.4.1",
"bootstrap": "npm:fastadmin-bootstrap@^3.4.1",
"bootstrap-daterangepicker": "~2.1.25",
"bootstrap-select": "^1.13.18",
"bootstrap-slider": "^11.0.2",
"eonasdan-bootstrap-datetimepicker": "^4.17.49",
"fastadmin-addtabs": "karsonzhang/jquery-addtabs#semver:~1.0.7",
"fastadmin-citypicker": "karsonzhang/fastadmin-citypicker#semver:~1.3.2",
"fastadmin-cxselect": "karsonzhang/fastadmin-cxselect#semver:~1.4.0",
"fastadmin-dragsort": "karsonzhang/fastadmin-dragsort#semver:~1.0.1",
"fastadmin-layer": "karsonzhang/fastadmin-layer#semver:~3.5.2",
"fastadmin-selectpage": "karsonzhang/fastadmin-selectpage#semver:~1.0.11",
"bootstrap-table": "karsonzhang/fastadmin-bootstraptable",
"nice-validator": "karsonzhang/fastadmin-nicevalidator#semver:~1.1.6",
"cxselect": "^1.4.0",
"fastadmin-addtabs": "^1.0.8",
"fastadmin-arttemplate": "^3.1.4",
"fastadmin-bootstraptable": "^1.11.12",
"fastadmin-citypicker": "^1.3.6",
"fastadmin-cxselect": "npm:cxselect@^1.4.0",
"fastadmin-dragsort": "^1.0.5",
"fastadmin-layer": "^3.5.6",
"fastadmin-selectpage": "^1.1.1",
"fastadmin-nicevalidator": "^1.1.6",
"art-template": "npm:fastadmin-arttemplate@^3.1.4",
"bootstrap-table": "npm:fastadmin-bootstraptable@^1.11.12",
"nice-validator": "npm:fastadmin-nicevalidator@^1.1.6",
"font-awesome": "^4.6.1",
"jquery": "^3.7.0",
"jquery": "^3.7.1",
"jquery-slimscroll": "~1.3.8",
"jquery.cookie": "~1.4.1",
"jstree": "~3.3.2",
"moment": "^2.10",
"require-css": "~0.1.8",
"sortablejs": "^1.12.0",
"tableexport.jquery.plugin": "^1.26.0",
"tableexport.jquery.plugin": "^1.20.0",
"toastr": "~2.1.3"
},
"author": "FastAdmin",
@ -45,11 +49,14 @@
"parse-config-file": "^1.0.4"
},
"overrides": {
"eonasdan-bootstrap-datetimepicker": {
"moment-timezone": "^0.5.0"
},
"canvg": {
"xmldom": "^0.7.0"
},
"tableexport.jquery.plugin": {
"xlsx": "npm:@e965/xlsx@^0.20.3"
},
"eonasdan-bootstrap-datetimepicker": {
"moment-timezone": "^0.5.35"
}
},
"dists": {
@ -60,20 +67,23 @@
"daterangepicker.css"
],
"bootstrap-select": "dist/**",
"bootstrap-slider": "dist/**",
"bootstrap-slider": [
"dist/**",
"*.css",
"*.js"
],
"coloris": [
"dist/umd/**",
"dist/*.css"
],
"eonasdan-bootstrap-datetimepicker": "build/**",
"fastadmin-addtabs": "*.js",
"fastadmin-bootstraptable": "dist/**",
"fastadmin-citypicker": "dist/**",
"fastadmin-cxselect": "js/**",
"fastadmin-dragsort": "*.js",
"fastadmin-layer": "dist/**",
"fastadmin-selectpage": "*",
"bootstrap-table": "dist/**",
"nice-validator": "dist/**",
"font-awesome": [
"css/**",
"fonts/**"
@ -86,11 +96,14 @@
"moment.js",
"locale/**"
],
"nice-validator": "dist/**",
"require-css": "*.js",
"sortablejs": "*.js",
"tableexport.jquery.plugin": "tableExport.min.js",
"toastr": [
"toastr.js",
"*.less",
"*.css",
"*.js",
"build/**"
]
}

View File

@ -11,7 +11,7 @@
@import url("../libs/nice-validator/dist/jquery.validator.css");
@import url("../libs/bootstrap-select/dist/css/bootstrap-select.min.css");
@import url("../libs/fastadmin-selectpage/selectpage.css");
@import url("../libs/bootstrap-slider/dist/css/bootstrap-slider.min.css");
@import url("../libs/bootstrap-slider/dist/css/bootstrap-slider.css");
.m-0 {
margin-top: 0px !important;
margin-right: 0px !important;

File diff suppressed because one or more lines are too long

View File

@ -1424,7 +1424,7 @@ select.form-control {
.input-lg + .form-control-feedback.fa,
.input-group-lg + .form-control-feedback.fa,
.form-group-lg .form-control + .form-control-feedback.fa {
line-height: 44px;
line-height: 45px;
}
.input-sm + .form-control-feedback.fa,
.input-group-sm + .form-control-feedback.fa,

View File

@ -2,7 +2,7 @@
@import url("../css/fastadmin.css");
@import url("../css/iconfont.css");
@import url("../libs/font-awesome/css/font-awesome.min.css");
@import url("../libs/toastr/build/toastr.min.css");
@import url("../libs/toastr/toastr.min.css");
@import url("../libs/fastadmin-layer/dist/theme/default/layer.css");
@import url("../libs/bootstrap-table/dist/bootstrap-table.min.css");
@import url("../libs/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css");
@ -10,7 +10,7 @@
@import url("../libs/nice-validator/dist/jquery.validator.css");
@import url("../libs/bootstrap-select/dist/css/bootstrap-select.min.css");
@import url("../libs/fastadmin-selectpage/selectpage.css");
@import url("../libs/bootstrap-slider/dist/css/bootstrap-slider.min.css");
@import url("../libs/bootstrap-slider/slider.css");
.m-0 {
margin-top: 0px !important;
margin-right: 0px !important;

File diff suppressed because one or more lines are too long

View File

@ -57,6 +57,7 @@ p {
margin-bottom: 20px;
}
#mainbody {
position: relative;
width: 100%;
@ -113,11 +114,15 @@ p {
@media (max-width: 767px) {
#mainbody > .container > .text-center {
padding: 130px 0 0 0;
height: calc(100vh - 261px);
}
#mainbody > .container > .text-center > h1 {
font-size: 50px;
margin-bottom: 20px;
}
@ -134,4 +139,3 @@ p {
font-size: 14px;
margin: 0;
}

View File

@ -22,10 +22,14 @@ define(['fast', 'template', 'moment'], function (Fast, Template, Moment) {
});
$.each(badgeList, function (k, v) {
var anchor = top.window.$("li a[addtabs][url='" + k + "']");
if (anchor) {
top.window.$(".pull-right-container", anchor).html(v);
top.window.$(".nav-addtabs li a[node-id='" + anchor.attr("addtabs") + "'] .pull-right-container").html(v);
}
if (!anchor||anchor.html()===undefined){
k = k.replace(Config.moduleurl+'/', "");
anchor=top.window.$("li a[addtabs][data-href='" + k + "']");
}
if (anchor&&v) {
top.window.$(".pull-right-container", anchor).html(v);
top.window.$(".nav-addtabs li a[node-id='" + anchor.attr("addtabs") + "'] .pull-right-container").html(v);
}
});
},
addtabs: function (url, title, icon) {

View File

@ -20,7 +20,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
sortName: '',
escape: false,
escape: true,
columns: [
[
{field: 'state', checkbox: true,},

View File

@ -207,9 +207,8 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
//这一行需要放在点击左侧链接事件之前
var addtabs = Config.referer ? sessionStorage.getItem("addtabs") : null;
console.log($("[data-config='simplenav']").prop("checked"))
//绑定tabs事件,如果需要点击强制刷新iframe,则请将iframeForceRefresh置为true,iframeForceRefreshTable只强制刷新表格
nav.addtabs({iframeHeight: "100%", iframeForceRefresh: false, iframeForceRefreshTable: true, simple: $("[data-config='simplenav']").prop("checked"), nav: nav});
nav.addtabs({iframeHeight: "100%", iframeForceRefresh: false, iframeForceRefreshTable: true, nav: nav});
if ($("ul.sidebar-menu li.active a").length > 0) {
$("ul.sidebar-menu li.active a").trigger("click");
@ -343,13 +342,6 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], functi
}, 0);
});
// 切换简洁模式菜单
$(document).on("click", "[data-config='simplenav']", function () {
var value = $(this).prop("checked") ? 1 : 0;
createCookie('simplenav', value);
location.reload();
});
// 切换多级菜单
$(document).on("click", "[data-config='multiplenav']", function () {
var value = $(this).prop("checked") ? 1 : 0;

View File

@ -21,7 +21,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'weigh',
escape: false,
escape: true,
columns: [
[
{checkbox: true},

View File

@ -21,6 +21,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'user.id',
fixedColumns: true,
fixedRightNumber: 1,
columns: [
[
{checkbox: true},

View File

@ -157,7 +157,7 @@
} else {
key = isArray ? value : key;
}
optionList.push(sprintf("<option value='" + key + "' %s>" + value + "</option>", key == vObjCol.defaultValue ? 'selected' : ''));
optionList.push(sprintf("<option value='" + Fast.api.escape(key) + "' %s>" + Fast.api.escape(value) + "</option>", key == vObjCol.defaultValue ? 'selected' : ''));
});
return optionList;
};
@ -215,16 +215,6 @@
op[name] = sym;
filter[name] = value;
});
if (that.options.searchCountTips) {
var count = 0;
$.each(filter, function (key, value) {
if ((value === '' || value == null || ($.isArray(value) && value.length === 0))) {
return true;
}
count++;
});
that.$toolbar.find(".btn-commonsearch > span").text(count).toggleClass("hidden", count === 0);
}
return {op: op, filter: filter};
};
@ -254,7 +244,6 @@
actionForm: "",
searchFormTemplate: "",
searchFormVisible: true,
searchCountTips: true,
searchClass: 'searchit',
showSearch: true,
renderDefault: true,
@ -322,11 +311,8 @@
html = [];
if (that.options.showSearch) {
html.push(sprintf('<div class="columns-%s pull-%s" style="margin-top:10px;margin-bottom:10px;">', this.options.buttonsAlign, this.options.buttonsAlign));
html.push(sprintf('<button class="btn btn-default btn-commonsearch %s' + '" type="button" name="commonSearch" title="%s">', that.options.iconSize === undefined ? '' : ' btn-' + that.options.iconSize, that.options.formatCommonSearch()));
if (that.options.searchCountTips) {
html.push(sprintf('<span class="label label-danger hidden">0</span>'));
}
html.push(sprintf('<i class="%s %s"></i>', that.options.iconsPrefix, that.options.icons.commonSearchIcon));
html.push(sprintf('<button class="btn btn-default%s' + '" type="button" name="commonSearch" title="%s">', that.options.iconSize === undefined ? '' : ' btn-' + that.options.iconSize, that.options.formatCommonSearch()));
html.push(sprintf('<i class="%s %s"></i>', that.options.iconsPrefix, that.options.icons.commonSearchIcon))
html.push('</button></div>');
}
if (that.$toolbar.find(".pull-right").length > 0) {

View File

@ -4,7 +4,7 @@
* @author: karson
* @version: v0.0.1
*
* @update 2017-06-24 <http://github.com/karsonzhang/fastadmin>
* @update 2017-06-24 <http://github.com/fastadminnet/fastadmin>
*/
!function ($) {

View File

@ -1,65 +1,34 @@
define(['fast', 'template', 'moment'], function (Fast, Template, Moment) {
var Frontend = {
api: {
//发送验证码
sendcaptcha: function (btn, type, data, success, error) {
$(btn).addClass("disabled", true).text("发送中...");
var si = {};
Frontend.api.ajax({url: $(btn).data("url"), data: data}, function (data, ret) {
clearInterval(si[type]);
var seconds = 60;
si[type] = setInterval(function () {
seconds--;
if (seconds <= 0) {
clearInterval(si);
$(btn).removeClass("disabled").text("发送验证码");
} else {
$(btn).addClass("disabled").text(seconds + "秒后可再次发送");
}
}, 1000);
if (typeof success == 'function') {
success.call(this, data, ret);
}
}, function (data, ret) {
$(btn).removeClass("disabled").text('发送验证码');
if (typeof error == 'function') {
error.call(this, data, ret);
}
});
},
//准备验证码
preparecaptcha: function (btn, type, data) {
require(['form'], function (Form) {
Layer.open({
title: '请完成验证',
type: 1,
content: Template("captchatpl", {}),
btnAlign: 'c',
success: function (layero, index) {
var form = $("form", layero);
form.data("validator-options", {
valid: function (ret) {
data.captcha = $("input[name=captcha]", form).val();
Frontend.api.sendcaptcha(btn, type, data, function (data, ret) {
Layer.close(index);
}, function (data, ret) {
$("img.captcha-img", form).trigger("click");
});
return true;
}
})
Form.api.bindevent(form);
}
});
});
}
},
api: Fast.api,
init: function () {
//点击发送验证码
var si = {};
//发送验证码
$(document).on("click", ".btn-captcha", function (e) {
var type = $(this).data("type") ? $(this).data("type") : 'mobile';
var btn = this;
Frontend.api.sendcaptcha = function (btn, type, data, callback) {
$(btn).addClass("disabled", true).text("发送中...");
Frontend.api.ajax({url: $(btn).data("url"), data: data}, function (data, ret) {
clearInterval(si[type]);
var seconds = 60;
si[type] = setInterval(function () {
seconds--;
if (seconds <= 0) {
clearInterval(si);
$(btn).removeClass("disabled").text("发送验证码");
} else {
$(btn).addClass("disabled").text(seconds + "秒后可再次发送");
}
}, 1000);
if (typeof callback == 'function') {
callback.call(this, data, ret);
}
}, function () {
$(btn).removeClass("disabled").text('发送验证码');
});
};
if (['mobile', 'email'].indexOf(type) > -1) {
var element = $(this).data("input-id") ? $("#" + $(this).data("input-id")) : $("input[name='" + type + "']", $(this).closest("form"));
var text = type === 'email' ? '邮箱' : '手机号码';
@ -78,13 +47,9 @@ define(['fast', 'template', 'moment'], function (Fast, Template, Moment) {
}
element.isValid(function (v) {
if (v) {
var data = {event: $(btn).data("event"), id: $(btn).data("id")};
var data = {event: $(btn).data("event")};
data[type] = element.val();
if ($("#captchatpl").length === 0) {
Frontend.api.sendcaptcha(btn, type, data);
} else {
Frontend.api.preparecaptcha(btn, type, data);
}
Frontend.api.sendcaptcha(btn, type, data);
} else {
Layer.msg("请确认已经输入了正确的" + text + "");
}
@ -92,12 +57,7 @@ define(['fast', 'template', 'moment'], function (Fast, Template, Moment) {
} else {
var data = {event: $(btn).data("event")};
Frontend.api.sendcaptcha(btn, type, data, function (data, ret) {
Layer.open({
title: false,
area: [Math.min($(window).width(), 400) + "px", "430px"],
content: "<img src='" + data.image + "' width='400' height='400' /><div class='text-center panel-title'>扫一扫关注公众号获取验证码</div>",
type: 1
});
Layer.open({title: false, area: ["400px", "430px"], content: "<img src='" + data.image + "' width='400' height='400' /><div class='text-center panel-title'>扫一扫关注公众号获取验证码</div>", type: 1});
});
}
return false;

View File

@ -4,8 +4,7 @@ define(['jquery', 'bootstrap', 'frontend', 'form', 'template'], function ($, und
$.each(errors, function (i, j) {
Layer.msg(j);
});
},
ignore: ':hidden'
}
};
var Controller = {
login: function () {
@ -46,18 +45,6 @@ define(['jquery', 'bootstrap', 'frontend', 'form', 'template'], function ($, und
}
});
});
//切换账号手机验证码登录
$(document).on("click", ".btn-switchlogin", function () {
var form = $(this).closest("form");
var current = $(this).data("type");
var type = current == 'mobile' ? 'account' : 'mobile';
var text = $(this).data(current + "-text");
$(this).text(text).data("type", type);
$("[data-login]").addClass("hidden");
$("[data-login='"+type+"']").removeClass("hidden");
form.attr("action", $(this).data(type + "-action"));
});
},
register: function () {
//本地验证未通过时提示

File diff suppressed because one or more lines are too long

View File

@ -18,7 +18,8 @@ require.config({
'adminlte': 'adminlte',
'bootstrap-table-commonsearch': 'bootstrap-table-commonsearch',
'bootstrap-table-template': 'bootstrap-table-template',
// 以下的包从libs目录加载
//
// 以下的包从bower的libs目录加载
'jquery': '../libs/jquery/dist/jquery.min',
'bootstrap': '../libs/bootstrap/dist/js/bootstrap.min',
'bootstrap-datetimepicker': '../libs/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min',
@ -26,15 +27,15 @@ require.config({
'bootstrap-select': '../libs/bootstrap-select/dist/js/bootstrap-select.min',
'bootstrap-select-lang': '../libs/bootstrap-select/dist/js/i18n/defaults-zh_CN',
'bootstrap-table': '../libs/bootstrap-table/dist/bootstrap-table.min',
'bootstrap-table-export': '../libs/bootstrap-table/dist/extensions/export/bootstrap-table-export',
'bootstrap-table-export': '../libs/bootstrap-table/dist/extensions/export/bootstrap-table-export.min',
'bootstrap-table-fixed-columns': '../libs/bootstrap-table/dist/extensions/fixed-columns/bootstrap-table-fixed-columns',
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile.min',
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile',
'bootstrap-table-lang': '../libs/bootstrap-table/dist/locale/bootstrap-table-zh-CN',
'bootstrap-table-jumpto': '../libs/bootstrap-table/dist/extensions/page-jumpto/bootstrap-table-jumpto',
'bootstrap-slider': '../libs/bootstrap-slider/dist/bootstrap-slider.min',
'tableexport': '../libs/tableexport.jquery.plugin/tableExport.min',
'bootstrap-slider': '../libs/bootstrap-slider/bootstrap-slider',
'tableexport': '../libs/tableExport.jquery.plugin/tableExport.min',
'dragsort': '../libs/fastadmin-dragsort/jquery.dragsort',
'sortable': '../libs/sortablejs/Sortable.min',
'sortable': '../libs/Sortable/Sortable.min',
'addtabs': '../libs/fastadmin-addtabs/jquery.addtabs',
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
'validator': '../libs/nice-validator/dist/jquery.validator',
@ -101,22 +102,13 @@ require.config({
deps: ['bootstrap', 'slimscroll'],
exports: '$.AdminLTE'
},
'table': [
'moment', 'moment/locale/zh-cn',
'bootstrap-table',
'bootstrap-table-lang', 'bootstrap-table-export', 'bootstrap-table-commonsearch', 'bootstrap-table-template',
'bootstrap-table-jumpto', 'bootstrap-table-fixed-columns'
'bootstrap-daterangepicker': [
'moment/locale/zh-cn'
],
'bootstrap-datetimepicker': [
'moment/locale/zh-cn',
],
'bootstrap-daterangepicker': ['moment', 'moment/locale/zh-cn'],
'bootstrap-datetimepicker': ['moment', 'moment/locale/zh-cn'],
'bootstrap-select-lang': ['bootstrap-select'],
'selectpage': {
deps: ['jquery'],
exports: '$.fn.extend'
},
'layer': {
deps: ['jquery']
},
'jstree': ['css!../libs/jstree/dist/themes/default/style.css'],
'validator-lang': ['validator'],
'citypicker': ['citypicker-data', 'css!../libs/fastadmin-citypicker/dist/css/city-picker.css']
@ -141,15 +133,6 @@ require(['jquery', 'bootstrap'], function ($, undefined) {
paths['lang'] = Config.moduleurl + '/ajax/lang?callback=define&controllername=' + Config.controllername + '&lang=' + Config.language;
// 避免目录冲突
paths['backend/'] = 'backend/';
// 如果是英文,则移除默认的定义
if (Config.language === 'en') {
$.each(requirejs.s.contexts._.config.paths, function (key, value) {
if (key.match(/\-lang$/)) {
define(key);
}
});
define('moment/locale/zh-cn');
}
require.config({paths: paths});
// 初始化

File diff suppressed because one or more lines are too long

View File

@ -325,16 +325,28 @@ define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], functio
}
data[match[1]][match[2]] = j.value;
});
var result = template ? [] : {};
//使用数组保存
var usearray = container.data("usearray") || false;
//保留空数据
var keepempty = container.data("keepempty") || false;
var result = template || usearray ? [] : {};
var keys = Object.keys(Object.values(data)[0] || {});
var isassociative = !usearray && keys.indexOf("value") > -1 && (keys.length === 1 || (keys.length === 2 && keys.indexOf("key") > -1));
if(isassociative && keys.length ===2){
result = {};
}
$.each(data, function (i, j) {
if (j) {
var keys = Object.keys(j);
if (keys.indexOf("value") > -1 && (keys.length === 1 || (keys.length === 2 && keys.indexOf("key") > -1))) {
if (isassociative) {
if (keys.length === 2) {
if (j.key != '') {
if (j.key != '' || keepempty) {
result['__PLACEHOLDKEY__' + j.key] = j.value;
}
} else {
//一维数组
result.push(j.value);
}
} else {

View File

@ -18,7 +18,8 @@ require.config({
'adminlte': 'adminlte',
'bootstrap-table-commonsearch': 'bootstrap-table-commonsearch',
'bootstrap-table-template': 'bootstrap-table-template',
// 以下的包从libs目录加载
//
// 以下的包从bower的libs目录加载
'jquery': '../libs/jquery/dist/jquery.min',
'bootstrap': '../libs/bootstrap/dist/js/bootstrap.min',
'bootstrap-datetimepicker': '../libs/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min',
@ -28,18 +29,17 @@ require.config({
'bootstrap-table': '../libs/bootstrap-table/dist/bootstrap-table.min',
'bootstrap-table-export': '../libs/bootstrap-table/dist/extensions/export/bootstrap-table-export.min',
'bootstrap-table-fixed-columns': '../libs/bootstrap-table/dist/extensions/fixed-columns/bootstrap-table-fixed-columns',
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile.min',
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile',
'bootstrap-table-lang': '../libs/bootstrap-table/dist/locale/bootstrap-table-zh-CN',
'bootstrap-table-jumpto': '../libs/bootstrap-table/dist/extensions/page-jumpto/bootstrap-table-jumpto',
'bootstrap-slider': '../libs/bootstrap-slider/dist/bootstrap-slider.min',
'tableexport': '../libs/tableexport.jquery.plugin/tableExport.min',
'tableexport': '../libs/tableExport.jquery.plugin/tableExport.min',
'dragsort': '../libs/fastadmin-dragsort/jquery.dragsort',
'sortable': '../libs/sortablejs/Sortable.min',
'sortable': '../libs/Sortable/Sortable.min',
'addtabs': '../libs/fastadmin-addtabs/jquery.addtabs',
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
'validator': '../libs/nice-validator/dist/jquery.validator',
'validator-lang': '../libs/nice-validator/dist/local/zh-CN',
'toastr': '../libs/toastr/build/toastr.min',
'toastr': '../libs/toastr/toastr',
'jstree': '../libs/jstree/dist/jstree.min',
'layer': '../libs/fastadmin-layer/dist/layer',
'cookie': '../libs/jquery.cookie/jquery.cookie',
@ -101,22 +101,13 @@ require.config({
deps: ['bootstrap', 'slimscroll'],
exports: '$.AdminLTE'
},
'table': [
'moment', 'moment/locale/zh-cn',
'bootstrap-table',
'bootstrap-table-lang', 'bootstrap-table-export', 'bootstrap-table-commonsearch', 'bootstrap-table-template',
'bootstrap-table-jumpto', 'bootstrap-table-fixed-columns'
'bootstrap-daterangepicker': [
'moment/locale/zh-cn'
],
'bootstrap-datetimepicker': [
'moment/locale/zh-cn',
],
'bootstrap-daterangepicker': ['moment', 'moment/locale/zh-cn'],
'bootstrap-datetimepicker': ['moment', 'moment/locale/zh-cn'],
'bootstrap-select-lang': ['bootstrap-select'],
'selectpage': {
deps: ['jquery'],
exports: '$.fn.extend'
},
'layer': {
deps: ['jquery']
},
'jstree': ['css!../libs/jstree/dist/themes/default/style.css'],
'validator-lang': ['validator'],
'citypicker': ['citypicker-data', 'css!../libs/fastadmin-citypicker/dist/css/city-picker.css']
@ -141,15 +132,6 @@ require(['jquery', 'bootstrap'], function ($, undefined) {
paths['lang'] = Config.moduleurl + '/ajax/lang?callback=define&controllername=' + Config.controllername + '&lang=' + Config.language;
// 避免目录冲突
paths['frontend/'] = 'frontend/';
// 如果是英文,则移除默认的定义
if (Config.language === 'en') {
$.each(requirejs.s.contexts._.config.paths, function (key, value) {
if (key.match(/\-lang$/)) {
define(key);
}
});
define('moment/locale/zh-cn');
}
require.config({paths: paths});
// 初始化
@ -159,13 +141,7 @@ require(['jquery', 'bootstrap'], function ($, undefined) {
//加载相应模块
if (Config.jsname) {
require([Config.jsname], function (Controller) {
if (Controller.hasOwnProperty(Config.actionname)) {
Controller[Config.actionname]();
} else {
if (Controller.hasOwnProperty("_empty")) {
Controller._empty();
}
}
Controller[Config.actionname] != undefined && Controller[Config.actionname]();
}, function (e) {
console.error(e);
// 这里可捕获模块加载的错误

File diff suppressed because one or more lines are too long

62
public/assets/js/require-table.js 100755 → 100644
View File

@ -1,4 +1,4 @@
define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table', 'bootstrap-table-lang', 'bootstrap-table-export', 'bootstrap-table-commonsearch', 'bootstrap-table-template', 'bootstrap-table-jumpto', 'bootstrap-table-fixed-columns'], function ($, undefined) {
define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table', 'bootstrap-table-lang', 'bootstrap-table-export', 'bootstrap-table-commonsearch', 'bootstrap-table-template', 'bootstrap-table-jumpto', 'bootstrap-table-fixed-columns'], function ($, undefined, Moment) {
var Table = {
list: {},
// Bootstrap-table 基础配置
@ -34,9 +34,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
singleSelect: false, //是否启用单选
showRefresh: false,
showJumpto: true,
locale: Config.language === 'en' ? 'en-US' : Config.language.replace(/\-(\w+)$/, function (value) {
return value.toUpperCase();
}),
locale: Config.language === 'zh-cn' ? 'zh-CN' : 'en-US',
showToggle: true,
showColumns: true,
pk: 'id',
@ -469,10 +467,8 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
toolbar.on('click', Table.config.delbtn, function () {
var that = this;
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(
message || __('Are you sure you want to delete the %s selected item?', ids.length),
__('Are you sure you want to delete the %s selected item?', ids.length),
{icon: 3, title: __('Warning'), offset: 0, shadeClose: true, btn: [__('OK'), __('Cancel')]},
function (index) {
Table.api.multi("del", ids, table, that);
@ -694,7 +690,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
top = left = undefined;
}
Layer.confirm(
$(that).data("confirm") || __('Are you sure you want to delete this item?'),
__('Are you sure you want to delete this item?'),
{icon: 3, title: __('Warning'), offset: [top, left], shadeClose: true, btn: [__('OK'), __('Cancel')]},
function (index) {
var table = $(that).closest('table');
@ -792,6 +788,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
if (typeof this.custom !== 'undefined') {
custom = $.extend(custom, this.custom);
}
value = row[this.field] || value;
value = value == null || value.length === 0 ? '' : value.toString();
var keys = typeof this.searchList === 'object' ? Object.keys(this.searchList) : [];
var index = keys.indexOf(value);
@ -804,8 +801,10 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
if (!display) {
display = __(value.charAt(0).toUpperCase() + value.slice(1));
}
value = Fast.api.escape(value);
display = Fast.api.escape(display);
var html = '<span class="text-' + color + '">' + (icon ? '<i class="' + icon + '"></i> ' : '') + display + '</span>';
if (typeof this.operate !== 'undefined' && this.operate != false) {
if (this.operate != false) {
html = '<a href="javascript:;" class="searchit" data-toggle="tooltip" title="' + __('Click to search %s', display) + '" data-field="' + this.field + '" data-value="' + value + '">' + html + '</a>';
}
return html;
@ -881,9 +880,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
}
if (typeof that.searchList === 'object' && typeof that.custom === 'undefined') {
var i = 0;
var searchValues = Object.keys(colorArr).map(function (e) {
return colorArr[e];
});
var searchValues = Object.values(colorArr);
$.each(that.searchList, function (key, val) {
if (typeof colorArr[key] == 'undefined') {
colorArr[key] = searchValues[i];
@ -894,7 +891,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
//渲染Flag
var html = [];
var arr = $.isArray(value) ? value : value !== '' ? value.split(',') : [];
var arr = $.isArray(value) ? value : value != '' ? value.split(',') : [];
var color, display, label;
$.each(arr, function (i, value) {
value = value == null || value.length === 0 ? '' : value.toString();
@ -902,6 +899,8 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
return true;
color = value && typeof colorArr[value] !== 'undefined' ? colorArr[value] : 'primary';
display = typeof that.searchList !== 'undefined' && typeof that.searchList[value] !== 'undefined' ? that.searchList[value] : __(value.charAt(0).toUpperCase() + value.slice(1));
value = Fast.api.escape(value);
display = Fast.api.escape(display);
label = '<span class="label label-' + color + '">' + display + '</span>';
if (that.operate) {
html.push('<a href="javascript:;" class="searchit" data-toggle="tooltip" title="' + __('Click to search %s', display) + '" data-field="' + field + '" data-value="' + value + '">' + label + '</a>');
@ -926,28 +925,23 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
var table = this.table;
// 操作配置
var options = table ? table.bootstrapTable('getOptions') : {};
var buttons = [];
var existBtn = [];
var defaultBtn = ['dragsort', 'edit', 'del'];
var tempButton = $.extend({}, Table.button, {});
(this.buttons || []).forEach(function (item, index) {
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]);
}
// 默认按钮组
var buttons = $.extend([], this.buttons || []);
// 所有按钮名称
var names = [];
buttons.forEach(function (item) {
names.push(item.name);
});
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');
}
,

View File

@ -173,8 +173,12 @@ define(['jquery', 'bootstrap', 'dropzone', 'template'], function ($, undefined,
options = $.extend(true, {}, options, $(this).data("upload-options") || {});
delete options.success;
delete options.url;
// delete options.params;
multipart = $.isArray(multipart) ? {} : multipart;
var params = $(this).data("params") || {};
var category = typeof params.category !== 'undefined' ? params.category : ($(this).data("category") || '');
if (category) {
// multipart.category = category;
}
Upload.list[id] = new Dropzone(this, $.extend({
url: url,

View File

@ -1,5 +1,5 @@
/** vim: et:ts=4:sw=4:sts=4
* @license RequireJS 2.3.2 Copyright jQuery Foundation and other contributors.
* @license RequireJS 2.3.7 Copyright jQuery Foundation and other contributors.
* Released under MIT license, https://github.com/requirejs/requirejs/blob/master/LICENSE
*/
//Not using strict: uneven strict support in browsers, #392, and causes
@ -11,7 +11,7 @@ var requirejs, require, define;
(function (global, setTimeout) {
var req, s, head, baseElement, dataMain, src,
interactiveScript, currentlyAddingScript, mainScript, subPath,
version = '2.3.2',
version = '2.3.7',
commentRegExp = /\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/mg,
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
jsSuffixRegExp = /\.js$/,
@ -33,7 +33,8 @@ var requirejs, require, define;
contexts = {},
cfg = {},
globalDefQueue = [],
useInteractive = false;
useInteractive = false,
disallowedProps = ['__proto__', 'constructor'];
//Could match something like ')//comment', do not lose the prefix to comment.
function commentReplace(match, singlePrefix) {
@ -94,7 +95,7 @@ var requirejs, require, define;
function eachProp(obj, func) {
var prop;
for (prop in obj) {
if (hasProp(obj, prop)) {
if (hasProp(obj, prop) && disallowedProps.indexOf(prop) == -1) {
if (func(obj[prop], prop)) {
break;
}
@ -165,7 +166,7 @@ var requirejs, require, define;
* @returns {Error}
*/
function makeError(id, msg, err, requireModules) {
var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#' + id);
var e = new Error(msg + '\nhttps://requirejs.org/docs/errors.html#' + id);
e.requireType = id;
e.requireModules = requireModules;
if (err) {
@ -440,7 +441,9 @@ var requirejs, require, define;
//Account for relative paths if there is a base name.
if (name) {
if (prefix) {
if (pluginModule && pluginModule.normalize) {
if (isNormalized) {
normalizedName = name;
} else if (pluginModule && pluginModule.normalize) {
//Plugin is loaded, use its normalize method.
normalizedName = pluginModule.normalize(name, function (name) {
return normalize(name, parentName, applyMap);
@ -972,7 +975,8 @@ var requirejs, require, define;
//prefix and name should already be normalized, no need
//for applying map config again either.
normalizedMap = makeModuleMap(map.prefix + '!' + name,
this.map.parentMap);
this.map.parentMap,
true);
on(normalizedMap,
'defined', bind(this, function (value) {
this.map.normalizedMap = normalizedMap;

File diff suppressed because one or more lines are too long

View File

@ -16,7 +16,7 @@
@import url("../libs/nice-validator/dist/jquery.validator.css");
@import url("../libs/bootstrap-select/dist/css/bootstrap-select.min.css");
@import url("../libs/fastadmin-selectpage/selectpage.css");
@import url("../libs/bootstrap-slider/dist/css/bootstrap-slider.min.css");
@import url("../libs/bootstrap-slider/dist/css/bootstrap-slider.css");
@import "tinycss.less";
@main-bg: #f1f4f6;

View File

@ -5,7 +5,7 @@
@import url("../css/fastadmin.css");
@import url("../css/iconfont.css");
@import url("../libs/font-awesome/css/font-awesome.min.css");
@import url("../libs/toastr/build/toastr.min.css");
@import url("../libs/toastr/toastr.min.css");
@import url("../libs/fastadmin-layer/dist/theme/default/layer.css");
@import url("../libs/bootstrap-table/dist/bootstrap-table.min.css");
@import url("../libs/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css");
@ -13,7 +13,7 @@
@import url("../libs/nice-validator/dist/jquery.validator.css");
@import url("../libs/bootstrap-select/dist/css/bootstrap-select.min.css");
@import url("../libs/fastadmin-selectpage/selectpage.css");
@import url("../libs/bootstrap-slider/dist/css/bootstrap-slider.min.css");
@import url("../libs/bootstrap-slider/slider.css");
@import "tinycss.less";
@primary-color: #007bff;