作者 Karson

新增插件管理本地插件功能

新增插件管理HTTPS提示
新增插件管理登录会会员功能
完善插件管理语言包
修复build_heading的错误
... ... @@ -89,7 +89,7 @@ function build_category_select($name, $type, $selected = null, $attr = [], $head
function build_toolbar($btns = NULL, $attr = [])
{
$auth = \app\admin\library\Auth::instance();
$controller = str_replace('.','/',strtolower(think\Request::instance()->controller()));
$controller = str_replace('.', '/', strtolower(think\Request::instance()->controller()));
$btns = $btns ? $btns : ['refresh', 'add', 'edit', 'del'];
$btns = is_array($btns) ? $btns : explode(',', $btns);
$index = array_search('delete', $btns);
... ... @@ -125,12 +125,16 @@ function build_toolbar($btns = NULL, $attr = [])
* @param string $content
* @return string
*/
function build_heading($title = NULL, $content = NULL)
function build_heading($title = NULL, $content = NULL, $path = NULL)
{
if (is_null($title) && is_null($content))
{
$path = request()->pathinfo();
$path = $path[0] == '/' ? $path : '/' . $path;
if (is_null($path))
{
$action = request()->action();
$controller = str_replace('.', '/', request()->controller());
$path = strtolower($controller . ($action && $action != 'index' ? '/' . $action : ''));
}
// 根据当前的URI自动匹配父节点的标题和备注
$data = Db::name('auth_rule')->where('name', $path)->field('title,remark')->find();
if ($data)
... ...
... ... @@ -121,10 +121,12 @@ class Addon extends Backend
}
try
{
Service::install($name, $force);
$uid = $this->request->post("uid");
$token = $this->request->post("token");
Service::install($name, $force, ['uid' => $uid, 'token' => $token]);
$info = get_addon_info($name);
$info['config'] = get_addon_config($name) ? 1 : 0;
$this->success("安装成功", null, ['addon' => $info]);
$this->success(__('Install successful'), null, ['addon' => $info]);
}
catch (AddonException $e)
{
... ... @@ -150,7 +152,7 @@ class Addon extends Backend
try
{
Service::uninstall($name, $force);
$this->success("卸载成功");
$this->success(__('Uninstall successful'));
}
catch (AddonException $e)
{
... ... @@ -179,7 +181,7 @@ class Addon extends Backend
$action = $action == 'enable' ? $action : 'disable';
//调用启用、禁用的方法
Service::$action($name, $force);
$this->success("操作成功");
$this->success(__('Operate successful'));
}
catch (AddonException $e)
{
... ... @@ -197,7 +199,7 @@ class Addon extends Backend
public function local()
{
Config::set('default_return_type', 'json');
$file = $this->request->file('file');
$addonTmpDir = RUNTIME_PATH . 'addons' . DS;
if (!is_dir($addonTmpDir))
... ... @@ -217,20 +219,20 @@ class Addon extends Backend
$infoFile = $tmpAddonDir . 'info.ini';
if (!is_file($infoFile))
{
throw new Exception("插件配置文件未找到");
throw new Exception(__('Addon info file was not found'));
}
$config = Config::parse($infoFile, '', $tmpName);
$name = isset($config['name']) ? $config['name'] : '';
if (!$name)
{
throw new Exception("插件配置信息不正确");
throw new Exception(__('Addon info file data incorrect'));
}
$newAddonDir = ADDON_PATH . $name . DS;
if (is_dir($newAddonDir))
{
throw new Exception("上传的插件已经存在");
throw new Exception(__('Addon already exists'));
}
//重命名插件文件夹
... ... @@ -255,9 +257,9 @@ class Addon extends Backend
//导入SQL
Service::importsql($name);
$info['config'] = get_addon_config($name) ? 1 : 0;
$this->success("插件安装成功,你需要手动启用该插件,使之生效", null, ['addon' => $info]);
$this->success(__('Installed tips'), null, ['addon' => $info]);
}
catch (Exception $e)
{
... ... @@ -287,7 +289,7 @@ class Addon extends Backend
try
{
Service::refresh();
$this->success("操作成功");
$this->success(__('Operate successful'));
}
catch (Exception $e)
{
... ... @@ -295,4 +297,53 @@ class Addon extends Backend
}
}
/**
* 已装插件
*/
public function downloaded()
{
$offset = (int) $this->request->get("offset");
$limit = (int) $this->request->get("limit");
$filter = $this->request->get("filter");
$filter = (array) json_decode($filter, true);
foreach ($filter as $k => &$v)
{
$v = htmlspecialchars(strip_tags($v));
}
unset($v);
$where = ['status' => 'normal'];
if (isset($filter['id']))
{
$where['id'] = (int) $filter['id'];
}
if (isset($filter['name']))
{
$where['name'] = ['like', "%{$filter['name']}%"];
}
if (isset($filter['title']))
{
$where['title'] = ['like', "%{$filter['title']}%"];
}
$addons = get_addon_list();
$list = [];
foreach ($addons as $k => $v)
{
$v['flag'] = '';
$v['banner'] = '';
$v['image'] = '';
$v['donateimage'] = '';
$v['demourl'] = '';
$v['price'] = '0.00';
$v['url'] = '/addons/' . $v['name'];
$v['createtime'] = 0;
$list[] = $v;
}
$list = array_slice($list, $offset, $limit);
$result = array("total" => count($addons), "rows" => $list);
$callback = $this->request->get('callback') ? "jsonp" : "json";
return $callback($result);
}
}
... ...
<?php
return [
'Id' => 'ID',
'Title' => '标题',
'Value' => '配置值',
'Array key' => '键',
'Array value' => '值',
'Id' => 'ID',
'Title' => '标题',
'Value' => '配置值',
'Array key' => '键',
'Array value' => '值',
'File' => '文件',
'Warmtips' => '温馨提示',
'Offline install' => '离线安装',
'Refresh addon cache' => '刷新插件缓存',
'Userinfo' => '会员信息',
'Online store' => '在线商店',
'Local addon' => '本地插件',
'Https tips' => '当前你无法在插件管理中在线安装FastAdmin市场中的插件,请前往 <a href="http://www.fastadmin.net/store.html" target="_blank" class="">FastAdmin插件市场</a> 中下载后进行离线安装。',
'Conflict tips' => '此插件中发现和现有系统中部分文件发现冲突!以下文件将会被影响,请备份好相关文件后再继续操作',
'Login tips' => '此处登录账号为<a href="http://www.fastadmin.net" target="_blank">FastAdmin官网账号</a>',
'Logined tips' => '你好!%s<br />当前你已经登录,将同步保存你的购买记录',
'Pay tips' => '支付完成后请稍等1~5分钟后再尝试安装,请不要重复支付,如果仍然无法安装,请加<a href="https://jq.qq.com/?_wv=1027&k=487PNBb" target="_blank">QQ群:636393962</a>向管理员反馈',
'Pay click tips' => '请点击这里在新窗口中进行支付!',
'Pay new window tips' => '请在新弹出的窗口中进行支付,支付完成后再重新点击安装按钮进行安装!',
'Uninstall tips' => '确认卸载插件?<p class="text-danger">卸载将会删除所有插件文件且不可找回!!! 插件如果有创建数据库表请手动删除!!!</p>如有重要数据请备份后再操作!',
'Installed tips' => '插件安装成功,你需要手动启用该插件,使之生效',
'Recommend' => '推荐',
'Hot' => '热门',
'New' => '新',
'Free' => '免费',
'Sale' => '折扣',
'No image' => '暂无缩略图',
'Author' => '作者',
'Intro' => '介绍',
'Version' => '版本',
'Createtime' => '添加时间',
'Demo' => '在线演示',
'Install' => '安装',
'Uninstall' => '卸载',
'Setting' => '配置',
'Disable' => '禁用',
'Enable' => '启用',
'Your username or email' => '你的用户名或邮箱',
'Your password' => '你的密码',
'Login FastAdmin' => '登录FastAdmin',
'Login' => '登录',
'Logout' => '退出登录',
'Register' => '注册账号',
'You\'re not login' => '当前未登录',
'Pay now' => '立即支付',
'Continue install' => '继续安装',
'Continue uninstall' => '继续安装',
'Continue operate' => '继续操作',
'Install successful' => '安装成功',
'Uninstall successful' => '卸载成功',
'Operate successful' => '操作成功',
'Addon info file was not found' => '插件配置文件未找到',
'Addon info file data incorrect' => '插件配置文件未找到',
'Addon info file data incorrect' => '插件配置信息不正确',
'Addon already exists' => '上传的插件已经存在',
];
... ...
<style type="text/css">
.item-addon{margin-left:15px;margin-bottom:15px;}
.item-addon img.img-responsive,.item-addon .noimage{width: 300px;height:200px;}
.noimage {line-height: 200px;text-align: center;background:#18bc9c;color:#fff;}
.addon {
height:100%;position: relative;
position: relative;
}
.addon > span {
position:absolute;left:15px;top:15px;
... ... @@ -10,6 +13,10 @@
}
.layui-layer-pay {border:none;}
</style>
<div id="warmtips" class="alert alert-dismissable alert-danger hide">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{:__('Warning')}</strong> {:__('Https tips')}
</div>
<div class="panel panel-default panel-intro">
{:build_heading()}
... ... @@ -19,8 +26,11 @@
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh')}
<button type="button" id="plupload-addon" class="btn btn-danger plupload" data-url="addon/local" data-mimetype="application/zip" data-multiple="false"><i class="fa fa-upload"></i> {:__('本地安装')}</button>
<a class="btn btn-success btn-ajax" href="addon/refresh"><i class="fa fa-refresh"></i> {:__('刷新插件缓存')}</a>
<button type="button" id="plupload-addon" class="btn btn-danger plupload" data-url="addon/local" data-mimetype="application/zip" data-multiple="false"><i class="fa fa-upload"></i> {:__('Offline install')}</button>
<a class="btn btn-success btn-ajax" href="addon/refresh"><i class="fa fa-refresh"></i> {:__('Refresh addon cache')}</a>
<a class="btn btn-info btn-switch btn-store" href="javascript:;" data-url="{$config.fastadmin.api_url}/addon/index"><i class="fa fa-cloud"></i> {:__('Online store')}</a>
<a class="btn btn-info btn-switch" href="javascript:;" data-url="addon/downloaded"><i class="fa fa-laptop"></i> {:__('Local addon')}</a>
<a class="btn btn-primary btn-userinfo" href="javascript:;"><i class="fa fa-user"></i> {:__('Userinfo')}</a>
</div>
<table id="table" class="table table-striped table-hover" width="100%">
... ... @@ -32,6 +42,42 @@
</div>
</div>
</div>
<script id="logintpl" type="text/html">
<div>
<form class="form-horizontal">
<fieldset>
<div class="alert alert-dismissable alert-danger">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{:__('Warning')}</strong><br />{:__('Login tips')}
</div>
<div class="form-group">
<label for="inputAccount" class="col-lg-3 control-label">{:__('Username')}</label>
<div class="col-lg-9">
<input type="text" class="form-control" id="inputAccount" value="" placeholder="{:__('Your username or email')}">
</div>
</div>
<div class="form-group">
<label for="inputPassword" class="col-lg-3 control-label">{:__('Password')}</label>
<div class="col-lg-9">
<input type="password" class="form-control" id="inputPassword" value="" placeholder="{:__('Your password')}">
</div>
</div>
</fieldset>
</form>
</div>
</script>
<script id="userinfotpl" type="text/html">
<div>
<form class="form-horizontal">
<fieldset>
<div class="alert alert-dismissable alert-success">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{:__('Warning')}</strong><br />{:__('Logined tips', '<%=username%>')}
</div>
</fieldset>
</form>
</div>
</script>
<script id="paytpl" type="text/html">
<div style="position:relative;width:800px;height:600px;background:url('<%=payimg%>') 0 0 no-repeat;">
<div style="position:absolute;left:265px;top:442px;">
... ... @@ -45,13 +91,13 @@
<script id="conflicttpl" type="text/html">
<div class="alert alert-dismissable alert-danger">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>警告!</strong> 此插件中发现和现有系统中部分文件发现冲突!以下文件将会被影响,请备份好相关文件后再继续操
<strong>{:__('Warning')}</strong> {:__('Conflict tips')}
</div>
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>文件</th>
<th>{:__('File')}</th>
</tr>
</thead>
<tbody>
... ... @@ -65,47 +111,56 @@
</table>
</script>
<script id="itemtpl" type="text/html">
<div class="col-sm-4 col-md-3">
<div class="item-addon">
<% var labelarr = ['primary', 'success', 'info', 'danger', 'warning']; %>
<% var label = labelarr[item.id % 5]; %>
<% var addon = typeof addons[item.name]!= 'undefined' ? addons[item.name] : null; %>
<div class="thumbnail addon">
<!--<span class="btn btn-<%=label%>">ID:<%=item.id%></span>-->
<a href="<%=addon?addon.url:'javascript:;'%>" target="_blank"><img src="<%=item.image%>" class="img-responsive" alt="<%=item.title%>"></a>
<a href="<%=addon?addon.url:'javascript:;'%>" target="_blank">
<%if(item.image){%>
<img src="<%=item.image%>" class="img-responsive" alt="<%=item.title%>">
<%}else{%>
<div class="noimage">{:__('No image')}</div>
<%}%>
</a>
<div class="caption">
<h4><%=item.title?item.title:''%>
<h4><%=item.title?item.title:'{:__('None')}'%>
<% if(item.flag.indexOf("recommend")>-1){%>
<span class="label label-success">推荐</span>
<span class="label label-success">{:__('Recommend')}</span>
<% } %>
<% if(item.flag.indexOf("hot")>-1){%>
<span class="label label-danger">热门</span>
<span class="label label-danger">{:__('Hot')}</span>
<% } %>
<% if(item.flag.indexOf("free")>-1){%>
<span class="label label-info">免费</span>
<span class="label label-info">{:__('Free')}</span>
<% } %>
<% if(item.flag.indexOf("sale")>-1){%>
<span class="label label-warning">折扣</span>
<span class="label label-warning">{:__('Sale')}</span>
<% } %>
</h4>
<p class="text-<%=item.price>0?'danger':'success'%>"><b><%=item.price%></b></p>
<p class="text-muted">作者: <a href="<%=item.url?item.url:'javascript:;'%>" target="_blank"><%=item.author%></a></p>
<p class="text-muted">描述: <%=item.intro%></p>
<p class="text-muted">版本: <%=# addon && item && addon.version!=item.version?'<span class="label label-danger">'+addon.version+'</span> -> <span class="label label-success">'+item.version+'</span>':item.version%></p>
<p class="text-muted">添加时间: <%=Moment(item.createtime*1000).format("YYYY-MM-DD HH:mm:ss")%></p>
<!--<p class="text-muted">最后时间: <%=Moment(item.updatetime*1000).format("YYYY-MM-DD HH:mm:ss")%></p>-->
<p class="text-muted">{:__('Author')}: <a href="<%=item.url?item.url:'javascript:;'%>" target="_blank"><%=item.author%></a></p>
<p class="text-muted">{:__('Intro')}: <%=item.intro%></p>
<p class="text-muted">{:__('Version')}: <%=# addon && item && addon.version!=item.version?'<span class="label label-danger">'+addon.version+'</span> -> <span class="label label-success">'+item.version+'</span>':item.version%></p>
<p class="text-muted">{:__('Createtime')}: <%=Moment(item.createtime*1000).format("YYYY-MM-DD HH:mm:ss")%></p>
<p class="operate" data-id="<%=item.id%>" data-name="<%=item.name%>">
<% if(!addon){ %>
<a href="javascript:;" class="btn btn-primary btn-success btn-install"><i class="fa fa-cloud-download"></i> 安装</a>
<a href="javascript:;" class="btn btn-primary btn-success btn-install" data-type="<%=item.price<=0?'free':'price';%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a>
<% if(item.demourl){ %>
<a href="<%=item.demourl%>" class="btn btn-primary btn-info btn-demo" target="_blank"><i class="fa fa-flash"></i> {:__('Demo')}</a>
<% } %>
<% } %>
<% if(addon){ %>
<% if(addon.config){ %>
<a href="javascript:;" class="btn btn-primary btn-config"><i class="fa fa-pencil"></i> 配置</a>
<a href="javascript:;" class="btn btn-primary btn-config"><i class="fa fa-pencil"></i> {:__('Setting')}</a>
<% } %>
<% if(addon.state == "1"){ %>
<a href="javascript:;" class="btn btn-warning btn-disable" data-action="disable"><i class="fa fa-times"></i> 点击禁用</a>
<a href="javascript:;" class="btn btn-warning btn-disable" data-action="disable"><i class="fa fa-times"></i> {:__('Disable')}</a>
<% }else{ %>
<a href="javascript:;" class="btn btn-success btn-enable" data-action="enable"><i class="fa fa-check"></i> 点击启用</a>
<a href="javascript:;" class="btn btn-danger btn-uninstall"><i class="fa fa-times"></i> 卸载</a>
<a href="javascript:;" class="btn btn-success btn-enable" data-action="enable"><i class="fa fa-check"></i> {:__('Enable')}</a>
<a href="javascript:;" class="btn btn-danger btn-uninstall"><i class="fa fa-times"></i> {:__('Uninstall')}</a>
<% } %>
<% } %>
<!--
... ...
... ... @@ -19,7 +19,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
// 初始化表格
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
url: location.protocol === "https:" ? "addon/downloaded" : $.fn.bootstrapTable.defaults.extend.index_url,
columns: [
[
{field: 'id', title: 'ID'},
... ... @@ -27,6 +27,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
{field: 'title', title: __('Title')}
]
],
dataType: 'jsonp',
templateView: true,
search: false,
showColumns: false,
... ... @@ -34,12 +35,18 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
showExport: false,
commonSearch: true,
searchFormVisible: false,
pageSize: 12
pageSize: 10
});
// 为表格绑定事件
Table.api.bindevent(table);
// 如果是https则启用提示
if (location.protocol === "https:") {
$("#warmtips").removeClass("hide");
$(".btn-switch,.btn-userinfo").addClass("disabled");
}
require(['upload'], function (Upload) {
Upload.api.plupload("#plupload-addon", function (data, ret) {
Config['addons'][data.addon.name] = data.addon;
... ... @@ -48,13 +55,79 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
});
});
//点击安装
//切换URL
$(document).on("click", ".btn-switch", function () {
table.bootstrapTable('refresh', {url: $(this).data("url"), pageNumber: 1});
});
// 会员信息
$(document).on("click", ".btn-userinfo", function () {
var userinfo = Controller.api.userinfo.get();
if (!userinfo) {
Layer.open({
content: Template("logintpl", {}),
area: ['400px', '330px'],
title: __('Login FastAdmin'),
resize: false,
btn: [__('Login'), __('Register')],
yes: function (index, layero) {
Fast.api.ajax({
url: Config.fastadmin.api_url + '/user/login',
dataType: 'jsonp',
data: {account: $("#inputAccount", layero).val(), password: $("#inputPassword", layero).val(), _method: 'POST'}
}, function (data, ret) {
Controller.api.userinfo.set(data);
Layer.closeAll();
Layer.alert(ret.msg);
}, function (data, ret) {
Layer.alert(ret.msg);
});
},
btn2: function () {
return false;
},
success: function (layero, index) {
$(".layui-layer-btn1", layero).prop("href", "http://www.fastadmin.net/user/register.html").prop("target", "_blank");
}
});
} else {
var userinfo = Controller.api.userinfo.get();
if (!userinfo) {
Layer.alert(__('You\'re not login'));
return false;
}
Layer.open({
content: Template("userinfotpl", userinfo),
area: ['400px', '330px'],
title: __('Userinfo'),
resize: false,
btn: [__('Logout'), __('Cancel')],
yes: function () {
Fast.api.ajax({
url: Config.fastadmin.api_url + '/user/logout',
dataType: 'jsonp',
data: {uid: userinfo.id, token: userinfo.token}
}, function (data, ret) {
Controller.api.userinfo.set(null);
Layer.closeAll();
Layer.alert(ret.msg);
}, function (data, ret) {
Layer.alert(ret.msg);
});
}
});
}
});
// 点击安装
$(document).on("click", ".btn-install", function () {
var name = $(this).closest(".operate").data("name");
var userinfo = Controller.api.userinfo.get();
var uid = userinfo ? userinfo.id : 0;
var token = userinfo ? userinfo.token : '';
var install = function (name, force) {
Fast.api.ajax({
url: 'addon/install',
data: {name: name, force: force ? 1 : 0}
data: {name: name, force: force ? 1 : 0, uid: uid, token: token}
}, function (data, ret) {
Layer.closeAll();
Config['addons'][data.addon.name] = ret.data.addon;
... ... @@ -73,19 +146,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
btn: false,
resize: false,
end: function () {
Layer.alert("支付完成后请稍等1~5分钟后再尝试安装,请不要重复支付,如果仍然无法安装,请加<a href='https://jq.qq.com/?_wv=1027&k=487PNBb' target='_blank'>QQ群:636393962</a>向管理员反馈");
Layer.alert(__('Pay tips'));
}
});
} else if (ret && ret.code === -2) {
//跳转支付
Layer.alert('请点击这里在新窗口中进行支付!', {
btn: ['立即支付', '取消'],
Layer.alert(__('Pay click tips'), {
btn: [__('Pay now'), __('Cancel')],
icon: 0,
success: function (layero) {
$(".layui-layer-btn0", layero).attr("href", ret.data.payurl).attr("target", "_blank");
}
}, function () {
Layer.alert("请在新弹出的窗口中进行支付,支付完成后再重新点击安装按钮进行安装!", {icon: 0});
Layer.alert(__('Pay new window tips'), {icon: 0});
});
} else if (ret && ret.code === -3) {
... ... @@ -94,8 +167,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
content: Template("conflicttpl", ret.data),
shade: 0.8,
area: ['800px', '600px'],
title: "温馨提示",
btn: ['继续安装', '取消'],
title: __('Warning'),
btn: [__('Continue install'), __('Cancel')],
end: function () {
},
... ... @@ -131,8 +204,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
content: Template("conflicttpl", ret.data),
shade: 0.8,
area: ['800px', '600px'],
title: "温馨提示",
btn: ['继续卸载', '取消'],
title: __('Warning'),
btn: [__('Continue uninstall'), __('Cancel')],
end: function () {
},
... ... @@ -147,7 +220,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
return false;
});
};
Layer.confirm("确认卸载插件?<p class='text-danger'>卸载将会删除所有插件文件且不可找回!!! 插件如果有创建数据库表请手动删除!!!</p>如有重要数据请备份后再操作!", function () {
Layer.confirm(__('Uninstall tips'), function () {
uninstall(name, false);
});
});
... ... @@ -155,7 +228,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
//点击配置
$(document).on("click", ".btn-config", function () {
var name = $(this).closest(".operate").data("name");
Fast.api.open("addon/config?name=" + name, "修改配置");
Fast.api.open("addon/config?name=" + name, __('Setting'));
});
//点击启用/禁用
... ... @@ -178,8 +251,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
content: Template("conflicttpl", ret.data),
shade: 0.8,
area: ['800px', '600px'],
title: "温馨提示",
btn: ['继续操作', '取消'],
title: __('Warning'),
btn: [__('Continue operate'), __('Cancel')],
end: function () {
},
... ... @@ -206,6 +279,19 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
},
userinfo: {
get: function () {
var userinfo = localStorage.getItem("fastadmin_userinfo");
return userinfo ? JSON.parse(userinfo) : null;
},
set: function (data) {
if (data) {
localStorage.setItem("fastadmin_userinfo", JSON.stringify(data));
} else {
localStorage.removeItem("fastadmin_userinfo");
}
}
}
}
};
... ...