新增系统配置关联字段、城市专区类型

新增自定义数组类型标题
新增多选项卡配置
新增自定义皮肤配置
pull/192/MERGE
Karson 2020-08-21 23:25:34 +08:00
parent f36a3415d7
commit 3d9cde96a1
22 changed files with 1299 additions and 1085 deletions

View File

@ -321,6 +321,7 @@ CREATE TABLE `fa_config` (
`content` text NOT NULL COMMENT '变量字典数据',
`rule` varchar(100) NOT NULL DEFAULT '' COMMENT '验证规则',
`extend` varchar(255) NOT NULL DEFAULT '' COMMENT '扩展属性',
`setting` varchar(255) NOT NULL DEFAULT '' COMMENT '配置',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT='系统配置';
@ -329,23 +330,23 @@ CREATE TABLE `fa_config` (
-- Records of fa_config
-- ----------------------------
BEGIN;
INSERT INTO `fa_config` VALUES (1, 'name', 'basic', 'Site name', '请填写站点名称', 'string', '我的网站', '', 'required', '');
INSERT INTO `fa_config` VALUES (2, 'beian', 'basic', 'Beian', '粤ICP备15000000号-1', 'string', '', '', '', '');
INSERT INTO `fa_config` VALUES (3, 'cdnurl', 'basic', 'Cdn url', '如果静态资源使用第三方云储存请配置该值', 'string', '', '', '', '');
INSERT INTO `fa_config` VALUES (4, 'version', 'basic', 'Version', '如果静态资源有变动请重新配置该值', 'string', '1.0.1', '', 'required', '');
INSERT INTO `fa_config` VALUES (5, 'timezone', 'basic', 'Timezone', '', 'string', 'Asia/Shanghai', '', 'required', '');
INSERT INTO `fa_config` VALUES (6, 'forbiddenip', 'basic', 'Forbidden ip', '一行一条记录', 'text', '', '', '', '');
INSERT INTO `fa_config` VALUES (7, 'languages', 'basic', 'Languages', '', 'array', '{\"backend\":\"zh-cn\",\"frontend\":\"zh-cn\"}', '', 'required', '');
INSERT INTO `fa_config` VALUES (8, 'fixedpage', 'basic', 'Fixed page', '请尽量输入左侧菜单栏存在的链接', 'string', 'dashboard', '', 'required', '');
INSERT INTO `fa_config` VALUES (9, 'categorytype', 'dictionary', 'Category type', '', 'array', '{\"default\":\"Default\",\"page\":\"Page\",\"article\":\"Article\",\"test\":\"Test\"}', '', '', '');
INSERT INTO `fa_config` VALUES (10, 'configgroup', 'dictionary', 'Config group', '', 'array', '{\"basic\":\"Basic\",\"email\":\"Email\",\"dictionary\":\"Dictionary\",\"user\":\"User\",\"example\":\"Example\"}', '', '', '');
INSERT INTO `fa_config` VALUES (11, 'mail_type', 'email', 'Mail type', '选择邮件发送方式', 'select', '1', '[\"Please select\",\"SMTP\",\"Mail\"]', '', '');
INSERT INTO `fa_config` VALUES (12, 'mail_smtp_host', 'email', 'Mail smtp host', '错误的配置发送邮件会导致服务器超时', 'string', 'smtp.qq.com', '', '', '');
INSERT INTO `fa_config` VALUES (13, 'mail_smtp_port', 'email', 'Mail smtp port', '(不加密默认25,SSL默认465,TLS默认587)', 'string', '465', '', '', '');
INSERT INTO `fa_config` VALUES (14, 'mail_smtp_user', 'email', 'Mail smtp user', '(填写完整用户名)', 'string', '10000', '', '', '');
INSERT INTO `fa_config` VALUES (15, 'mail_smtp_pass', 'email', 'Mail smtp password', '(填写您的密码)', 'string', 'password', '', '', '');
INSERT INTO `fa_config` VALUES (16, 'mail_verify_type', 'email', 'Mail vertify type', 'SMTP验证方式[推荐SSL]', 'select', '2', '[\"None\",\"TLS\",\"SSL\"]', '', '');
INSERT INTO `fa_config` VALUES (17, 'mail_from', 'email', 'Mail from', '', 'string', '10000@qq.com', '', '', '');
INSERT INTO `fa_config` VALUES (1, 'name', 'basic', 'Site name', '请填写站点名称', 'string', '我的网站', '', 'required', '', '');
INSERT INTO `fa_config` VALUES (2, 'beian', 'basic', 'Beian', '粤ICP备15000000号-1', 'string', '', '', '', '', '');
INSERT INTO `fa_config` VALUES (3, 'cdnurl', 'basic', 'Cdn url', '如果全站静态资源使用第三方云储存请配置该值', 'string', '', '', '', '', '');
INSERT INTO `fa_config` VALUES (4, 'version', 'basic', 'Version', '如果静态资源有变动请重新配置该值', 'string', '1.0.1', '', 'required', '', '');
INSERT INTO `fa_config` VALUES (5, 'timezone', 'basic', 'Timezone', '', 'string', 'Asia/Shanghai', '', 'required', '', '');
INSERT INTO `fa_config` VALUES (6, 'forbiddenip', 'basic', 'Forbidden ip', '一行一条记录', 'text', '', '', '', '', '');
INSERT INTO `fa_config` VALUES (7, 'languages', 'basic', 'Languages', '', 'array', '{\"backend\":\"zh-cn\",\"frontend\":\"zh-cn\"}', '', 'required', '', '');
INSERT INTO `fa_config` VALUES (8, 'fixedpage', 'basic', 'Fixed page', '请尽量输入左侧菜单栏存在的链接', 'string', 'dashboard', '', 'required', '', '');
INSERT INTO `fa_config` VALUES (9, 'categorytype', 'dictionary', 'Category type', '', 'array', '{\"default\":\"Default\",\"page\":\"Page\",\"article\":\"Article\",\"test\":\"Test\"}', '', '', '', '');
INSERT INTO `fa_config` VALUES (10, 'configgroup', 'dictionary', 'Config group', '', 'array', '{\"basic\":\"Basic\",\"email\":\"Email\",\"dictionary\":\"Dictionary\",\"user\":\"User\",\"example\":\"Example\"}', '', '', '', '');
INSERT INTO `fa_config` VALUES (11, 'mail_type', 'email', 'Mail type', '选择邮件发送方式', 'select', '1', '[\"Please select\",\"SMTP\",\"Mail\"]', '', '', '');
INSERT INTO `fa_config` VALUES (12, 'mail_smtp_host', 'email', 'Mail smtp host', '错误的配置发送邮件会导致服务器超时', 'string', 'smtp.qq.com', '', '', '', '');
INSERT INTO `fa_config` VALUES (13, 'mail_smtp_port', 'email', 'Mail smtp port', '(不加密默认25,SSL默认465,TLS默认587)', 'string', '465', '', '', '', '');
INSERT INTO `fa_config` VALUES (14, 'mail_smtp_user', 'email', 'Mail smtp user', '(填写完整用户名)', 'string', '10000', '', '', '', '');
INSERT INTO `fa_config` VALUES (15, 'mail_smtp_pass', 'email', 'Mail smtp password', '(填写您的密码)', 'string', 'password', '', '', '', '');
INSERT INTO `fa_config` VALUES (16, 'mail_verify_type', 'email', 'Mail vertify type', 'SMTP验证方式[推荐SSL]', 'select', '2', '[\"None\",\"TLS\",\"SSL\"]', '', '', '');
INSERT INTO `fa_config` VALUES (17, 'mail_from', 'email', 'Mail from', '', 'string', '10000@qq.com', '', '', '', '');
COMMIT;
-- ----------------------------

View File

@ -5,6 +5,8 @@ namespace app\admin\controller\general;
use app\common\controller\Backend;
use app\common\library\Email;
use app\common\model\Config as ConfigModel;
use think\Cache;
use think\Db;
use think\Exception;
use think\Validate;
@ -21,7 +23,7 @@ class Config extends Backend
* @var \app\common\model\Config
*/
protected $model = null;
protected $noNeedRight = ['check', 'rulelist'];
protected $noNeedRight = ['check', 'rulelist', 'selectpage', 'get_fields_list'];
public function _initialize()
{
@ -82,7 +84,7 @@ class Config extends Backend
$params = $this->request->post("row/a", [], 'trim');
if ($params) {
foreach ($params as $k => &$v) {
$v = is_array($v) ? implode(',', $v) : $v;
$v = is_array($v) && $k !== 'setting' ? implode(',', $v) : $v;
}
if (in_array($params['type'], ['select', 'selects', 'checkbox', 'radio', 'array'])) {
$params['content'] = json_encode(ConfigModel::decode($params['content']), JSON_UNESCAPED_UNICODE);
@ -202,12 +204,12 @@ class Config extends Backend
if ($params) {
$config = $this->model->get($params);
if (!$config) {
return $this->success();
$this->success();
} else {
return $this->error(__('Name already exist'));
$this->error(__('Name already exist'));
}
} else {
return $this->error(__('Invalid parameters'));
$this->error(__('Invalid parameters'));
}
}
@ -262,7 +264,51 @@ class Config extends Backend
$this->error($email->getError());
}
} else {
return $this->error(__('Invalid parameters'));
$this->error(__('Invalid parameters'));
}
}
public function selectpage()
{
$id = $this->request->get("id/d");
$config = \app\common\model\Config::get($id);
if (!$config) {
$this->error(__('Invalid parameters'));
}
$setting = $config['setting'];
//自定义条件
$custom = isset($setting['conditions']) ? (array)json_decode($setting['conditions'], true) : [];
$custom = array_filter($custom);
$this->request->request(['showField' => $setting['field'], 'keyField' => $setting['primarykey'], 'custom' => $custom, 'searchField' => [$setting['field'], $setting['primarykey']]]);
$this->model = \think\Db::connect()->setTable($setting['table']);
return parent::selectpage();
}
/**
* 获取表列表
* @internal
*/
public function get_table_list()
{
$tableList = [];
$dbname = \think\Config::get('database.database');
$tableList = \think\Db::query("SELECT `TABLE_NAME` AS `name`,`TABLE_COMMENT` AS `title` FROM `information_schema`.`TABLES` where `TABLE_SCHEMA` = '{$dbname}';");
$this->success('', null, ['tableList' => $tableList]);
}
/**
* 获取表字段列表
* @internal
*/
public function get_fields_list()
{
$table = $this->request->request('table');
$dbname = \think\Config::get('database.database');
//从数据库中获取表字段信息
$sql = "SELECT `COLUMN_NAME` AS `name`,`COLUMN_COMMENT` AS `title`,`DATA_TYPE` AS `type` FROM `information_schema`.`columns` WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? ORDER BY ORDINAL_POSITION";
//加载主表的列
$fieldList = Db::query($sql, [$dbname, $table]);
$this->success("", null, ['fieldList' => $fieldList]);
}
}

View File

@ -33,7 +33,17 @@ return [
'Array' => '数组',
'Array key' => '键名',
'Array value' => '键值',
'City' => '城市地区',
'Selectpage' => '关联表',
'Selectpages' => '关联表(多选)',
'Custom' => '自定义',
'Please select table' => '关联表',
'Selectpage table' => '关联表',
'Selectpage primarykey' => '存储字段',
'Selectpage field' => '显示字段',
'Selectpage conditions' => '筛选条件',
'Field title' => '字段名',
'Field value' => '字段值',
'Content' => '数据列表',
'Rule' => '校验规则',
'Site name' => '站点名称',

View File

@ -8,6 +8,10 @@
<!-- Loading Bootstrap -->
<link href="__CDN__/assets/css/backend{$Think.config.app_debug?'':'.min'}.css?v={$Think.config.site.version}" 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">
{/if}
<!-- HTML5 shim, for IE6-8 support of HTML5 elements. All other JS at the end of file. -->
<!--[if lt IE 9]>
<script src="__CDN__/assets/js/html5shiv.js"></script>

View File

@ -59,35 +59,35 @@
<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_html} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}"/>
{/case}
{case text}
<textarea {$item.extend} name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
<textarea {$item.extend_html} name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
{/case}
{case editor}
<textarea {$item.extend} 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} 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>
{/case}
{case array}
<dl class="fieldlist" data-name="row[{$item.name}]">
<dl {$item.extend_html} class="fieldlist" data-name="row[{$item.name}]">
<dd>
<ins>{:__('Array key')}</ins>
<ins>{:__('Array value')}</ins>
<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>
</dl>
{/case}
{case date}
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend_html} type="text" name="row[{$item.name}]" value="{$item.value}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
{/case}
{case time}
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend_html} type="text" name="row[{$item.name}]" value="{$item.value}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
{/case}
{case datetime}
<input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value}" 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} type="text" name="row[{$item.name}]" value="{$item.value}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
{/case}
{case number}
<input {$item.extend} type="number" name="row[{$item.name}]" value="{$item.value}" class="form-control" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
<input {$item.extend_html} type="number" name="row[{$item.name}]" value="{$item.value}" class="form-control" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
{/case}
{case checkbox}
{foreach name="item.content" item="vo"}
@ -101,7 +101,7 @@
{/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_html} name="row[{$item.name}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip}" {$item.type=='selects'?'multiple':''}>
{foreach name="item.content" item="vo"}
<option value="{$key}" {in name="key" value="$item.value" }selected{/in}>{$vo}</option>
{/foreach}
@ -136,6 +136,15 @@
<label for="row[{$item.name}]-yes"><input id="row[{$item.name}]-yes" name="row[{$item.name}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip}" /> {:__('Yes')}</label>
<label for="row[{$item.name}]-no"><input id="row[{$item.name}]-no" name="row[{$item.name}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip}" /> {:__('No')}</label>
{/case}
{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}" />
</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}" />
{/case}
{case custom}
{$item.extend_html}
{/case}
@ -169,16 +178,6 @@
<div class="tab-pane fade" id="addcfg">
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="{:url('general.config/add')}">
{:token()}
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
<div class="col-xs-12 col-sm-4">
<select name="row[type]" class="form-control selectpicker">
{foreach name="typeList" item="vo"}
<option value="{$key}" {in name="key" value="string" }selected{/in}>{$vo}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
<div class="col-xs-12 col-sm-4">
@ -189,6 +188,16 @@
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
<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>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label for="name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-4">
@ -201,6 +210,52 @@
<input type="text" class="form-control" id="title" name="row[title]" value="" data-rule="required"/>
</div>
</div>
<div class="form-group hidden tf tf-selectpage tf-selectpages">
<label for="c-selectpage-table" class="control-label col-xs-12 col-sm-2">{:__('Selectpage table')}:</label>
<div class="col-xs-12 col-sm-4">
<select id="c-selectpage-table" name="row[setting][table]" class="form-control selectpicker" data-live-search="true">
<option value="">{:__('Please select table')}</option>
</select>
</div>
</div>
<div class="form-group hidden tf tf-selectpage tf-selectpages">
<label for="c-selectpage-primarykey" class="control-label col-xs-12 col-sm-2">{:__('Selectpage primarykey')}:</label>
<div class="col-xs-12 col-sm-4">
<select name="row[setting][primarykey]" class="form-control selectpicker" id="c-selectpage-primarykey"></select>
</div>
</div>
<div class="form-group hidden tf tf-selectpage tf-selectpages">
<label for="c-selectpage-field" class="control-label col-xs-12 col-sm-2">{:__('Selectpage field')}:</label>
<div class="col-xs-12 col-sm-4">
<select name="row[setting][field]" class="form-control selectpicker" id="c-selectpage-field"></select>
</div>
</div>
<div class="form-group hidden tf tf-selectpage tf-selectpages">
<label class="control-label col-xs-12 col-sm-2">{:__('Selectpage conditions')}:</label>
<div class="col-xs-12 col-sm-8">
<dl class="fieldlist" data-name="row[setting][conditions]">
<dd>
<ins>{:__('Field title')}</ins>
<ins>{:__('Field value')}</ins>
</dd>
<dd><a href="javascript:;" class="append btn btn-sm btn-success"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
<textarea name="row[setting][conditions]" class="form-control hide" cols="30" rows="5"></textarea>
</dl>
</div>
</div>
<div class="form-group hidden tf tf-array">
<label for="c-array-key" class="control-label col-xs-12 col-sm-2">{:__('Array key')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" name="row[setting][key]" class="form-control" id="c-array-key">
</div>
</div>
<div class="form-group hidden tf tf-array">
<label for="c-array-value" class="control-label col-xs-12 col-sm-2">{:__('Array value')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" name="row[setting][value]" class="form-control" id="c-array-value">
</div>
</div>
<div class="form-group">
<label for="value" class="control-label col-xs-12 col-sm-2">{:__('Value')}:</label>
<div class="col-xs-12 col-sm-4">

View File

@ -4,7 +4,7 @@
<!-- 加载样式及META信息 -->
{include file="common/meta" /}
</head>
<body class="hold-transition skin-green sidebar-mini fixed {if $Think.config.fastadmin.multiplenav}multiplenav{/if}" id="tabs">
<body class="hold-transition skin-green {$Think.config.fastadmin.adminskin} sidebar-mini fixed {:$Think.config.fastadmin.multipletab?'multipletab':''} {:$Think.config.fastadmin.multiplenav?'multiplenav':''}" id="tabs">
<div class="wrapper">

View File

@ -1,105 +1,121 @@
<!DOCTYPE html>
<html lang="{$config.language}">
<head>
{include file="common/meta" /}
<head>
{include file="common/meta" /}
<style type="text/css">
body {
color:#999;
background:url('{$background}');
background-size:cover;
}
a {
color:#fff;
}
.login-panel{margin-top:150px;}
<style type="text/css">
body {
color: #999;
background: url('{$background}');
background-size: cover;
}
a {
color: #fff;
}
.login-panel {
margin-top: 150px;
}
.login-screen {
max-width: 400px;
padding: 0;
margin: 100px auto 0 auto;
}
.login-screen .well {
border-radius: 3px;
-webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);
background: rgba(255, 255, 255, 0.2);
border: 1px solid rgba(227, 227, 227, 0.4);
}
.login-screen .input-group .input-group-addon, .login-screen input.form-control {
/*border-color: transparent;*/
}
.login-screen .copyright {
text-align: center;
}
@media (max-width: 767px) {
.login-screen {
max-width:400px;
padding:0;
margin:100px auto 0 auto;
padding: 0 20px;
}
}
}
.login-screen .well {
border-radius: 3px;
-webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
background: rgba(255,255,255, 0.2);
}
.login-screen .copyright {
text-align: center;
}
@media(max-width:767px) {
.login-screen {
padding:0 20px;
}
}
.profile-img-card {
width: 100px;
height: 100px;
margin: 10px auto;
display: block;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
}
.profile-name-card {
text-align: center;
}
.profile-img-card {
width: 100px;
height: 100px;
margin: 10px auto;
display: block;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
}
#login-form {
margin-top:20px;
}
#login-form .input-group {
margin-bottom:15px;
}
.profile-name-card {
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<div class="login-wrapper">
<div class="login-screen">
<div class="well">
<div class="login-form">
<img id="profile-img" class="profile-img-card" src="__CDN__/assets/img/avatar.png" />
<p id="profile-name" class="profile-name-card"></p>
#login-form {
margin-top: 20px;
}
<form action="" method="post" id="login-form">
<div id="errtips" class="hide"></div>
{:token()}
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></div>
<input type="text" class="form-control" id="pd-form-username" placeholder="{:__('Username')}" name="username" autocomplete="off" value="" data-rule="{:__('Username')}:required;username" />
</div>
#login-form .input-group {
margin-bottom: 15px;
}
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span></div>
<input type="password" class="form-control" id="pd-form-password" placeholder="{:__('Password')}" name="password" autocomplete="off" value="" data-rule="{:__('Password')}:required;password" />
</div>
{if $Think.config.fastadmin.login_captcha}
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-option-horizontal" aria-hidden="true"></span></div>
<input type="text" name="captcha" class="form-control" placeholder="{:__('Captcha')}" data-rule="{:__('Captcha')}:required;length(4)" />
<span class="input-group-addon" style="padding:0;border:none;cursor:pointer;">
</style>
</head>
<body>
<div class="container">
<div class="login-wrapper">
<div class="login-screen">
<div class="well">
<div class="login-form">
<img id="profile-img" class="profile-img-card" src="__CDN__/assets/img/avatar.png"/>
<p id="profile-name" class="profile-name-card"></p>
<form action="" method="post" id="login-form">
<div id="errtips" class="hide"></div>
{:token()}
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></div>
<input type="text" class="form-control" id="pd-form-username" placeholder="{:__('Username')}" name="username" autocomplete="off" value="" data-rule="{:__('Username')}:required;username"/>
</div>
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span></div>
<input type="password" class="form-control" id="pd-form-password" placeholder="{:__('Password')}" name="password" autocomplete="off" value="" data-rule="{:__('Password')}:required;password"/>
</div>
{if $Think.config.fastadmin.login_captcha}
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-option-horizontal" aria-hidden="true"></span></div>
<input type="text" name="captcha" class="form-control" placeholder="{:__('Captcha')}" data-rule="{:__('Captcha')}:required;length(4)"/>
<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>
</div>
{/if}
<div class="form-group checkbox">
<label class="inline" for="keeplogin">
<input type="checkbox" name="keeplogin" id="keeplogin" value="1" />
{:__('Keep login')}
</label>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success btn-lg btn-block">{:__('Sign in')}</button>
</div>
</form>
</div>
</div>
{/if}
<div class="form-group checkbox">
<label class="inline" for="keeplogin">
<input type="checkbox" name="keeplogin" id="keeplogin" value="1"/>
{:__('Keep login')}
</label>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success btn-lg btn-block">{:__('Sign in')}</button>
</div>
</form>
</div>
</div>
</div>
{include file="common/script" /}
</body>
</div>
</div>
{include file="common/script" /}
</body>
</html>

View File

@ -149,7 +149,7 @@ class Backend extends Controller
}
// 判断是否需要验证权限
if (!$this->auth->match($this->noNeedRight)) {
// 判断控制器和方法判断是否有对应权限
// 判断控制器和方法是否有对应权限
if (!$this->auth->check($path)) {
Hook::listen('admin_nopermission', $this);
$this->error(__('You have no permission'), '');

View File

@ -21,6 +21,9 @@ class Config extends Model
protected $append = [
'extend_html'
];
protected $type = [
'setting' => 'json',
];
/**
* 读取配置类型

View File

@ -273,10 +273,12 @@ return [
'login_background' => "/assets/img/loginbg.jpg",
//是否启用多级菜单导航
'multiplenav' => false,
//是否开启多选项卡(仅在开启多级菜单时起作用)
'multipletab' => true,
//后台皮肤,为空时表示使用skin-green
'adminskin' => '',
//允许跨域的域名,多个以,分隔
'cors_request_domain' => 'localhost,127.0.0.1',
//自动检测更新
'checkupdate' => false,
//版本号
'version' => '1.2.0',
//API接口地址

View File

@ -17,7 +17,7 @@
{include file="common/sidenav" /}
</div>
<div class="col-md-9">
<div class="panel panel-default ">
<div class="panel panel-default">
<div class="panel-body">
<h2 class="page-header">
{:__('Member center')}
@ -73,4 +73,4 @@
</div>
</div>
</div>
</div>
</div>

View File

@ -385,13 +385,6 @@ form.form-horizontal .control-label {
.nav-addtabs li:hover > .close-tab {
display: block;
}
.multiplenav .content-wrapper,
.multiplenav .right-side {
padding-top: 94px;
}
.multiplenav #firstnav .nav-addtabs {
padding-right: 450px;
}
#firstnav {
height: 50px;
border-bottom: 1px solid transparent;
@ -420,6 +413,7 @@ form.form-horizontal .control-label {
}
/*次栏菜单栏*/
#secondnav {
display: none;
height: 44px;
position: absolute;
top: 50px;
@ -495,6 +489,20 @@ form.form-horizontal .control-label {
border-color: #222e32;
color: #222e32;
}
.multiplenav .content-wrapper,
.multiplenav .right-side {
padding-top: 50px;
}
.multiplenav #firstnav .nav-addtabs {
padding-right: 450px;
}
.multipletab #secondnav {
display: block;
}
.multipletab.multiplenav .content-wrapper,
.multipletab.multiplenav .right-side {
padding-top: 94px;
}
.main-sidebar .sidebar-form {
overflow: visible;
}

File diff suppressed because one or more lines are too long

View File

@ -13,6 +13,7 @@ body {
body {
padding-top: 50px;
font-size: 13px;
background: #f4f6f8;
}
.dropdown:hover .dropdown-menu {
display: block;
@ -100,7 +101,10 @@ form.form-horizontal .control-label {
}
.panel-default {
padding: 0 15px;
border-color: #e4ecf3;
border: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
.panel-default > .panel-heading {
position: relative;
@ -109,6 +113,14 @@ form.form-horizontal .control-label {
background: #fff;
border-bottom: 1px solid #f5f5f5;
}
.panel-default h2.page-header {
margin-top: 0;
height: 50px;
line-height: 31px;
font-size: 18px;
padding: 10px 0;
border-bottom: 1px solid #f5f5f5;
}
.panel-default > .panel-heading .panel-title {
color: #313131;
}
@ -320,7 +332,6 @@ footer.footer .copyright a:hover {
-moz-background-clip: padding;
border-radius: 4px;
background-clip: padding-box;
border: 1px solid #e4ecf3;
}
.login-section {
margin: 50px auto;
@ -346,7 +357,7 @@ footer.footer .copyright a:hover {
font-size: 16px;
text-align: center;
color: #616161;
background-color: #f5f5f5;
background-color: #ececec;
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
@ -400,13 +411,6 @@ main.content {
padding: 20px 0 10px 0;
margin-bottom: 20px;
background-color: #fff;
-webkit-border-radius: 4px;
-webkit-background-clip: padding-box;
-moz-border-radius: 4px;
-moz-background-clip: padding;
border-radius: 4px;
background-clip: padding-box;
border: 1px solid #e4ecf3;
}
.sidenav .list-group:last-child {
margin-bottom: 0;
@ -439,7 +443,8 @@ main.content {
background-clip: padding-box;
}
.sidenav .list-group .list-group-item:hover {
background-color: #f5f5f5;
border-left: 2px solid rgba(245, 245, 245, 0.38);
background-color: rgba(245, 245, 245, 0.38);
}
.sidenav .list-group .list-group-item > a {
display: block;
@ -448,7 +453,7 @@ main.content {
}
.sidenav .list-group .list-group-item.active {
border-left: 2px solid #46c37b;
background-color: #f5f5f5;
background-color: rgba(245, 245, 245, 0.38);
}
.sidenav .list-group .list-group-item.active > a {
color: #46c37b;

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

View File

@ -101,10 +101,6 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart
myChart.resize();
});
$(document).on("click", ".btn-checkversion", function () {
top.window.$("[data-toggle=checkupdate]").trigger("click");
});
$(document).on("click", ".btn-refresh", function () {
setTimeout(function () {
myChart.resize();
@ -115,4 +111,4 @@ define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echart
};
return Controller;
});
});

View File

@ -27,6 +27,53 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
}, 1500);
});
//渲染关联显示字段和存储字段
var renderselect = function (id, data, defaultvalue) {
var html = [];
for (var i = 0; i < data.length; i++) {
html.push("<option value='" + data[i].name + "' " + (defaultvalue == data[i].name ? "selected" : "") + " data-subtext='" + data[i].title + "'>" + data[i].name + "</option>");
}
var select = $(id);
$(select).html(html.join(""));
select.trigger("change");
if (select.data("selectpicker")) {
select.selectpicker('refresh');
}
};
//关联表切换
$(document).on('change', "#c-selectpage-table", function (e, first) {
var that = this;
Fast.api.ajax({
url: "general/config/get_fields_list",
data: {table: $(that).val()},
}, function (data, ret) {
renderselect("#c-selectpage-primarykey", data.fieldList, first ? $("#c-selectpage-primarykey").data("value") : '');
renderselect("#c-selectpage-field", data.fieldList, first ? $("#c-selectpage-field").data("value") : '');
return false;
});
return false;
});
//如果编辑模式则渲染已知数据
if (['selectpage', 'selectpages'].indexOf($("#c-type").val()) > -1) {
$("#c-selectpage-table").trigger("change", true);
}
//切换类型时
$(document).on("change", "#c-type", function () {
var value = $(this).val();
$(".tf").addClass("hidden");
$(".tf.tf-" + value).removeClass("hidden");
if (["selectpage", "selectpages"].indexOf(value) > -1 && $("#c-selectpage-table option").size() == 1) {
//异步加载表列表
Fast.api.ajax({
url: "general/config/get_table_list",
}, function (data, ret) {
renderselect("#c-selectpage-table", data.tableList);
return false;
});
}
});
//切换显示隐藏变量字典列表
$(document).on("change", "form#add-form select[name='row[type]']", function (e) {
$("#add-content-container").toggleClass("hide", ['select', 'selects', 'checkbox', 'radio'].indexOf($(this).val()) > -1 ? false : true);

View File

@ -11258,7 +11258,7 @@ define('table',['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstr
});
});
//当内容渲染完成后
table.on('post-body.bs.table', function (e, settings, json, xhr) {
table.on('post-body.bs.table', function (e, data) {
$(Table.config.refreshbtn, toolbar).find(".fa").removeClass("fa-spin");
if ($(Table.config.checkboxtd + ":first", table).find("input[type='checkbox'][data-index]").size() > 0) {
// 拖拽选择,需要重新绑定事件

View File

@ -198,7 +198,7 @@ define(['jquery', 'bootstrap', 'moment', 'moment/locale/zh-cn', 'bootstrap-table
});
});
//当内容渲染完成后
table.on('post-body.bs.table', function (e, settings, json, xhr) {
table.on('post-body.bs.table', function (e, data) {
$(Table.config.refreshbtn, toolbar).find(".fa").removeClass("fa-spin");
if ($(Table.config.checkboxtd + ":first", table).find("input[type='checkbox'][data-index]").size() > 0) {
// 拖拽选择,需要重新绑定事件

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,7 @@ body {
body {
padding-top: 50px;
font-size:13px;
background:#f4f6f8;
}
.dropdown:hover .dropdown-menu {
@ -121,7 +122,8 @@ form.form-horizontal .control-label {
.panel-default {
padding: 0 15px;
border-color: #e4ecf3;
border: none;
.box-shadow(none);
> .panel-heading {
position: relative;
font-size: 16px;
@ -129,6 +131,14 @@ form.form-horizontal .control-label {
background: #fff;
border-bottom: 1px solid #f5f5f5;
}
h2.page-header {
margin-top:0;
height:50px;
line-height:31px;
font-size:18px;
padding:10px 0;
border-bottom: 1px solid #f5f5f5;
}
> .panel-heading {
.panel-title {
color: #313131;
@ -308,7 +318,6 @@ footer.footer{
padding: 15px;
margin-bottom: 20px;
.border-radius(4px);
border: 1px solid #e4ecf3;
}
.login-section {
margin: 50px auto;
@ -327,7 +336,7 @@ footer.footer{
font-size: 16px;
text-align: center;
color: #616161;
background-color: #f5f5f5;
background-color: #ececec;
.transition(all 0.3s ease);
&:hover {
background-color: #fafafa;
@ -377,8 +386,6 @@ main.content {
padding: 20px 0 10px 0;
margin-bottom: 20px;
background-color: #fff;
.border-radius(4px);
border: 1px solid #e4ecf3;
.list-group{
&:last-child {
margin-bottom: 0;
@ -399,7 +406,8 @@ main.content {
.border-radius(0);
}
&:hover {
background-color: #f5f5f5;
border-left: 2px solid rgba(245, 245, 245, 0.38);
background-color: rgba(245, 245, 245, 0.38);
}
> a {
display: block;
@ -408,7 +416,7 @@ main.content {
}
&.active {
border-left: 2px solid #46c37b;
background-color: #f5f5f5;
background-color: rgba(245, 245, 245, 0.38);
> a {
color: #46c37b;
}