浏览代码

新增插件管理本地插件功能
新增插件管理HTTPS提示
新增插件管理登录会会员功能
完善插件管理语言包
修复build_heading的错误

Karson 8 年之前
父节点
当前提交
7d45e67fdb

+ 8 - 4
application/admin/common.php

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

+ 62 - 11
application/admin/controller/Addon.php

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

+ 55 - 5
application/admin/lang/zh-cn/addon.php

@@ -1,9 +1,59 @@
 <?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'           => '上传的插件已经存在',
 ];

+ 77 - 22
application/admin/view/addon/index.html

@@ -1,6 +1,9 @@
 <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>
                     <% } %>
                     <% } %>
                     <!--                    

+ 102 - 16
public/assets/js/backend/addon.js

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