diff --git a/application/admin/controller/Index.php b/application/admin/controller/Index.php
index 80d5ee4d..611f9fe6 100644
--- a/application/admin/controller/Index.php
+++ b/application/admin/controller/Index.php
@@ -105,7 +105,8 @@ class Index extends Backend
{
$this->redirect($url);
}
- $background = cdnurl(Config::get('fastadmin.login_background'));
+ $background = Config::get('fastadmin.login_background');
+ $background = stripos($background, 'http')===0 ? $background : config('site.cdnurl') . $background;
$this->view->assign('background', $background);
$this->view->assign('title', __('Login'));
Hook::listen("login_init", $this->request);
diff --git a/application/admin/controller/general/Config.php b/application/admin/controller/general/Config.php
index b594fda1..573a04e3 100644
--- a/application/admin/controller/general/Config.php
+++ b/application/admin/controller/general/Config.php
@@ -25,6 +25,9 @@ class Config extends Backend
$this->model = model('Config');
}
+ /**
+ * 查看
+ */
public function index()
{
$siteList = [];
@@ -48,10 +51,6 @@ class Config extends Backend
{
$value['value'] = explode(',', $value['value']);
}
- if ($value['type'] == 'array')
- {
- $value['value'] = (array) json_decode($value['value'], TRUE);
- }
$value['content'] = json_decode($value['content'], TRUE);
$siteList[$v['group']]['list'][] = $value;
}
@@ -119,6 +118,10 @@ class Config extends Backend
return $this->view->fetch();
}
+ /**
+ * 编辑
+ * @param null $ids
+ */
public function edit($ids = NULL)
{
if ($this->request->isPost())
diff --git a/application/admin/view/general/config/index.html b/application/admin/view/general/config/index.html
index 9013cd0b..9875aab4 100644
--- a/application/admin/view/general/config/index.html
+++ b/application/admin/view/general/config/index.html
@@ -54,20 +54,13 @@
{/case}
{case array}
-
+
-
{:__('Array key')}
{:__('Array value')}
- {foreach $item.value as $key => $vo}
- -
-
-
-
-
-
- {/foreach}
- - {:__('Append')}
+ - {:__('Append')}
+
{/case}
{case datetime}
diff --git a/application/common/library/Token.php b/application/common/library/Token.php
index d42679cf..2751f644 100644
--- a/application/common/library/Token.php
+++ b/application/common/library/Token.php
@@ -2,84 +2,158 @@
namespace app\common\library;
+use app\common\library\token\Driver;
+use think\App;
+use think\Config;
+use think\Log;
+
/**
* Token操作类
*/
class Token
{
+ /**
+ * @var array Token的实例
+ */
+ public static $instance = [];
/**
- * 存储Token
- * @param string $token Token
- * @param int $user_id 会员ID
- * @param int $expire 过期时长,0表示无限,单位秒
+ * @var object 操作句柄
*/
- public static function set($token, $user_id, $expire = 0)
+ public static $handler;
+
+ /**
+ * 连接Token驱动
+ * @access public
+ * @param array $options 配置数组
+ * @param bool|string $name Token连接标识 true 强制重新连接
+ * @return Driver
+ */
+ public static function connect(array $options = [], $name = false)
{
- $expiretime = $expire ? time() + $expire : 0;
- \app\common\model\Token::create(['token' => $token, 'user_id' => $user_id, 'expiretime' => $expiretime]);
- return TRUE;
+ $type = !empty($options['type']) ? $options['type'] : 'File';
+
+ if (false === $name) {
+ $name = md5(serialize($options));
+ }
+
+ if (true === $name || !isset(self::$instance[$name])) {
+ $class = false === strpos($type, '\\') ?
+ '\\app\\common\\library\\token\\driver\\' . ucwords($type) :
+ $type;
+
+ // 记录初始化信息
+ App::$debug && Log::record('[ TOKEN ] INIT ' . $type, 'info');
+
+ if (true === $name) {
+ return new $class($options);
+ }
+
+ self::$instance[$name] = new $class($options);
+ }
+
+ return self::$instance[$name];
}
/**
- * 获取Token内的信息
- * @param string $token
- * @return array
+ * 自动初始化Token
+ * @access public
+ * @param array $options 配置数组
+ * @return Driver
*/
- public static function get($token)
+ public static function init(array $options = [])
{
- $data = \app\common\model\Token::get($token);
- if ($data)
- {
- if (!$data['expiretime'] || $data['expiretime'] > time())
- {
- return $data;
- }
- else
- {
- self::delete($token);
+ if (is_null(self::$handler)) {
+ if (empty($options) && 'complex' == Config::get('token.type')) {
+ $default = Config::get('token.default');
+ // 获取默认Token配置,并连接
+ $options = Config::get('token.' . $default['type']) ?: $default;
+ } elseif (empty($options)) {
+ $options = Config::get('token');
}
+
+ self::$handler = self::connect($options);
}
- return [];
+
+ return self::$handler;
+ }
+
+ /**
+ * 判断Token是否可用(check别名)
+ * @access public
+ * @param string $token Token标识
+ * @return bool
+ */
+ public static function has($token, $user_id)
+ {
+ return self::check($token, $user_id);
}
/**
* 判断Token是否可用
- * @param string $token Token
- * @param int $user_id 会员ID
- * @return boolean
+ * @param string $token Token标识
+ * @return bool
*/
public static function check($token, $user_id)
{
- $data = self::get($token);
- return $data && $data['user_id'] == $user_id ? true : false;
+ return self::init()->check($token, $user_id);
+ }
+
+ /**
+ * 读取Token
+ * @access public
+ * @param string $token Token标识
+ * @param mixed $default 默认值
+ * @return mixed
+ */
+ public static function get($token, $default = false)
+ {
+ return self::init()->get($token, $default);
+ }
+
+ /**
+ * 写入Token
+ * @access public
+ * @param string $token Token标识
+ * @param mixed $user_id 存储数据
+ * @param int|null $expire 有效时间 0为永久
+ * @return boolean
+ */
+ public static function set($token, $user_id, $expire = null)
+ {
+ return self::init()->set($token, $user_id, $expire);
+ }
+
+ /**
+ * 删除Token(delete别名)
+ * @access public
+ * @param string $token Token标识
+ * @return boolean
+ */
+ public static function rm($token)
+ {
+ return self::delete($token);
}
/**
* 删除Token
- * @param string $token
- * @return boolean
+ * @param string $token 标签名
+ * @return bool
*/
public static function delete($token)
{
- $data = \app\common\model\Token::get($token);
- if ($data)
- {
- $data->delete();
- return true;
- }
- return false;
+ return self::init()->delete($token);
}
/**
- * 删除指定用户的所有Token
- * @param int $user_id
- * @return boolean
+ * 清除Token
+ * @access public
+ * @param string $token Token标记
+ * @return boolean
*/
- public static function clear($user_id)
+ public static function clear($user_id = null)
{
- \app\common\model\Token::where('user_id', $user_id)->delete();
- return true;
+ return self::init()->clear($user_id);
}
}
diff --git a/application/common/library/token/Driver.php b/application/common/library/token/Driver.php
new file mode 100644
index 00000000..7e2dfa77
--- /dev/null
+++ b/application/common/library/token/Driver.php
@@ -0,0 +1,91 @@
+
+// +----------------------------------------------------------------------
+
+namespace app\common\library\token;
+
+/**
+ * Token基础类
+ */
+abstract class Driver
+{
+ protected $handler = null;
+ protected $options = [];
+
+ /**
+ * 存储Token
+ * @param string $token Token
+ * @param int $user_id 会员ID
+ * @param int $expire 过期时长,0表示无限,单位秒
+ * @return bool
+ */
+ abstract function set($token, $user_id, $expire = 0);
+
+ /**
+ * 获取Token内的信息
+ * @param string $token
+ * @return array
+ */
+ abstract function get($token);
+
+ /**
+ * 判断Token是否可用
+ * @param string $token Token
+ * @param int $user_id 会员ID
+ * @return boolean
+ */
+ abstract function check($token, $user_id);
+
+ /**
+ * 删除Token
+ * @param string $token
+ * @return boolean
+ */
+ abstract function delete($token);
+
+ /**
+ * 删除指定用户的所有Token
+ * @param int $user_id
+ * @return boolean
+ */
+ abstract function clear($user_id);
+
+ /**
+ * 返回句柄对象,可执行其它高级方法
+ *
+ * @access public
+ * @return object
+ */
+ public function handler()
+ {
+ return $this->handler;
+ }
+
+ /**
+ * 获取加密后的Token
+ * @param string $token Token标识
+ * @return string
+ */
+ protected function getEncryptedToken($token)
+ {
+ $config = \think\Config::get('token');
+ return hash_hmac($config['hashalgo'], $token, $config['key']);
+ }
+
+ /**
+ * 获取过期剩余时长
+ * @param $expiretime
+ * @return float|int|mixed
+ */
+ protected function getExpiredIn($expiretime)
+ {
+ return $expiretime ? max(0, $expiretime - time()) : 365 * 86400;
+ }
+}
diff --git a/application/common/library/token/driver/Mysql.php b/application/common/library/token/driver/Mysql.php
new file mode 100644
index 00000000..c61fcd6f
--- /dev/null
+++ b/application/common/library/token/driver/Mysql.php
@@ -0,0 +1,112 @@
+ 'user_token',
+ 'expire' => 2592000,
+ 'connection' => [],
+ ];
+
+
+ /**
+ * 构造函数
+ * @param array $options 参数
+ * @access public
+ */
+ public function __construct($options = [])
+ {
+ if (!empty($options)) {
+ $this->options = array_merge($this->options, $options);
+ }
+ if ($this->options['connection']) {
+ $this->handler = \think\Db::connect($this->options['connection'])->name($this->options['table']);
+ } else {
+ $this->handler = \think\Db::name('user_token');
+ }
+ }
+
+ /**
+ * 存储Token
+ * @param string $token Token
+ * @param int $user_id 会员ID
+ * @param int $expire 过期时长,0表示无限,单位秒
+ * @return bool
+ */
+ public function set($token, $user_id, $expire = null)
+ {
+ $expiretime = !is_null($expire) ? time() + $expire : ($expire === 0 ? 0 : time() + $this->options['expire']);
+ $token = $this->getEncryptedToken($token);
+ $this->handler->insert(['token' => $token, 'user_id' => $user_id, 'createtime' => time(), 'expiretime' => $expiretime]);
+ return TRUE;
+ }
+
+ /**
+ * 获取Token内的信息
+ * @param string $token
+ * @return array
+ */
+ public function get($token)
+ {
+ $data = $this->handler->where('token', $this->getEncryptedToken($token))->find();
+ if ($data) {
+ if (!$data['expiretime'] || $data['expiretime'] > time()) {
+ //返回未加密的token给客户端使用
+ $data['token'] = $token;
+ //返回剩余有效时间
+ $data['expired_in'] = $this->getExpiredIn($data['expiretime']);
+ return $data;
+ } else {
+ self::delete($token);
+ }
+ }
+ return [];
+ }
+
+ /**
+ * 判断Token是否可用
+ * @param string $token Token
+ * @param int $user_id 会员ID
+ * @return boolean
+ */
+ public function check($token, $user_id)
+ {
+ $data = $this->get($token);
+ return $data && $data['user_id'] == $user_id ? true : false;
+ }
+
+ /**
+ * 删除Token
+ * @param string $token
+ * @return boolean
+ */
+ public function delete($token)
+ {
+ $this->handler->where('token', $this->getEncryptedToken($token))->delete();
+ return true;
+ }
+
+ /**
+ * 删除指定用户的所有Token
+ * @param int $user_id
+ * @return boolean
+ */
+ public function clear($user_id)
+ {
+ $this->handler->where('user_id', $user_id)->delete();
+ return true;
+ }
+
+}
diff --git a/application/common/library/token/driver/Redis.php b/application/common/library/token/driver/Redis.php
new file mode 100644
index 00000000..877da4c5
--- /dev/null
+++ b/application/common/library/token/driver/Redis.php
@@ -0,0 +1,166 @@
+ '127.0.0.1',
+ 'port' => 6379,
+ 'password' => '',
+ 'select' => 0,
+ 'timeout' => 0,
+ 'expire' => 0,
+ 'persistent' => false,
+ 'userprefix' => 'up:',
+ 'tokenprefix' => 'tp:',
+ ];
+
+ /**
+ * 构造函数
+ * @param array $options 缓存参数
+ * @throws \BadFunctionCallException
+ * @access public
+ */
+ public function __construct($options = [])
+ {
+ if (!extension_loaded('redis')) {
+ throw new \BadFunctionCallException('not support: redis');
+ }
+ if (!empty($options)) {
+ $this->options = array_merge($this->options, $options);
+ }
+ $this->handler = new \Redis;
+ if ($this->options['persistent']) {
+ $this->handler->pconnect($this->options['host'], $this->options['port'], $this->options['timeout'], 'persistent_id_' . $this->options['select']);
+ } else {
+ $this->handler->connect($this->options['host'], $this->options['port'], $this->options['timeout']);
+ }
+
+ if ('' != $this->options['password']) {
+ $this->handler->auth($this->options['password']);
+ }
+
+ if (0 != $this->options['select']) {
+ $this->handler->select($this->options['select']);
+ }
+ }
+
+ /**
+ * 获取加密后的Token
+ * @param string $token Token标识
+ * @return string
+ */
+ protected function getEncryptedToken($token)
+ {
+ $config = \think\Config::get('token');
+ return $this->options['tokenprefix'] . hash_hmac($config['hashalgo'], $token, $config['key']);
+ }
+
+ /**
+ * 获取会员的key
+ * @param $user_id
+ * @return string
+ */
+ protected function getUserKey($user_id)
+ {
+ return $this->options['userprefix'] . $user_id;
+ }
+
+ /**
+ * 存储Token
+ * @param string $token Token
+ * @param int $user_id 会员ID
+ * @param int $expire 过期时长,0表示无限,单位秒
+ * @return bool
+ */
+ public function set($token, $user_id, $expire = 0)
+ {
+ if (is_null($expire)) {
+ $expire = $this->options['expire'];
+ }
+ if ($expire instanceof \DateTime) {
+ $expire = $expire->getTimestamp() - time();
+ }
+ $key = $this->getEncryptedToken($token);
+ if ($expire) {
+ $result = $this->handler->setex($key, $expire, $user_id);
+ } else {
+ $result = $this->handler->set($key, $user_id);
+ }
+ //写入会员关联的token
+ $this->handler->sAdd($this->getUserKey($user_id), $key);
+ return $result;
+ }
+
+ /**
+ * 获取Token内的信息
+ * @param string $token
+ * @return array
+ */
+ public function get($token)
+ {
+ $key = $this->getEncryptedToken($token);
+ $value = $this->handler->get($key);
+ if (is_null($value) || false === $value) {
+ return [];
+ }
+ //获取有效期
+ $expire = $this->handler->ttl($key);
+ $expire = $expire < 0 ? 365 * 86400 : $expire;
+ $expiretime = time() + $expire;
+ $result = ['token' => $token, 'user_id' => $value, 'expiretime' => $expiretime, 'expired_in' => $expire];
+
+ return $result;
+ }
+
+ /**
+ * 判断Token是否可用
+ * @param string $token Token
+ * @param int $user_id 会员ID
+ * @return boolean
+ */
+ public function check($token, $user_id)
+ {
+ $data = self::get($token);
+ return $data && $data['user_id'] == $user_id ? true : false;
+ }
+
+ /**
+ * 删除Token
+ * @param string $token
+ * @return boolean
+ */
+ public function delete($token)
+ {
+ $data = $this->get($token);
+ if ($data) {
+ $key = $this->getEncryptedToken($token);
+ $user_id = $data['user_id'];
+ $this->handler->del($key);
+ $this->handler->sRem($this->getUserKey($user_id), $key);
+ }
+ return true;
+
+ }
+
+ /**
+ * 删除指定用户的所有Token
+ * @param int $user_id
+ * @return boolean
+ */
+ public function clear($user_id)
+ {
+ $keys = $this->handler->sMembers($this->getUserKey($user_id));
+ $this->handler->del($this->getUserKey($user_id));
+ $this->handler->del($keys);
+ return true;
+ }
+
+}
diff --git a/application/common/model/Token.php b/application/common/model/Token.php
deleted file mode 100644
index 978d362f..00000000
--- a/application/common/model/Token.php
+++ /dev/null
@@ -1,36 +0,0 @@
- true
],
+ // +----------------------------------------------------------------------
+ // | Token设置
+ // +----------------------------------------------------------------------
+ 'token' => [
+ // 驱动方式
+ 'type' => 'Redis',
+ // 缓存前缀
+ 'key' => 'i3d6o32wo8fvs1fvdpwens',
+ // 加密方式
+ 'hashalgo' => 'ripemd160',
+ // 缓存有效期 0表示永久缓存
+ 'expire' => 0,
+ ],
//FastAdmin配置
'fastadmin' => [
+ //是否开启前台会员中心
+ 'usercenter' => true,
//登录验证码
'login_captcha' => true,
//是否同一账号同一时间只能在一个地方登录
@@ -253,7 +268,8 @@ return [
//自动检测更新
'checkupdate' => false,
//版本号
- 'version' => '1.0.0.20180327_beta',
+ 'version' => '1.0.0.20180401_beta',
+ //API接口地址
'api_url' => 'https://api.fastadmin.net',
],
];
diff --git a/application/index/controller/Index.php b/application/index/controller/Index.php
index 78f23599..ba5aaf4d 100755
--- a/application/index/controller/Index.php
+++ b/application/index/controller/Index.php
@@ -3,6 +3,7 @@
namespace app\index\controller;
use app\common\controller\Frontend;
+use app\common\library\Token;
class Index extends Frontend
{
diff --git a/application/index/controller/User.php b/application/index/controller/User.php
index 73e66abc..04ed25bd 100644
--- a/application/index/controller/User.php
+++ b/application/index/controller/User.php
@@ -3,6 +3,7 @@
namespace app\index\controller;
use app\common\controller\Frontend;
+use think\Config;
use think\Cookie;
use think\Hook;
use think\Session;
@@ -23,27 +24,30 @@ class User extends Frontend
parent::_initialize();
$auth = $this->auth;
+ if (!Config::get('fastadmin.usercenter')) {
+ $this->error(__('User center already closed'));
+ }
+
$ucenter = get_addon_info('ucenter');
- if ($ucenter && $ucenter['state'])
- {
+ if ($ucenter && $ucenter['state']) {
include ADDON_PATH . 'ucenter' . DS . 'uc.php';
}
//监听注册登录注销的事件
- Hook::add('user_login_successed', function($user) use($auth) {
+ Hook::add('user_login_successed', function ($user) use ($auth) {
$expire = input('post.keeplogin') ? 30 * 86400 : 0;
Cookie::set('uid', $user->id, $expire);
Cookie::set('token', $auth->getToken(), $expire);
});
- Hook::add('user_register_successed', function($user) use($auth) {
+ Hook::add('user_register_successed', function ($user) use ($auth) {
Cookie::set('uid', $user->id);
Cookie::set('token', $auth->getToken());
});
- Hook::add('user_delete_successed', function($user) use($auth) {
+ Hook::add('user_delete_successed', function ($user) use ($auth) {
Cookie::delete('uid');
Cookie::delete('token');
});
- Hook::add('user_logout_successed', function($user) use($auth) {
+ Hook::add('user_logout_successed', function ($user) use ($auth) {
Cookie::delete('uid');
Cookie::delete('token');
});
@@ -66,8 +70,7 @@ class User extends Frontend
$url = $this->request->request('url', url('user/index'));
if ($this->auth->id)
$this->success(__('You\'ve logged in, do not login again'), $url);
- if ($this->request->isPost())
- {
+ if ($this->request->isPost()) {
$username = $this->request->post('username');
$password = $this->request->post('password');
$email = $this->request->post('email');
@@ -103,23 +106,18 @@ class User extends Frontend
];
$validate = new Validate($rule, $msg);
$result = $validate->check($data);
- if (!$result)
- {
+ if (!$result) {
$this->error(__($validate->getError()));
}
- if ($this->auth->register($username, $password, $email, $mobile))
- {
+ if ($this->auth->register($username, $password, $email, $mobile)) {
$synchtml = '';
////////////////同步到Ucenter////////////////
- if (defined('UC_STATUS') && UC_STATUS)
- {
+ if (defined('UC_STATUS') && UC_STATUS) {
$uc = new \addons\ucenter\library\client\Client();
$synchtml = $uc->uc_user_synregister($this->auth->id, $password);
}
$this->success(__('Sign up successful') . $synchtml, $url);
- }
- else
- {
+ } else {
$this->error($this->auth->getError());
}
}
@@ -136,11 +134,10 @@ class User extends Frontend
$url = $this->request->request('url', url('user/index'));
if ($this->auth->id)
$this->success(__('You\'ve logged in, do not login again'), $url);
- if ($this->request->isPost())
- {
+ if ($this->request->isPost()) {
$account = $this->request->post('account');
$password = $this->request->post('password');
- $keeplogin = (int) $this->request->post('keeplogin');
+ $keeplogin = (int)$this->request->post('keeplogin');
$token = $this->request->post('__token__');
$rule = [
'account' => 'require|length:3,50',
@@ -161,24 +158,19 @@ class User extends Frontend
];
$validate = new Validate($rule, $msg);
$result = $validate->check($data);
- if (!$result)
- {
+ if (!$result) {
$this->error(__($validate->getError()));
return FALSE;
}
- if ($this->auth->login($account, $password))
- {
+ if ($this->auth->login($account, $password)) {
$synchtml = '';
////////////////同步到Ucenter////////////////
- if (defined('UC_STATUS') && UC_STATUS)
- {
+ if (defined('UC_STATUS') && UC_STATUS) {
$uc = new \addons\ucenter\library\client\Client();
$synchtml = $uc->uc_user_synlogin($this->auth->id);
}
$this->success(__('Logged in successful') . $synchtml, $url);
- }
- else
- {
+ } else {
$this->error($this->auth->getError());
}
}
@@ -195,8 +187,7 @@ class User extends Frontend
$this->auth->logout();
$synchtml = '';
////////////////同步到Ucenter////////////////
- if (defined('UC_STATUS') && UC_STATUS)
- {
+ if (defined('UC_STATUS') && UC_STATUS) {
$uc = new \addons\ucenter\library\client\Client();
$synchtml = $uc->uc_user_synlogout();
}
@@ -217,8 +208,7 @@ class User extends Frontend
*/
public function changepwd()
{
- if ($this->request->isPost())
- {
+ if ($this->request->isPost()) {
$oldpassword = $this->request->post("oldpassword");
$newpassword = $this->request->post("newpassword");
$renewpassword = $this->request->post("renewpassword");
@@ -245,26 +235,21 @@ class User extends Frontend
];
$validate = new Validate($rule, $msg, $field);
$result = $validate->check($data);
- if (!$result)
- {
+ if (!$result) {
$this->error(__($validate->getError()));
return FALSE;
}
$ret = $this->auth->changepwd($newpassword, $oldpassword);
- if ($ret)
- {
+ if ($ret) {
$synchtml = '';
////////////////同步到Ucenter////////////////
- if (defined('UC_STATUS') && UC_STATUS)
- {
+ if (defined('UC_STATUS') && UC_STATUS) {
$uc = new \addons\ucenter\library\client\Client();
$synchtml = $uc->uc_user_synlogout();
}
$this->success(__('Reset password successful') . $synchtml, url('user/login'));
- }
- else
- {
+ } else {
$this->error($this->auth->getError());
}
}
diff --git a/application/index/lang/zh-cn.php b/application/index/lang/zh-cn.php
index e2e141f2..9c5c85c3 100755
--- a/application/index/lang/zh-cn.php
+++ b/application/index/lang/zh-cn.php
@@ -81,6 +81,7 @@ return [
'Github' => 'Github',
'QQ group' => 'QQ群',
'Go to Dashboard' => '登录后台',
+ 'Go to Member center' => '会员中心',
'Contribution' => '为FastAdmin贡献代码!',
'Copyrights' => '版权所有',
'Responsive' => '响应式开发',
diff --git a/application/index/lang/zh-cn/user.php b/application/index/lang/zh-cn/user.php
index 0f1fcf08..1ca3c238 100755
--- a/application/index/lang/zh-cn/user.php
+++ b/application/index/lang/zh-cn/user.php
@@ -59,6 +59,7 @@ return [
'Sign up successful' => '注册成功',
'Logged in successful' => '登录成功',
'Logout successful' => '注销成功',
+ 'User center already closed' => '会员中心已经关闭',
'Operation failed' => '操作失败',
'Invalid parameters' => '参数不正确',
'Change password failure' => '修改密码失败',
diff --git a/application/index/view/index/index.html b/application/index/view/index/index.html
index 0e4571fb..0ff5b96d 100755
--- a/application/index/view/index/index.html
+++ b/application/index/view/index/index.html
@@ -62,7 +62,8 @@
diff --git a/public/assets/js/require-backend.min.js b/public/assets/js/require-backend.min.js
index 1f5d6107..8896312c 100644
--- a/public/assets/js/require-backend.min.js
+++ b/public/assets/js/require-backend.min.js
@@ -11148,6 +11148,7 @@ define('validator',['validator-core', 'validator-lang'], function (Validator, un
define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, Upload, Validator) {
var Form = {
config: {
+ fieldlisttpl: '-
'
},
events: {
validator: function (form, success, error, submit) {
@@ -11173,7 +11174,7 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
},
target: function (input) {
var $formitem = $(input).closest('.form-group'),
- $msgbox = $formitem.find('span.msg-box');
+ $msgbox = $formitem.find('span.msg-box');
if (!$msgbox.length) {
return [];
}
@@ -11269,7 +11270,8 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
citypicker: function (form) {
//绑定城市远程插件
if ($("[data-toggle='city-picker']", form).size() > 0) {
- require(['citypicker'], function () {});
+ require(['citypicker'], function () {
+ });
}
},
datetimepicker: function (form) {
@@ -11387,27 +11389,90 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
}
},
fieldlist: function (form) {
+ //绑定fieldlist
if ($(".fieldlist", form).size() > 0) {
- $(".fieldlist", form).on("click", ".append", function () {
- var rel = parseInt($(this).closest("dl").attr("rel")) + 1;
- var name = $(this).closest("dl").data("name");
- $(this).closest("dl").attr("rel", rel);
- $('-
').insertBefore($(this).parent());
- });
- $(".fieldlist", form).on("click", "dd .btn-remove", function () {
- $(this).parent().remove();
- });
- //拖拽排序
- require(['dragsort'], function () {
- //绑定拖动排序
+ require(['dragsort', 'template'], function (undefined, Template) {
+ //刷新隐藏textarea的值
+ var refresh = function (name) {
+ var data = {};
+ var textarea = $("textarea[name='" + name + "']", form);
+ var container = textarea.closest("dl");
+ var template = container.data("template");
+ console.log(name, container);
+ $.each($("input,select", container).serializeArray(), function (i, j) {
+ var reg = /\[(\w+)\]\[(\w+)\]$/g;
+ var match = reg.exec(j.name);
+ if (!match)
+ return true;
+ match[1] = "x" + parseInt(match[1]);
+ if (typeof data[match[1]] == 'undefined') {
+ data[match[1]] = {};
+ }
+ data[match[1]][match[2]] = j.value;
+ });
+ var result = template ? [] : {};
+ $.each(data, function (i, j) {
+ if (j) {
+ if (!template) {
+ if (j.key != '') {
+ result[j.key] = j.value;
+ }
+ } else {
+ result.push(j);
+ }
+ }
+ });
+ textarea.val(JSON.stringify(result));
+ };
+ //监听文本框改变事件
+ $(document).on('change keyup', ".fieldlist input,.fieldlist textarea,.fieldlist select", function () {
+ refresh($(this).closest("dl").data("name"));
+ });
+ //追加控制
+ $(".fieldlist", form).on("click", ".btn-append", function (e, row) {
+ var container = $(this).closest("dl");
+ var index = container.data("index");
+ var name = container.data("name");
+ var template = container.data("template");
+ var data = container.data();
+ index = index ? parseInt(index) : 0;
+ container.data("index", index + 1);
+ var row = row ? row : {};
+ var vars = {index: index, name: name, data: data, row: row};
+ var html = template ? Template(template, vars) : Template.render(Form.config.fieldlisttpl, vars);
+ $(html).insertBefore($(this).closest("dd"));
+ $(this).trigger("fa.event.appendfieldlist", $(this).closest("dd").prev());
+ });
+ //移除控制
+ $(".fieldlist", form).on("click", "dd .btn-remove", function () {
+ var container = $(this).closest("dl");
+ $(this).closest("dd").remove();
+ refresh(container.data("name"));
+ });
+ //拖拽排序
$("dl.fieldlist", form).dragsort({
itemSelector: 'dd',
- dragSelector: ".btn-dragsort",
+ dragSelector: ".btn-fdragsort",
dragEnd: function () {
-
+ refresh($(this).closest("dl").data("name"));
},
placeHolderTemplate: ""
});
+ //渲染数据
+ $(".fieldlist", form).each(function () {
+ var container = this;
+ var textarea = $("textarea[name='" + $(this).data("name") + "']", form);
+ if (textarea.val() == '') {
+ return true;
+ }
+ var template = $(this).data("template");
+ $.each(JSON.parse(textarea.val()), function (i, j) {
+ $(".btn-append", container).trigger('click', template ? j : {
+ key: i,
+ value: j
+ });
+ });
+ });
});
}
},
diff --git a/public/assets/js/require-form.js b/public/assets/js/require-form.js
index 0747213b..c1714de8 100755
--- a/public/assets/js/require-form.js
+++ b/public/assets/js/require-form.js
@@ -1,6 +1,7 @@
define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, Upload, Validator) {
var Form = {
config: {
+ fieldlisttpl: '-
'
},
events: {
validator: function (form, success, error, submit) {
@@ -26,7 +27,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
},
target: function (input) {
var $formitem = $(input).closest('.form-group'),
- $msgbox = $formitem.find('span.msg-box');
+ $msgbox = $formitem.find('span.msg-box');
if (!$msgbox.length) {
return [];
}
@@ -122,7 +123,8 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
citypicker: function (form) {
//绑定城市远程插件
if ($("[data-toggle='city-picker']", form).size() > 0) {
- require(['citypicker'], function () {});
+ require(['citypicker'], function () {
+ });
}
},
datetimepicker: function (form) {
@@ -240,27 +242,90 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
}
},
fieldlist: function (form) {
+ //绑定fieldlist
if ($(".fieldlist", form).size() > 0) {
- $(".fieldlist", form).on("click", ".append", function () {
- var rel = parseInt($(this).closest("dl").attr("rel")) + 1;
- var name = $(this).closest("dl").data("name");
- $(this).closest("dl").attr("rel", rel);
- $('-
').insertBefore($(this).parent());
- });
- $(".fieldlist", form).on("click", "dd .btn-remove", function () {
- $(this).parent().remove();
- });
- //拖拽排序
- require(['dragsort'], function () {
- //绑定拖动排序
+ require(['dragsort', 'template'], function (undefined, Template) {
+ //刷新隐藏textarea的值
+ var refresh = function (name) {
+ var data = {};
+ var textarea = $("textarea[name='" + name + "']", form);
+ var container = textarea.closest("dl");
+ var template = container.data("template");
+ console.log(name, container);
+ $.each($("input,select", container).serializeArray(), function (i, j) {
+ var reg = /\[(\w+)\]\[(\w+)\]$/g;
+ var match = reg.exec(j.name);
+ if (!match)
+ return true;
+ match[1] = "x" + parseInt(match[1]);
+ if (typeof data[match[1]] == 'undefined') {
+ data[match[1]] = {};
+ }
+ data[match[1]][match[2]] = j.value;
+ });
+ var result = template ? [] : {};
+ $.each(data, function (i, j) {
+ if (j) {
+ if (!template) {
+ if (j.key != '') {
+ result[j.key] = j.value;
+ }
+ } else {
+ result.push(j);
+ }
+ }
+ });
+ textarea.val(JSON.stringify(result));
+ };
+ //监听文本框改变事件
+ $(document).on('change keyup', ".fieldlist input,.fieldlist textarea,.fieldlist select", function () {
+ refresh($(this).closest("dl").data("name"));
+ });
+ //追加控制
+ $(".fieldlist", form).on("click", ".btn-append", function (e, row) {
+ var container = $(this).closest("dl");
+ var index = container.data("index");
+ var name = container.data("name");
+ var template = container.data("template");
+ var data = container.data();
+ index = index ? parseInt(index) : 0;
+ container.data("index", index + 1);
+ var row = row ? row : {};
+ var vars = {index: index, name: name, data: data, row: row};
+ var html = template ? Template(template, vars) : Template.render(Form.config.fieldlisttpl, vars);
+ $(html).insertBefore($(this).closest("dd"));
+ $(this).trigger("fa.event.appendfieldlist", $(this).closest("dd").prev());
+ });
+ //移除控制
+ $(".fieldlist", form).on("click", "dd .btn-remove", function () {
+ var container = $(this).closest("dl");
+ $(this).closest("dd").remove();
+ refresh(container.data("name"));
+ });
+ //拖拽排序
$("dl.fieldlist", form).dragsort({
itemSelector: 'dd',
- dragSelector: ".btn-dragsort",
+ dragSelector: ".btn-fdragsort",
dragEnd: function () {
-
+ refresh($(this).closest("dl").data("name"));
},
placeHolderTemplate: ""
});
+ //渲染数据
+ $(".fieldlist", form).each(function () {
+ var container = this;
+ var textarea = $("textarea[name='" + $(this).data("name") + "']", form);
+ if (textarea.val() == '') {
+ return true;
+ }
+ var template = $(this).data("template");
+ $.each(JSON.parse(textarea.val()), function (i, j) {
+ $(".btn-append", container).trigger('click', template ? j : {
+ key: i,
+ value: j
+ });
+ });
+ });
});
}
},
diff --git a/public/install.php b/public/install.php
index 971c9682..c407b0e4 100644
--- a/public/install.php
+++ b/public/install.php
@@ -4,7 +4,7 @@
*
* 安装完成后建议删除此文件
* @author Karson
- * @website http://www.fastadmin.net
+ * @website https://www.fastadmin.net
*/
// error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// ini_set('display_errors', '1');
@@ -41,9 +41,9 @@ $sitename = "FastAdmin";
$link = array(
'qqun' => "https://jq.qq.com/?_wv=1027&k=487PNBb",
'gitee' => 'https://gitee.com/karson/fastadmin/attach_files',
- 'home' => 'http://www.fastadmin.net?ref=install',
- 'forum' => 'http://forum.fastadmin.net?ref=install',
- 'doc' => 'http://doc.fastadmin.net?ref=install',
+ 'home' => 'https://www.fastadmin.net?ref=install',
+ 'forum' => 'https://forum.fastadmin.net?ref=install',
+ 'doc' => 'https://doc.fastadmin.net?ref=install',
);
// 检测目录是否存在
@@ -77,7 +77,7 @@ else if (!extension_loaded("PDO"))
}
else if (!is_really_writable($dbConfigFile))
{
- $errInfo = '当前权限不足,无法写入配置文件application/database.php
点击查看解决办法';
+ $errInfo = '当前权限不足,无法写入配置文件application/database.php
点击查看解决办法';
}
else
{
@@ -86,7 +86,7 @@ else
{
if (!is_dir(ROOT_PATH . $v))
{
- $errInfo = '当前代码仅包含核心代码,请前往官网下载完整包或资源包覆盖后再尝试安装,立即前往下载';
+ $errInfo = '当前代码仅包含核心代码,请前往官网下载完整包或资源包覆盖后再尝试安装,立即前往下载';
break;
}
}