Karson 8 jaren geleden
bovenliggende
commit
2ceb5f513e
100 gewijzigde bestanden met toevoegingen van 7001 en 0 verwijderingen
  1. 3 0
      .bowerrc
  2. 8 0
      .gitignore
  3. 42 0
      .travis.yml
  4. 191 0
      LICENSE
  5. 1 0
      application/.htaccess
  6. 417 0
      application/admin/command/Crud.php
  7. 11 0
      application/admin/command/Crud/stubs/add.stub
  8. 25 0
      application/admin/command/Crud/stubs/controller.stub
  9. 11 0
      application/admin/command/Crud/stubs/edit.stub
  10. 25 0
      application/admin/command/Crud/stubs/index.stub
  11. 46 0
      application/admin/command/Crud/stubs/javascript.stub
  12. 5 0
      application/admin/command/Crud/stubs/lang.stub
  13. 16 0
      application/admin/command/Crud/stubs/model.stub
  14. 212 0
      application/admin/command/Menu.php
  15. 136 0
      application/admin/common.php
  16. 8 0
      application/admin/config.php
  17. 284 0
      application/admin/controller/Ajax.php
  18. 45 0
      application/admin/controller/Dashboard.php
  19. 109 0
      application/admin/controller/Index.php
  20. 24 0
      application/admin/controller/Page.php
  21. 151 0
      application/admin/controller/auth/Admin.php
  22. 219 0
      application/admin/controller/auth/Group.php
  23. 114 0
      application/admin/controller/auth/Rule.php
  24. 159 0
      application/admin/controller/general/Attachment.php
  25. 175 0
      application/admin/controller/general/Configvalue.php
  26. 147 0
      application/admin/controller/general/Crontab.php
  27. 219 0
      application/admin/controller/general/Database.php
  28. 68 0
      application/admin/controller/general/Profile.php
  29. 49 0
      application/admin/controller/wechat/Autoreply.php
  30. 127 0
      application/admin/controller/wechat/Config.php
  31. 85 0
      application/admin/controller/wechat/Menu.php
  32. 85 0
      application/admin/controller/wechat/Response.php
  33. 111 0
      application/admin/lang/zh-cn.php
  34. 14 0
      application/admin/lang/zh-cn/general/attachment.php
  35. 30 0
      application/admin/lang/zh-cn/general/database.php
  36. 23 0
      application/admin/lang/zh-cn/index.php
  37. 16 0
      application/admin/lang/zh-cn/page.php
  38. 205 0
      application/admin/library/Auth.php
  39. 126 0
      application/admin/library/traits/Backend.php
  40. 34 0
      application/admin/model/Admin.php
  41. 30 0
      application/admin/model/AdminLog.php
  42. 16 0
      application/admin/model/AuthGroup.php
  43. 10 0
      application/admin/model/AuthGroupAccess.php
  44. 16 0
      application/admin/model/AuthRule.php
  45. 16 0
      application/admin/model/Page.php
  46. 45 0
      application/admin/view/auth/admin/add.html
  47. 45 0
      application/admin/view/auth/admin/edit.html
  48. 21 0
      application/admin/view/auth/admin/index.html
  49. 37 0
      application/admin/view/auth/group/add.html
  50. 37 0
      application/admin/view/auth/group/edit.html
  51. 19 0
      application/admin/view/auth/group/index.html
  52. 65 0
      application/admin/view/auth/rule/add.html
  53. 61 0
      application/admin/view/auth/rule/edit.html
  54. 21 0
      application/admin/view/auth/rule/index.html
  55. 42 0
      application/admin/view/auth/rule/tpl.html
  56. 191 0
      application/admin/view/common/control.html
  57. 107 0
      application/admin/view/common/header.html
  58. 27 0
      application/admin/view/common/menu.html
  59. 22 0
      application/admin/view/common/meta.html
  60. 1 0
      application/admin/view/common/script.html
  61. 432 0
      application/admin/view/dashboard/index.html
  62. 29 0
      application/admin/view/general/attachment/add.html
  63. 64 0
      application/admin/view/general/attachment/edit.html
  64. 25 0
      application/admin/view/general/attachment/index.html
  65. 58 0
      application/admin/view/general/configvalue/add.html
  66. 59 0
      application/admin/view/general/configvalue/edit.html
  67. 26 0
      application/admin/view/general/configvalue/index.html
  68. 76 0
      application/admin/view/general/crontab/add.html
  69. 70 0
      application/admin/view/general/crontab/edit.html
  70. 25 0
      application/admin/view/general/crontab/index.html
  71. 80 0
      application/admin/view/general/database/index.html
  72. 61 0
      application/admin/view/general/profile/index.html
  73. 38 0
      application/admin/view/index/index.html
  74. 91 0
      application/admin/view/index/login.html
  75. 44 0
      application/admin/view/layout/default.html
  76. 79 0
      application/admin/view/page/add.html
  77. 79 0
      application/admin/view/page/edit.html
  78. 25 0
      application/admin/view/page/index.html
  79. 64 0
      application/admin/view/user/third/add.phtml
  80. 64 0
      application/admin/view/user/third/edit.phtml
  81. 25 0
      application/admin/view/user/third/index.phtml
  82. 193 0
      application/admin/view/user/user/add.phtml
  83. 187 0
      application/admin/view/user/user/edit.phtml
  84. 25 0
      application/admin/view/user/user/index.phtml
  85. 51 0
      application/admin/view/wechat/autoreply/add.html
  86. 57 0
      application/admin/view/wechat/autoreply/edit.html
  87. 25 0
      application/admin/view/wechat/autoreply/index.html
  88. 28 0
      application/admin/view/wechat/config/add.html
  89. 28 0
      application/admin/view/wechat/config/edit.html
  90. 19 0
      application/admin/view/wechat/config/index.html
  91. 82 0
      application/admin/view/wechat/menu/index.html
  92. 54 0
      application/admin/view/wechat/response/add.html
  93. 52 0
      application/admin/view/wechat/response/edit.html
  94. 19 0
      application/admin/view/wechat/response/index.html
  95. 16 0
      application/admin/view/wechat/response/select.html
  96. 1 0
      application/api/common.php
  97. 5 0
      application/api/config.php
  98. 15 0
      application/api/controller/Index.php
  99. 25 0
      application/build.php
  100. 0 0
      application/command.php

+ 3 - 0
.bowerrc

@@ -0,0 +1,3 @@
+{
+  "directory" : "public/assets/libs"
+}

+ 8 - 0
.gitignore

@@ -0,0 +1,8 @@
+/nbproject/
+.idea
+composer.lock
+*.log
+thinkphp
+vendor
+runtime
+public/assets/libs/

File diff suppressed because it is too large
+ 42 - 0
.travis.yml


+ 191 - 0
LICENSE

@@ -0,0 +1,191 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets "{}" replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same "printed page" as the copyright notice for easier identification within
+third-party archives.
+
+   Copyright 2017 Karson
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 1 - 0
application/.htaccess

@@ -0,0 +1 @@
+deny from all

+ 417 - 0
application/admin/command/Crud.php

@@ -0,0 +1,417 @@
+<?php
+
+namespace app\admin\command;
+
+use fast\Form;
+use think\Config;
+use think\console\Command;
+use think\console\Input;
+use think\console\input\Option;
+use think\console\Output;
+use think\Db;
+use think\Lang;
+
+class Crud extends Command
+{
+
+    protected function configure()
+    {
+        $this
+                ->setName('crud')
+                ->addOption('table', 't', Option::VALUE_REQUIRED, 'table name without prefix', null)
+                ->addOption('controller', 'c', Option::VALUE_OPTIONAL, 'controller name', null)
+                ->addOption('model', 'm', Option::VALUE_OPTIONAL, 'model name', null)
+                ->addOption('force', 'f', Option::VALUE_OPTIONAL, 'force override', null)
+                ->addOption('local', 'l', Option::VALUE_OPTIONAL, 'local model', 1)
+                ->setDescription('Build CRUD controller and model from table');
+    }
+
+    protected function execute(Input $input, Output $output)
+    {
+        $adminPath = dirname(__DIR__) . DS;
+        //表名
+        $table = $input->getOption('table') ? : '';
+        //自定义控制器
+        $controller = $input->getOption('controller');
+        //自定义模型
+        $model = $input->getOption('model');
+        //强制覆盖
+        $force = $input->getOption('force');
+        //是否为本地model,为0时表示为全局model将会把model放在app/common/model中
+        $local = $input->getOption('local');
+        if (!$table)
+        {
+            $output->error('table name can\'t empty');
+            return;
+        }
+        $dbname = Config::get('database.database');
+        $prefix = Config::get('database.prefix');
+        $tableName = $prefix . $table;
+        $tableInfo = Db::query("SHOW TABLE STATUS LIKE '{$tableName}'", [], TRUE);
+        if (!$tableInfo)
+        {
+            $output->error("table not found");
+            return;
+        }
+        $tableInfo = $tableInfo[0];
+
+        //根据表名匹配对应的Fontawesome图标
+        $iconPath = ROOT_PATH . '/public/assets/libs/font-awesome/less/variables.less';
+        $iconName = is_file($iconPath) && stripos(file_get_contents($iconPath), '@fa-var-' . $table . ':') ? $table : 'fa fa-circle-o';
+
+        //控制器默认以表名进行处理,以下划线进行分隔,如果需要自定义则需要传入controller,格式为目录层级
+        $controllerArr = !$controller ? explode('_', strtolower($table)) : explode('/', strtolower($controller));
+        $controllerUrl = implode('/', $controllerArr);
+        $controllerName = ucfirst(array_pop($controllerArr));
+        $controllerDir = implode('/', $controllerArr);
+        $controllerFile = ($controllerDir ? $controllerDir . '/' : '') . $controllerName . '.php';
+
+        //非覆盖模式时如果存在控制器文件则报错
+        if (is_file($controllerFile) && !$force)
+        {
+            $output->error('controller already exists');
+            return;
+        }
+
+        //模型默认以表名进行处理,以下划线进行分隔,如果需要自定义则需要传入model,不支持目录层级
+        if (!$model)
+        {
+            $modelarr = explode('_', strtolower($table));
+            foreach ($modelarr as $k => &$v)
+                $v = ucfirst($v);
+            unset($v);
+            $modelName = implode('', $modelarr);
+        }
+        else
+        {
+            $modelName = ucfirst($model);
+        }
+        $modelFile = ($local ? $adminPath : APP_PATH . 'common' . DS) . 'model' . DS . $modelName . '.php';
+
+        //非覆盖模式时如果存在模型文件则报错
+        if (is_file($modelFile) && !$force)
+        {
+            $output->error('model already exists');
+            return;
+        }
+
+        //从数据库中获取表字段信息
+        $columnList = Db::query("SELECT * FROM `information_schema`.`columns` WHERE TABLE_SCHEMA = ? AND table_name = ? ORDER BY ORDINAL_POSITION", [$dbname, $tableName]);
+        $fields = [];
+        foreach ($columnList as $k => $v)
+        {
+            $fields[] = $v['COLUMN_NAME'];
+        }
+
+        $addList = [];
+        $editList = [];
+        $javascriptList = [];
+        $langList = [];
+        $field = 'id';
+        $order = 'id';
+
+        //循环所有字段,开始构造视图的HTML和JS信息
+        foreach ($columnList as $k => $v)
+        {
+            $field = $v['COLUMN_NAME'];
+            $fieldLang = ucfirst($field);
+            // 语言列表
+            if ($v['COLUMN_COMMENT'] != '')
+            {
+                $langList[] = $this->getLangItem($field, $v['COLUMN_COMMENT']);
+            }
+            if ($v['COLUMN_KEY'] != 'PRI')
+            {
+                $inputType = 'text';
+                $step = 0;
+                switch ($v['DATA_TYPE'])
+                {
+                    case 'bigint':
+                    case 'int':
+                    case 'mediumint':
+                    case 'smallint':
+                    case 'tinyint':
+                        $inputType = 'number';
+                        break;
+                    case 'enum':
+                    case 'set':
+                        $inputType = 'select';
+                        break;
+                    case 'decimal':
+                    case 'double':
+                    case 'float':
+                        $inputType = 'number';
+                        $step = "0." . str_repeat(0, $v['NUMERIC_SCALE'] - 1) . "1";
+                    case 'text':
+                        $inputType = 'textarea';
+                    default:
+                        break;
+                }
+                if (substr($field, -4) == 'time')
+                {
+                    $inputType = 'datetime';
+                }
+
+                if ($inputType == 'select')
+                {
+                    $itemlist = substr($v['COLUMN_TYPE'], strlen($v['DATA_TYPE']) + 1, -1);
+                    $itemlist = str_replace("'", '', $itemlist);
+                    $attr = "'id'=>'c-$field','class'=>'form-control selectpicker'";
+                    if ($v['DATA_TYPE'] == 'enum')
+                    {
+                        $attr .= ",'multiple'=>''";
+                    }
+                    if ($v['COLUMN_DEFAULT'] == '')
+                    {
+                        $attr .= ",'required'=>''";
+                    }
+                    $formAddElement = "{:build_select('row[$field]', '{$itemlist}', null, [{$attr}])}";
+                    $formEditElement = "{:build_select('row[$field]', '{$itemlist}', \$row['$field'], [{$attr}])}";
+                }
+                else
+                {
+                    //CSS类名
+                    $cssClass = ['form-control'];
+                    $cssClass[] = substr($field, -4) == 'time' ? 'datetimepicker' : '';
+                    $cssClass[] = $v['DATA_TYPE'] == 'text' ? 'summernote' : '';
+                    $cssClass[] = substr($field, -3) == '_id' ? 'typeahead' : '';
+                    $cssClass[] = substr($field, -4) == '_ids' ? 'tagsinput' : '';
+                    $cssClass = array_filter($cssClass);
+                    //因为有自动完成可输入其它内容
+                    if (array_intersect($cssClass, ['typeahead', 'tagsinput']))
+                    {
+                        $inputType = 'text';
+                        $step = 0;
+                    }
+                    $attr = ['id' => "c-{$field}", 'class' => implode(' ', $cssClass)];
+                    if ($step)
+                    {
+                        $attr['step'] = $step;
+                    }
+                    //如果是图片则额外附加
+                    if (substr($field, -5) == 'image' || substr($field, -6) == 'avatar')
+                    {
+                        $attr['data-plupload-id'] = "plupload-{$field}-text";
+                        $attr['size'] = 50;
+                    }
+                    $fieldFunc = substr($field, -4) == 'time' ? "|datetime" : "";
+                    if ($inputType == 'textarea')
+                    {
+                        $formAddElement = Form::textarea("row[{$field}]", $v['COLUMN_DEFAULT'], $attr);
+                        $formEditElement = Form::textarea("row[{$field}]", "{\$row.{$field}{$fieldFunc}}", $attr);
+                    }
+                    else
+                    {
+                        $formAddElement = Form::input($inputType, "row[{$field}]", $v['COLUMN_DEFAULT'], $attr);
+                        $formEditElement = Form::input($inputType, "row[{$field}]", "{\$row.{$field}{$fieldFunc}}", $attr);
+                    }
+
+                    if (substr($field, -5) == 'image' || substr($field, -6) == 'avatar')
+                    {
+                        //如果是图片或头像
+                        $formAddElement = $this->getImageUpload($field, $formAddElement);
+                        $formEditElement = $this->getImageUpload($field, $formEditElement);
+                    }
+                    else if ($field == 'status')
+                    {
+                        //如果是状态字段
+                        $formAddElement = "{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}";
+                        $formEditElement = "{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], \$row['status'])}";
+                    }
+                }
+                //构造添加和编辑HTML信息
+                $addList[] = $this->getFormGroup($field, $formAddElement);
+                $editList[] = $this->getFormGroup($field, $formEditElement);
+            }
+
+            //过滤text类型字段
+            if ($v['DATA_TYPE'] != 'text')
+            {
+                //主键
+                if ($v['COLUMN_KEY'] == 'PRI')
+                {
+                    $javascriptList[] = "{field: 'state', checkbox: true}";
+                }
+                //构造JS列信息
+                $javascriptList[] = $this->getJsColumn($field);
+                //排序方式,如果有weigh则按weigh,否则按主键排序
+                $order = $field == 'weigh' ? 'weigh' : $order;
+            }
+        }
+        //JS最后一列加上操作列
+        $javascriptList[] = str_repeat(" ", 24) . "{field: 'operate', title: __('Operate'), events: Table.api.events.operate, formatter: Table.api.formatter.operate}";
+        $addList = implode("\n", array_filter($addList));
+        $editList = implode("\n", array_filter($editList));
+        $javascriptList = implode(",\n", array_filter($javascriptList));
+        $langList = implode(",\n", array_filter($langList));
+
+        //表注释
+        $tableComment = $tableInfo['Comment'];
+        $tableComment = mb_substr($tableComment, -1) == '表' ? mb_substr($tableComment, 0, -1) . '管理' : $tableComment;
+
+        //最终将生成的文件路径
+        $controllerFile = $adminPath . 'controller' . DS . $controllerFile;
+        $javascriptFile = ROOT_PATH . 'public' . DS . 'assets' . DS . 'js' . DS . 'backend' . DS . $controllerUrl . '.js';
+        $addFile = $adminPath . 'view' . DS . $controllerUrl . DS . 'add.html';
+        $editFile = $adminPath . 'view' . DS . $controllerUrl . DS . 'edit.html';
+        $indexFile = $adminPath . 'view' . DS . $controllerUrl . DS . 'index.html';
+        $langFile = $adminPath . 'lang' . DS . Lang::detect() . DS . $controllerUrl . '.php';
+
+        $appNamespace = Config::get('app_namespace');
+        $moduleName = 'admin';
+        $controllerNamespace = "{$appNamespace}\\{$moduleName}\\controller" . ($controllerDir ? "\\" : "") . str_replace('/', "\\", $controllerDir);
+        $modelNamespace = "{$appNamespace}\\" . ($local ? $moduleName : "common") . "\\model";
+
+        $data = [
+            'controllerNamespace'     => $controllerNamespace,
+            'modelNamespace'          => $modelNamespace,
+            'controllerUrl'           => $controllerUrl,
+            'controllerDir'           => $controllerDir,
+            'controllerName'          => $controllerName,
+            'modelName'               => $modelName,
+            'tableComment'            => $tableComment,
+            'iconName'                => $iconName,
+            'order'                   => $order,
+            'table'                   => $table,
+            'tableName'               => $tableName,
+            'addList'                 => $addList,
+            'editList'                => $editList,
+            'javascriptList'          => $javascriptList,
+            'langList'                => $langList,
+            'modelAutoWriteTimestamp' => in_array('createtime', $fields) || in_array('updatetime', $fields) ? "'int'" : 'false',
+            'createTime'              => in_array('createtime', $fields) ? "'createtime'" : 'false',
+            'updateTime'              => in_array('updatetime', $fields) ? "'updatetime'" : 'false',
+        ];
+
+        // 生成控制器文件
+        $result = $this->writeToFile('controller', $data, $controllerFile);
+        // 生成模型文件
+        $result = $this->writeToFile('model', $data, $modelFile);
+        // 生成视图文件
+        $result = $this->writeToFile('add', $data, $addFile);
+        $result = $this->writeToFile('edit', $data, $editFile);
+        $result = $this->writeToFile('index', $data, $indexFile);
+        // 生成JS文件
+        $result = $this->writeToFile('javascript', $data, $javascriptFile);
+        // 生成语言文件
+        if ($langList)
+        {
+            $result = $this->writeToFile('lang', $data, $langFile);
+        }
+        $output->writeln("<info>Build Successed</info>");
+    }
+
+    /**
+     * 写入到文件
+     * @param string $name
+     * @param array $data
+     * @param string $pathname
+     * @return mixed
+     */
+    protected function writeToFile($name, $data, $pathname)
+    {
+        $search = $replace = [];
+        foreach ($data as $k => $v)
+        {
+            $search[] = "{%{$k}%}";
+            $replace[] = $v;
+        }
+        $stub = file_get_contents($this->getStub($name));
+        $content = str_replace($search, $replace, $stub);
+
+        if (!is_dir(dirname($pathname)))
+        {
+            mkdir(strtolower(dirname($pathname)), 0755, true);
+        }
+        return file_put_contents($pathname, $content);
+    }
+
+    /**
+     * 获取基础模板
+     * @param string $name
+     * @return string
+     */
+    protected function getStub($name)
+    {
+        return __DIR__ . '/Crud/stubs/' . $name . '.stub';
+    }
+
+    protected function getLangItem($field, $content)
+    {
+        if (!Lang::has($field))
+        {
+            return <<<EOD
+    '{$field}'  =>  '{$content}'
+EOD;
+        }
+        else
+        {
+            return '';
+        }
+    }
+
+    /**
+     * 获取表单分组数据
+     * @param string $field
+     * @param string $content
+     * @return string
+     */
+    protected function getFormGroup($field, $content)
+    {
+        $langField = ucfirst($field);
+        return<<<EOD
+    <div class="form-group">
+        <label for="c-{$field}" class="control-label col-xs-12 col-sm-2">{:__('{$langField}')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {$content}
+        </div>
+    </div>
+EOD;
+    }
+
+    /**
+     * 获取图片模板数据
+     * @param string $field
+     * @param string $content
+     * @return array
+     */
+    protected function getImageUpload($field, $content)
+    {
+        return <<<EOD
+<div class="form-inline">
+                {$content}
+                <span><button id="plupload-{$field}" class="btn btn-danger plupload" ><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
+            </div>
+EOD;
+    }
+
+    /**
+     * 获取JS列数据
+     * @param string $field
+     * @return string
+     */
+    protected function getJsColumn($field)
+    {
+        $lang = ucfirst($field);
+        $html = str_repeat(" ", 24) . "{field: '{$field}', title: __('{$lang}')";
+        $formatter = '';
+        if ($field == 'status')
+            $formatter = 'status';
+        else if ($field == 'icon')
+            $formatter = 'icon';
+        else if ($field == 'flag')
+            $formatter = 'flag';
+        else if (substr($field, -4) == 'time')
+            $formatter = 'datetime';
+        else if (substr($field, -3) == 'url')
+            $formatter = 'url';
+        else if (substr($field, -5) == 'image')
+            $formatter = 'image';
+        if ($formatter)
+            $html .= ", formatter: Table.api.formatter." . $formatter . "}";
+        else
+            $html .= "}";
+        return $html;
+    }
+
+}

+ 11 - 0
application/admin/command/Crud/stubs/add.stub

@@ -0,0 +1,11 @@
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+
+{%addList%}
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 25 - 0
application/admin/command/Crud/stubs/controller.stub

@@ -0,0 +1,25 @@
+<?php
+
+namespace {%controllerNamespace%};
+
+use app\common\controller\Backend;
+
+use think\Controller;
+use think\Request;
+
+/**
+ * {%tableComment%}
+ *
+ * @icon {%iconName%}
+ */
+class {%controllerName%} extends Backend
+{
+
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = model('{%modelName%}');
+    }
+}

+ 11 - 0
application/admin/command/Crud/stubs/edit.stub

@@ -0,0 +1,11 @@
+<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+
+{%editList%}
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 25 - 0
application/admin/command/Crud/stubs/index.stub

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading($heading.name, $heading.intro)}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar()}
+                        <div class="dropdown btn-group">
+                            <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
+                            <ul class="dropdown-menu text-left" role="menu">
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> 设为正常</a></li>
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> 设为隐藏</a></li>
+                            </ul>
+                        </div>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover" width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 46 - 0
application/admin/command/Crud/stubs/javascript.stub

@@ -0,0 +1,46 @@
+define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
+
+    var Controller = {
+        index: function () {
+            // 初始化表格参数配置
+            Table.api.init({
+                extend: {
+                    index_url: '{%controllerUrl%}/index',
+                    add_url: '{%controllerUrl%}/add',
+                    edit_url: '{%controllerUrl%}/edit',
+                    del_url: '{%controllerUrl%}/del',
+                    multi_url: '{%controllerUrl%}/multi',
+                    table: '{%table%}',
+                }
+            });
+
+            var table = $("#table");
+
+            // 初始化表格
+            table.bootstrapTable({
+                url: $.fn.bootstrapTable.defaults.extend.index_url,
+                sortName: '{%order%}',
+                columns: [
+                    [
+                        {%javascriptList%}
+                    ]
+                ]
+            });
+
+            // 为表格绑定事件
+            Table.api.bindevent(table);
+        },
+        add: function () {
+            Controller.api.bindevent();
+        },
+        edit: function () {
+            Controller.api.bindevent();
+        },
+        api: {
+            bindevent: function () {
+                Form.api.bindevent($("form[role=form]"));
+            }
+        }
+    };
+    return Controller;
+});

+ 5 - 0
application/admin/command/Crud/stubs/lang.stub

@@ -0,0 +1,5 @@
+<?php
+
+return [
+{%langList%}
+];

+ 16 - 0
application/admin/command/Crud/stubs/model.stub

@@ -0,0 +1,16 @@
+<?php
+
+namespace {%modelNamespace%};
+
+use think\Model;
+
+class {%modelName%} extends Model
+{
+
+    // 自动写入时间戳字段
+    protected $autoWriteTimestamp = {%modelAutoWriteTimestamp%};
+
+    // 定义时间戳字段名
+    protected $createTime = {%createTime%};
+    protected $updateTime = {%updateTime%};
+}

+ 212 - 0
application/admin/command/Menu.php

@@ -0,0 +1,212 @@
+<?php
+
+namespace app\admin\command;
+
+use app\admin\model\AuthRule;
+use ReflectionClass;
+use ReflectionMethod;
+use think\Cache;
+use think\Config;
+use think\console\Command;
+use think\console\Input;
+use think\console\input\Option;
+use think\console\Output;
+
+class Menu extends Command
+{
+
+    protected $model = null;
+
+    protected function configure()
+    {
+        $this
+                ->setName('menu')
+                ->addOption('controller', 'c', Option::VALUE_REQUIRED, 'controller name,use \'all-controller\' when build all menu', null)
+                ->setDescription('Build auth menu from controller');
+    }
+
+    protected function execute(Input $input, Output $output)
+    {
+        $this->model = new AuthRule();
+        $adminPath = dirname(__DIR__) . DS;
+        //控制器名
+        $controller = $input->getOption('controller') ? : '';
+        if (!$controller)
+        {
+            $output->error("please input controller name");
+            return;
+        }
+
+        if ($controller != 'all-controller')
+        {
+            $controllerArr = explode('/', $controller);
+            end($controllerArr);
+            $key = key($controllerArr);
+            $controllerArr[$key] = ucfirst($controllerArr[$key]);
+            $adminPath = dirname(__DIR__) . DS . 'controller' . DS . implode('/', $controllerArr) . '.php';
+            if (!is_file($adminPath))
+            {
+                $output->error("controller not found");
+                return;
+            }
+            $this->importRule($controller);
+        }
+        else
+        {
+            $this->model->destroy([]);
+            $controllerDir = $adminPath . 'controller' . DS;
+            // 扫描新的节点信息并导入
+            $treelist = $this->import($this->scandir($controllerDir));
+        }
+        Cache::rm("__menu__");
+        $output->info("Build Successed!");
+    }
+
+    /**
+     * 递归扫描文件夹
+     * @param string $dir
+     * @return array
+     */
+    public function scandir($dir)
+    {
+        $result = [];
+        $cdir = scandir($dir);
+        foreach ($cdir as $value)
+        {
+            if (!in_array($value, array(".", "..")))
+            {
+                if (is_dir($dir . '/' . $value))
+                {
+                    $result[$value] = $this->scandir($dir . '/' . $value);
+                }
+                else
+                {
+                    $result[] = $value;
+                }
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * 导入规则节点
+     * @param array $dirarr
+     * @param array $parentdir
+     * @return array
+     */
+    public function import($dirarr, $parentdir = [])
+    {
+        $menuarr = [];
+        foreach ($dirarr as $k => $v)
+        {
+            if (is_array($v))
+            {
+                //当前是文件夹
+                $nowparentdir = array_merge($parentdir, [$k]);
+                $this->import($v, $nowparentdir);
+            }
+            else
+            {
+                //只匹配PHP文件
+                if (!preg_match('/^(\w+)\.php$/', $v, $matchone))
+                {
+                    continue;
+                }
+                //导入文件
+                $controller = ($parentdir ? implode('/', $parentdir) . '/' : '') . $matchone[1];
+                $this->importRule($controller);
+            }
+        }
+
+        return $menuarr;
+    }
+
+    protected function importRule($controller)
+    {
+        $controllerArr = explode('/', $controller);
+        end($controllerArr);
+        $key = key($controllerArr);
+        $controllerArr[$key] = ucfirst($controllerArr[$key]);
+        //反射机制调用类的注释和方法名
+        $reflector = new ReflectionClass("\\app\\admin\\controller\\" . implode("\\", $controllerArr) . (Config::get('controller_suffix') ? ucfirst(Config::get('url_controller_layer')) : ''));
+        //只匹配公共的方法
+        $methods = $reflector->getMethods(ReflectionMethod::IS_PUBLIC);
+        $classComment = $reflector->getDocComment();
+        //忽略的类
+        if (stripos($classComment, "@internal") !== FALSE)
+        {
+            return;
+        }
+        preg_match_all('#(@.*?)\n#s', $classComment, $annotations);
+        $controllerIcon = 'fa fa-circle-o';
+        $controllerRemark = '';
+        //判断注释中是否设置了icon值
+        if (isset($annotations[1]))
+        {
+            foreach ($annotations[1] as $tag)
+            {
+                if (stripos($tag, '@icon') !== FALSE)
+                {
+                    $controllerIcon = substr($tag, stripos($tag, ' ') + 1);
+                }
+                if (stripos($tag, '@remark') !== FALSE)
+                {
+                    $controllerRemark = substr($tag, stripos($tag, ' ') + 1);
+                }
+            }
+        }
+        //过滤掉其它字符
+        $controllerTitle = trim(preg_replace(array('/^\/\*\*(.*)[\n\r\t]/', '/[\s]+\*\//', '/\*\s@(.*)/', '/[\s|\*]+/'), '', $classComment));
+        //先定入菜单的数据
+        $pid = 0;
+        $name = "/admin";
+        foreach (explode('/', $controller) as $k => $v)
+        {
+            $name .= '/' . strtolower($v);
+            $title = (!isset($controllerArr[$k + 1]) ? $controllerTitle : ucfirst($v));
+            $icon = (!isset($controllerArr[$k + 1]) ? $controllerIcon : 'fa fa-list');
+            $remark = (!isset($controllerArr[$k + 1]) ? $controllerRemark : '');
+            $title = $title ? $title : ucfirst($v);
+            $rulemodel = $this->model->get(['name' => $name]);
+            if (!$rulemodel)
+            {
+                $this->model
+                        ->data(['pid' => $pid, 'name' => $name, 'title' => $title, 'icon' => $icon, 'remark' => $remark, 'ismenu' => 1, 'status' => 'normal'])
+                        ->isUpdate(false)
+                        ->save();
+                $pid = $this->model->id;
+            }
+            else
+            {
+                $pid = $rulemodel->id;
+            }
+        }
+        $ruleArr = [];
+        foreach ($methods as $m => $n)
+        {
+            //过滤特殊的类
+            if (substr($n->name, 0, 2) == '__' || $n->name == '_initialize')
+            {
+                continue;
+            }
+            //只匹配符合的方法
+            if (!preg_match('/^(\w+)' . Config::get('action_suffix') . '/', $n->name, $matchtwo))
+            {
+                unset($methods[$m]);
+                continue;
+            }
+            $comment = $reflector->getMethod($n->name)->getDocComment();
+            //忽略的方法
+            if (stripos($comment, "@internal") !== FALSE)
+            {
+                continue;
+            }
+            //过滤掉其它字符
+            $comment = preg_replace(array('/^\/\*\*(.*)[\n\r\t]/', '/[\s]+\*\//', '/\*\s@(.*)/', '/[\s|\*]+/'), '', $comment);
+
+            $ruleArr[] = array('pid' => $pid, 'name' => $name . "/" . strtolower($n->name), 'icon' => 'fa fa-circle-o', 'title' => $comment ? $comment : $n->name, 'ismenu' => 0, 'status' => 'normal');
+        }
+        $this->model->saveAll($ruleArr);
+    }
+
+}

+ 136 - 0
application/admin/common.php

@@ -0,0 +1,136 @@
+<?php
+
+use app\admin\library\Auth;
+use app\common\model\Configvalue;
+use fast\Form;
+use think\Db;
+
+function get_upload_multipart($savekey = '', $mimetype = '', $maxsize = '')
+{
+    // 加载配置
+    $configvalue = new Configvalue;
+    // 上传参数配置配置
+    $uploadcfg = $configvalue->upload($savekey, $mimetype, $maxsize);
+
+    return json_encode(['policy' => $uploadcfg['policy'], 'signature' => $uploadcfg['signature']]);
+}
+
+function get_flag_list()
+{
+    return [
+        'h' => __('Hot'),
+        'i' => __('Index'),
+        'r' => __('Recommend'),
+    ];
+}
+
+/**
+ * 生成下拉列表
+ * @param string $name
+ * @param mixed $options
+ * @param mixed $selected
+ * @param mixed $attr
+ * @return string
+ */
+function build_select($name, $options, $selected = [], $attr = [])
+{
+    $options = is_array($options) ? $options : explode(',', $options);
+    $selected = is_array($selected) ? $selected : explode(',', $selected);
+    return Form::select($name, $options, $selected, $attr);
+}
+
+/**
+ * 生成单选按钮组
+ * @param string $name
+ * @param array $list
+ * @param mixed $selected
+ * @return string
+ */
+function build_radios($name, $list = [], $selected = null)
+{
+    $html = [];
+    $selected = is_null($selected) ? key($list) : $selected;
+    foreach ($list as $k => $v)
+    {
+        $html[] = sprintf(Form::label("{$name}-{$k}", "%s {$v}"), Form::radio($name, $k, $k == $selected, ['id' => "{$name}-{$k}"]));
+    }
+    return implode(' ', $html);
+}
+
+/**
+ * 生成复选按钮组
+ * @param string $name
+ * @param array $list
+ * @param mixed $selected
+ * @return string
+ */
+function build_checkboxs($name, $list = [], $selected = null)
+{
+    $html = [];
+    $selected = is_null($selected) ? [] : $selected;
+    foreach ($list as $k => $v)
+    {
+        $html[] = sprintf(Form::label("{$name}-{$k}", "%s {$v}"), Form::checkbox($name, $k, $k == $selected, ['id' => "{$name}-{$k}"]));
+    }
+    return implode(' ', $html);
+}
+
+/**
+ * 生成表格操作按钮栏
+ * @param array $btns
+ * @return string
+ */
+function build_toolbar($btns = NULL)
+{
+    $btns = $btns ? $btns : ['refresh', 'add', 'edit', 'delete'];
+    $btns = is_array($btns) ? $btns : explode(',', $btns);
+    $addbtn = __('Add');
+    $editbtn = __('Edit');
+    $deletebtn = __('Delete');
+    $html = [];
+    if (in_array('refresh', $btns))
+    {
+        $html[] = '<a class="btn btn-primary btn-refresh" ><i class="fa fa-refresh"></i></a>';
+    }
+    if (in_array('add', $btns))
+    {
+        $html[] = '<a class="btn btn-success btn-add" ><i class="fa fa-plus"></i> ' . $addbtn . '</a>';
+    }
+    if (in_array('edit', $btns))
+    {
+        $html[] = '<a class="btn btn-success btn-edit btn-disabled disabled" ><i class="fa fa-pencil"></i> ' . $editbtn . '</a>';
+    }
+    if (in_array('delete', $btns))
+    {
+        $html[] = '<a class="btn btn-danger btn-del btn-disabled disabled" ><i class="fa fa-trash"></i> ' . $deletebtn . '</a>';
+    }
+    return implode(' ', $html);
+}
+
+/**
+ * 生成页面Heading
+ *
+ * @param string $title
+ * @param string $content
+ * @return string
+ */
+function build_heading($title = NULL, $content = NULL)
+{
+    if (is_null($title) && is_null($content))
+    {
+        // 根据当前的URI自动匹配父节点的标题和备注
+        $path = Auth::instance()->getRequestUri();
+        $data = Db::name('auth_rule')->where('id', 'IN', function($query) use($path)
+                {
+                    $query->name('auth_rule')->where('name', $path)->field('pid');
+                })->find();
+        if ($data)
+        {
+            $title = $data['title'];
+            $content = $data['remark'];
+        }
+    }
+    if (!$content)
+        return '';
+    return '<div class="panel-heading"><div class="panel-lead"><em>' . $title . '</em>' . $content . '</div></div>';
+}

+ 8 - 0
application/admin/config.php

@@ -0,0 +1,8 @@
+<?php
+
+//配置文件
+return [
+    'url_common_param'       => true,
+    'url_html_suffix'        => '',
+    'controller_auto_search' => true,
+];

+ 284 - 0
application/admin/controller/Ajax.php

@@ -0,0 +1,284 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\common\controller\Backend;
+use fast\Http;
+use fast\Tree;
+use think\Db;
+use think\Lang;
+
+/**
+ * Ajax异步请求接口
+ * @internal
+ */
+class Ajax extends Backend
+{
+
+    protected $noNeedLogin = ['dailybg', 'lang'];
+    protected $noNeedRight = ['*'];
+    protected $layout = '';
+
+    /**
+     * 自动完成
+     */
+    public function typeahead()
+    {
+        $search = $this->_request->getRequest("search");
+        $field = $this->_request->getRequest("field");
+        $field = str_replace(['row[', ']'], '', $field);
+        if (substr($field, -3) !== '_id' && substr($field, -4) !== '_ids')
+        {
+            $this->code = -1;
+            return;
+        }
+        $searchfield = 'name';
+        $field = substr($field, 0, -3);
+        switch ($field)
+        {
+            case 'category':
+                $field = 'category';
+                $searchfield = 'name';
+                break;
+            case 'user':
+                $searchfield = 'nickname';
+                break;
+        }
+
+        $searchlist = Db::table($field)
+                ->orWhere($searchfield, 'like', "%{$search}%")
+                ->orWhere('id', 'like', "%{$search}%")
+                ->limit(10)
+                ->select("id,{$searchfield} AS name");
+
+        foreach ($searchlist as $k => &$v)
+        {
+            $v['name'] = $v['name'] . "[id:{$v['id']}]";
+        }
+        unset($v);
+        $this->code = 1;
+        $this->data = ['searchlist' => $searchlist];
+    }
+
+    /**
+     * 加载语言包
+     */
+    public function lang()
+    {
+        header('Content-Type: application/javascript');
+        $modulename = $this->request->module();
+        $callback = $this->request->get('callback');
+        $controllername = input("controllername");
+        Lang::load(APP_PATH . $modulename . '/lang/' . Lang::detect() . '/' . str_replace('.', '/', $controllername) . '.php');
+        //强制输出JSON Object
+//        $result = 'define(' . json_encode(Lang::get(), JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE) . ');';
+        return jsonp(Lang::get());
+    }
+
+    /**
+     * 每日一图
+     */
+    public function dailybg()
+    {
+        //采用Infinty的图片
+        $this->code = 1;
+        $this->data = [
+            'url' => 'http://img.infinitynewtab.com/wallpaper/' . (date("Ymd") % 4000) . '.jpg'
+        ];
+        return;
+        //采用Bing每日一图
+        $ret = Http::sendRequest("http://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1", [], 'GET');
+        if ($ret['ret'])
+        {
+            $json = json_decode($ret['msg'], TRUE);
+            if ($json && isset($json['images'][0]))
+            {
+                $url = $json['images'][0]['url'];
+                $startdate = $json['images'][0]['startdate'];
+                $enddate = $json['images'][0]['enddate'];
+                $copyright = $json['images'][0]['copyright'];
+                $url = substr($url, 0, 4) != 'http' ? 'http://cn.bing.com' . $url : $url;
+                $title = '';
+                $intro = '';
+                $ret = Http::sendRequest("http://cn.bing.com/cnhp/coverstory/", [], 'GET');
+                if ($ret['ret'])
+                {
+                    $info = json_decode($ret['msg'], TRUE);
+                    if (isset($info['title']))
+                    {
+                        $title = $info['title'];
+                        $intro = $info['para1'];
+                    }
+                }
+                $this->code = 1;
+                $this->data = [
+                    'title'     => $title,
+                    'intro'     => $intro,
+                    'url'       => $url,
+                    'startdate' => $startdate,
+                    'enddate'   => $enddate,
+                    'copyright' => $copyright,
+                ];
+            }
+        }
+    }
+
+    /**
+     * 读取角色权限树
+     */
+    public function roletree()
+    {
+        $model = model('AuthGroup');
+        $id = $this->request->post("id");
+        $pid = $this->request->post("pid");
+        $parentgroupmodel = $model->get($pid);
+        $currentgroupmodel = NULL;
+        if ($id)
+        {
+            $currentgroupmodel = $model->get($id);
+        }
+        if (($pid || $parentgroupmodel) && (!$id || $currentgroupmodel))
+        {
+            $id = $id ? $id : NULL;
+            //读取父类角色所有节点列表
+            $parentrulelist = model('AuthRule')->all(in_array('*', explode(',', $parentgroupmodel->rules)) ? NULL : $parentgroupmodel->rules);
+            //读取当前角色下规则ID集合
+            $admin_rule_ids = $this->auth->getRuleIds();
+            $superadmin = $this->auth->isSuperAdmin();
+            $current_rule_ids = $id ? explode(',', $currentgroupmodel->rules) : [];
+            if (!$id || !array_key_exists($pid, Tree::instance()->init($model->all(['status' => 'normal']))->getChildrenIds($id, TRUE)))
+            {
+                //构造jstree所需的数据
+                $nodelist = [];
+                foreach ($parentrulelist as $k => $v)
+                {
+                    if (!$superadmin && !in_array($v['id'], $admin_rule_ids))
+                        continue;
+                    $state = array('selected' => !$v['ismenu'] && in_array($v['id'], $current_rule_ids));
+                    $nodelist[] = array('id' => $v['id'], 'parent' => $v['pid'] ? $v['pid'] : '#', 'text' => $v['title'], 'type' => 'menu', 'state' => $state);
+                }
+                $this->code = 1;
+                $this->data = $nodelist;
+            }
+            else
+            {
+                $this->code = -1;
+                $this->data = __('Can not change the parent to child');
+            }
+        }
+        else
+        {
+            $this->code = -1;
+            $this->data = __('Group not found');
+        }
+    }
+
+    /**
+     * 上传文件
+     */
+    public function upload()
+    {
+        $this->code = -1;
+        $this->data = NULL;
+        $file = $this->request->file('file');
+        dump($file);
+        $uploaddir = '/public/uploads/';
+        $info = $file->move(ROOT_PATH . $uploaddir);
+        if ($info)
+        {
+            $this->code = 1;
+            $this->data = $uploaddir . $info->getSaveName();
+        }
+        else
+        {
+            // 上传失败获取错误信息
+            $this->data = $file->getError();
+        }
+    }
+
+    /**
+     * 通用排序
+     */
+    public function weigh()
+    {
+        //排序的数组
+        $ids = $this->request->post("ids");
+        //拖动的记录ID
+        $changeid = $this->request->post("changeid");
+        //操作字段
+        $field = $this->request->post("field");
+        //操作的数据表
+        $table = $this->request->post("table");
+        //排序的方式
+        $orderway = $this->request->post("orderway", 'strtolower');
+        $orderway = $orderway == 'asc' ? 'ASC' : 'DESC';
+        $sour = $weighdata = [];
+        $ids = explode(',', $ids);
+        $prikey = 'id';
+        $pid = $this->request->post("pid");
+
+        // 如果设定了pid的值,此时只匹配满足条件的ID,其它忽略
+        if ($pid !== '')
+        {
+            $hasids = [];
+            $list = Db::name($table)->where($prikey, 'in', $ids)->where('pid', 'in', $pid)->field('id,pid')->select();
+            foreach ($list as $k => $v)
+            {
+                $hasids[] = $v['id'];
+            }
+            $ids = array_values(array_intersect($ids, $hasids));
+        }
+
+        //直接修复排序
+        $one = Db::name($table)->field("{$field},COUNT(*) AS nums")->group($field)->having('nums > 1')->find();
+        if ($one)
+        {
+            $list = Db::name($table)->field("$prikey,$field")->order($field, $orderway)->select();
+            foreach ($list as $k => $v)
+            {
+                Db::name($table)->where($prikey, $v[$prikey])->update([$field => $k + 1]);
+            }
+            $this->code = 1;
+        }
+        else
+        {
+            $list = Db::name($table)->field("$prikey,$field")->where($prikey, 'in', $ids)->order($field, $orderway)->select();
+            foreach ($list as $k => $v)
+            {
+                $sour[] = $v[$prikey];
+                $weighdata[$v[$prikey]] = $v[$field];
+            }
+            $position = array_search($changeid, $ids);
+            $desc_id = $sour[$position];    //移动到目标的ID值,取出所处改变前位置的值
+            $sour_id = $changeid;
+            $desc_value = $weighdata[$desc_id];
+            $sour_value = $weighdata[$sour_id];
+            //echo "移动的ID:{$sour_id}\n";
+            //echo "替换的ID:{$desc_id}\n";
+            $weighids = array();
+            $temp = array_values(array_diff_assoc($ids, $sour));
+            foreach ($temp as $m => $n)
+            {
+                if ($n == $sour_id)
+                {
+                    $offset = $desc_id;
+                }
+                else
+                {
+                    if ($sour_id == $temp[0])
+                    {
+                        $offset = isset($temp[$m + 1]) ? $temp[$m + 1] : $sour_id;
+                    }
+                    else
+                    {
+                        $offset = isset($temp[$m - 1]) ? $temp[$m - 1] : $sour_id;
+                    }
+                }
+                $weighids[$n] = $weighdata[$offset];
+                Db::name($table)->where($prikey, $n)->update([$field => $weighdata[$offset]]);
+            }
+            $this->code = 1;
+        }
+    }
+
+}

+ 45 - 0
application/admin/controller/Dashboard.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\common\controller\Backend;
+
+/**
+ * 控制台
+ *
+ * @icon fa fa-dashboard
+ * @remark 用于展示当前系统中的统计数据、统计报表及重要实时数据
+ */
+class Dashboard extends Backend
+{
+
+    public function index()
+    {
+        $seventtime = \fast\Date::unixtime('day', -7);
+        $paylist = $createlist = [];
+        for ($i = 0; $i < 7; $i++)
+        {
+            $day = date("Y-m-d", $seventtime + ($i * 86400));
+            $createlist[$day] = mt_rand(20, 200);
+            $paylist[$day] = mt_rand(1, mt_rand(1, $createlist[$day]));
+        }
+        $this->view->assign([
+            'totaluser'          => 3500,
+            'totalviews'         => 219390,
+            'totalorder'         => 32143,
+            'totalorderamount'   => 174800,
+            'todayuserlogin'     => 321,
+            'todayusersignup'    => 430,
+            'todayorder'         => 2324,
+            'todayunsettleorder' => 132,
+            'sevendnu'           => '80%',
+            'sevendau'           => '32%',
+            'paylist'            => $paylist,
+            'createlist'         => $createlist,
+        ]);
+
+
+        return $this->view->fetch();
+    }
+
+}

+ 109 - 0
application/admin/controller/Index.php

@@ -0,0 +1,109 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\common\controller\Backend;
+use fast\Menu;
+use think\Validate;
+
+/**
+ * 后台首页
+ * @internal
+ */
+class Index extends Backend
+{
+
+    protected $noNeedLogin = ['login', 'logout'];
+    protected $noNeedRight = ['index'];
+    protected $layout = '';
+
+    public function _initialize()
+    {
+        parent::_initialize();
+    }
+
+    /**
+     * 后台首页
+     */
+    public function index()
+    {
+        //
+        $menulist = Menu::instance()->sidebar([
+            'dashboard'  => 'hot',
+            'auth'       => ['new', 'red', 'badge'],
+            'auth/admin' => 12,
+            'auth/rule'  => 4,
+            'general'    => ['18', 'purple'],
+        ]);
+        $this->view->assign('menulist', $menulist);
+        $this->view->assign('title', __('Home'));
+        return $this->view->fetch();
+    }
+
+    /**
+     * 管理员登录
+     */
+    public function login()
+    {
+        $url = $this->request->get('url', 'index/index');
+        if ($this->auth->isLogin())
+        {
+            $this->error(__("You've logged in, do not login again"), $url);
+            return;
+        }
+        if ($this->request->isPost())
+        {
+            $username = $this->request->post('username');
+            $password = $this->request->post('password');
+            $keeplogin = $this->request->post('keeplogin');
+            $token = $this->request->post('__token__');
+            $rule = [
+                'username'  => 'require|length:3,30',
+                'password'  => 'require|length:3,30',
+                '__token__' => 'token',
+            ];
+            $data = [
+                'username'  => $username,
+                'password'  => $password,
+                '__token__' => $token,
+            ];
+            $validate = new Validate($rule);
+            $result = $validate->check($data);
+            if (!$result)
+            {
+                $this->error($validate->getError());
+                return;
+            }
+            $result = $this->auth->login($username, $password, $keeplogin ? 86400 : 0);
+            if ($result === true)
+            {
+                $this->success(__('Login success'), $url);
+                return;
+            }
+            else
+            {
+                $this->success(__('Username or password is incorrect'), $url);
+            }
+            return;
+        }
+
+        // 根据客户端的cookie,判断是否可以自动登录
+        if ($this->auth->autologin())
+        {
+            $this->redirect($url);
+        }
+        $this->view->assign('title', __('Login'));
+        return $this->view->fetch();
+    }
+
+    /**
+     * 注销登录
+     */
+    public function logout()
+    {
+        $this->auth->logout();
+        $this->success(__('Logout success!'), 'index/login');
+        return;
+    }
+
+}

+ 24 - 0
application/admin/controller/Page.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\common\controller\Backend;
+
+/**
+ * 单页管理
+ *
+ * @icon fa fa-circle-o
+ * @remark 用于管理普通的单页面,通常用于关于我们、联系我们、商务合作等单一页面
+ */
+class Page extends Backend
+{
+
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = model('Page');
+    }
+
+}

+ 151 - 0
application/admin/controller/auth/Admin.php

@@ -0,0 +1,151 @@
+<?php
+
+namespace app\admin\controller\auth;
+
+use app\common\controller\Backend;
+use fast\Random;
+use fast\Tree;
+
+/**
+ * 管理员管理
+ *
+ * @icon fa fa-users
+ * @remark 一个管理员可以有多个角色组,左侧的菜单根据管理员所拥有的权限进行生成
+ */
+class Admin extends Backend
+{
+
+    protected $model = null;
+    //当前登录管理员所有子节点组别
+    protected $childrenIds = [];
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = model('Admin');
+
+        $groups = $this->auth->getGroups();
+
+        // 取出所有分组
+        $grouplist = model('AuthGroup')->all(['status' => 'normal']);
+        $objlist = [];
+        foreach ($groups as $K => $v)
+        {
+            // 取出包含自己的所有子节点
+            $childrenlist = Tree::instance()->init($grouplist)->getChildren($v['id'], TRUE);
+            $obj = Tree::instance()->init($childrenlist)->getTreeArray($v['pid']);
+            $objlist = array_merge($objlist, Tree::instance()->getTreeList($obj));
+        }
+        $groupdata = [];
+        foreach ($objlist as $k => $v)
+        {
+            $groupdata[$v['id']] = $v['name'];
+        }
+        $this->childrenIds = array_keys($groupdata);
+        $this->view->assign('groupdata', $groupdata);
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                $params['salt'] = Random::basic(4);
+                $params['password'] = md5(md5($params['password']) . $params['salt']);
+
+                $admin = $this->model->create($params);
+                $group = $this->request->post("group/a");
+
+                //过滤不允许的组别,避免越权
+                $group = array_intersect($this->childrenIds, $group);
+                $dataset = [];
+                foreach ($group as $value)
+                {
+                    $dataset[] = ['uid' => $admin->id, 'group_id' => $value];
+                }
+                model('AuthGroupAccess')->saveAll($dataset);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit($ids = NULL)
+    {
+        $row = $this->model->get(['id' => $ids]);
+        if (!$row)
+            $this->error(__('No Results were found'));
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                if ($params['password'])
+                {
+                    $params['salt'] = Random::basic(4);
+                    $params['password'] = md5(md5($params['password']) . $params['salt']);
+                }
+                $row->save($params);
+
+                // 先移除所有权限
+                model('AuthGroupAccess')->where('uid', $row->id)->delete();
+
+                $group = $this->request->post("group/a");
+
+                // 过滤不允许的组别,避免越权
+                $group = array_intersect($this->childrenIds, $group);
+
+                $dataset = [];
+                foreach ($group as $value)
+                {
+                    $dataset[] = ['uid' => $row->id, 'group_id' => $value];
+                }
+                model('AuthGroupAccess')->saveAll($dataset);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        $grouplist = $this->auth->getGroups($row['id']);
+        $groupids = [];
+        foreach ($grouplist as $k => $v)
+        {
+            $groupids[] = $v['id'];
+        }
+        $this->view->assign("row", $row);
+        $this->view->assign("groupids", $groupids);
+        return $this->view->fetch();
+    }
+
+    /**
+     * 删除
+     */
+    public function del($ids = "")
+    {
+        $this->code = -1;
+        if ($ids)
+        {
+            $count = $this->model->where('id', 'in', $ids)->delete();
+            if ($count)
+            {
+                model('AuthGroupAccess')->where('uid', 'in', $ids)->delete();
+                $this->code = 1;
+            }
+        }
+
+        return;
+    }
+
+}

+ 219 - 0
application/admin/controller/auth/Group.php

@@ -0,0 +1,219 @@
+<?php
+
+namespace app\admin\controller\auth;
+
+use app\common\controller\Backend;
+use fast\Tree;
+
+/**
+ * 角色组
+ *
+ * @icon fa fa-group
+ * @remark 角色组可以有多个,角色有上下级层级关系,如果子角色有角色组和管理员的权限则可以派生属于自己组别下级的角色组或管理员
+ */
+class Group extends Backend
+{
+
+    protected $model = null;
+    //当前登录管理员所有子节点组别
+    protected $childrenIds = [];
+    //当前组别列表数据
+    protected $groupdata = [];
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = model('AuthGroup');
+
+        $groups = $this->auth->getGroups();
+
+        // 取出所有分组
+        $grouplist = model('AuthGroup')->all(['status' => 'normal']);
+        $objlist = [];
+        foreach ($groups as $K => $v)
+        {
+            // 取出包含自己的所有子节点
+            $childrenlist = Tree::instance()->init($grouplist)->getChildren($v['id'], TRUE);
+            $obj = Tree::instance()->init($childrenlist)->getTreeArray($v['pid']);
+            $objlist = array_merge($objlist, Tree::instance()->getTreeList($obj));
+        }
+
+        $groupdata = [];
+        foreach ($objlist as $k => $v)
+        {
+            $groupdata[$v['id']] = $v['name'];
+        }
+        $this->groupdata = $groupdata;
+        $this->childrenIds = array_keys($groupdata);
+        $this->view->assign('groupdata', $groupdata);
+    }
+
+    /**
+     * 查看
+     */
+    public function index()
+    {
+        if ($this->request->isAjax())
+        {
+            $list = [];
+            foreach ($this->groupdata as $k => $v)
+            {
+                $data = $this->model->get($k);
+                $data->name = $v;
+                $list[] = $data;
+            }
+            $total = count($list);
+            $result = array("total" => $total, "rows" => $list);
+
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            $params['rules'] = explode(',', $params['rules']);
+            if (!in_array($params['pid'], $this->childrenIds))
+            {
+                $this->code = -1;
+                return;
+            }
+            $parentmodel = model("AuthGroup")->get($params['pid']);
+            if (!$parentmodel)
+            {
+                $this->code = -1;
+                return;
+            }
+            // 父级别的规则节点
+            $parentrules = explode(',', $parentmodel->rules);
+            // 当前组别的规则节点
+            $currentrules = $this->auth->getRuleIds();
+            $rules = $params['rules'];
+            // 如果父组不是超级管理员则需要过滤规则节点,不能超过父组别的权限
+            $rules = in_array('*', $parentrules) ? $rules : array_intersect($parentrules, $rules);
+            // 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限
+            $rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules);
+            $params['rules'] = implode(',', $rules);
+            if ($params)
+            {
+                $this->model->create($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit($ids = NULL)
+    {
+        $row = $this->model->get(['id' => $ids]);
+        if (!$row)
+            $this->error(__('No Results were found'));
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            // 复节点不能是它自身的子节点
+            if (!in_array($params['pid'], $this->childrenIds))
+            {
+                $this->code = -1;
+                return;
+            }
+            $params['rules'] = explode(',', $params['rules']);
+
+            $parentmodel = model("AuthGroup")->get($params['pid']);
+            if (!$parentmodel)
+            {
+                $this->code = -1;
+                return;
+            }
+            // 父级别的规则节点
+            $parentrules = explode(',', $parentmodel->rules);
+            // 当前组别的规则节点
+            $currentrules = $this->auth->getRuleIds();
+            $rules = $params['rules'];
+            // 如果父组不是超级管理员则需要过滤规则节点,不能超过父组别的权限
+            $rules = in_array('*', $parentrules) ? $rules : array_intersect($parentrules, $rules);
+            // 如果当前组别不是超级管理员则需要过滤规则节点,不能超当前组别的权限
+            $rules = in_array('*', $currentrules) ? $rules : array_intersect($currentrules, $rules);
+            $params['rules'] = implode(',', $rules);
+            if ($params)
+            {
+                $row->save($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        $this->view->assign("row", $row);
+        return $this->view->fetch();
+    }
+
+    /**
+     * 删除
+     */
+    public function del($ids = "")
+    {
+        $this->code = -1;
+        if ($ids)
+        {
+            $ids = explode(',', $ids);
+            $grouplist = $this->auth->getGroups();
+            $group_ids = array_map(function($group)
+            {
+                return $group['id'];
+            }, $grouplist);
+            // 移除掉当前管理员所在组别
+            $ids = array_diff($ids, $group_ids);
+
+            // 循环判断每一个组别是否可删除
+            $grouplist = $this->model->where('id', 'in', $ids)->select();
+            $groupaccessmodel = model('AuthGroupAccess');
+            foreach ($grouplist as $k => $v)
+            {
+                // 当前组别下有管理员
+                $groupone = $groupaccessmodel->get(['group_id' => $v['id']]);
+                if ($groupone)
+                {
+                    $ids = array_diff($ids, [$v['id']]);
+                    continue;
+                }
+                // 当前组别下有子组别
+                $groupone = $this->model->get(['pid' => $v['id']]);
+                if ($groupone)
+                {
+                    $ids = array_diff($ids, [$v['id']]);
+                    continue;
+                }
+            }
+            $count = $this->model->where('id', 'in', $ids)->delete();
+            if ($count)
+            {
+                $this->code = 1;
+            }
+        }
+        return;
+    }
+
+    /**
+     * 批量更新
+     */
+    public function multi($ids = "")
+    {
+        // 组别禁止批量操作
+        $this->code = -1;
+        return;
+    }
+
+}

+ 114 - 0
application/admin/controller/auth/Rule.php

@@ -0,0 +1,114 @@
+<?php
+
+namespace app\admin\controller\auth;
+
+use app\common\controller\Backend;
+use fast\Tree;
+
+/**
+ * 规则管理
+ *
+ * @icon fa fa-list
+ * @remark 规则通常对应一个控制器的方法,同时左侧的菜单栏数据也从规则中体现,通常建议通过控制台进行生成规则节点
+ */
+class Rule extends Backend
+{
+
+    protected $model = null;
+    protected $rulelist = [];
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = model('AuthRule');
+        // 必须将结果集转换为数组
+        Tree::instance()->init(collection($this->model->order('weigh', 'desc')->select())->toArray());
+        $this->rulelist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'title');
+        $ruledata = [];
+        foreach ($this->rulelist as $k => $v)
+        {
+            $ruledata[$v['id']] = $v['title'];
+        }
+        $this->view->assign('ruledata', $ruledata);
+    }
+
+    /**
+     * 查看
+     */
+    public function index()
+    {
+        if ($this->request->isAjax())
+        {
+            $list = $this->rulelist;
+            $total = count($this->rulelist);
+
+            $result = array("total" => $total, "rows" => $list);
+
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                $this->model->create($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit($ids = NULL)
+    {
+        $row = $this->model->get(['id' => $ids]);
+        if (!$row)
+            $this->error(__('No Results were found'));
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                $row->save($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        $this->view->assign("row", $row);
+        return $this->view->fetch();
+    }
+
+    /**
+     * 删除
+     */
+    public function del($ids = "")
+    {
+        $this->code = -1;
+        if ($ids)
+        {
+            $count = $this->model->where('id', 'in', $ids)->delete();
+            if ($count)
+            {
+                $this->code = 1;
+            }
+        }
+
+        return;
+    }
+
+}

+ 159 - 0
application/admin/controller/general/Attachment.php

@@ -0,0 +1,159 @@
+<?php
+
+namespace app\admin\controller\general;
+
+use app\common\controller\Backend;
+
+/**
+ * 附件管理
+ *
+ * @icon fa fa-circle-o
+ * @remark 主要用于管理上传到又拍云的数据或上传至本服务的上传数据
+ */
+class Attachment extends Backend
+{
+
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = model('Attachment');
+    }
+
+    /**
+     * 查看
+     */
+    public function index()
+    {
+        if ($this->request->isAjax())
+        {
+            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
+            $total = $this->model
+                    ->where($where)
+                    ->order($sort, $order)
+                    ->count();
+
+            $list = $this->model
+                    ->where($where)
+                    ->order($sort, $order)
+                    ->limit($offset, $limit)
+                    ->select();
+
+            $result = array("total" => $total, "rows" => $list);
+
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                if ($this->request->has('field'))
+                {
+                    //JSON字段
+                    $fieldarr = $valuearr = [];
+                    $field = $this->request->post('field/a');
+                    $value = $this->request->post('value/a');
+                    foreach ($field as $k => $v)
+                    {
+                        if ($v != '')
+                        {
+                            $fieldarr[] = $field[$k];
+                            $valuearr[] = $value[$k];
+                        }
+                    }
+                    $params['content'] = array_combine($fieldarr, $valuearr);
+                }
+                $this->model->save($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit($ids = NULL)
+    {
+        $row = $this->model->get(['id' => $ids]);
+        if (!$row)
+            $this->error(__('No Results were found'));
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                $row->save($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        $this->view->assign("row", $row);
+        return $this->view->fetch();
+    }
+
+    /**
+     * 删除
+     */
+    public function del($ids = "")
+    {
+        $this->code = -1;
+        if ($ids)
+        {
+            $count = $this->model->where('id', 'in', $ids)->delete();
+            if ($count)
+            {
+                $this->code = 1;
+            }
+        }
+
+        return;
+    }
+
+    /**
+     * 批量更新
+     */
+    public function multi($ids = "")
+    {
+        $this->code = -1;
+        $ids = $ids ? $ids : $this->request->param("ids");
+        if ($ids)
+        {
+            if ($this->request->has('params'))
+            {
+                parse_str($this->request->post("params"), $values);
+                $values = array_intersect_key($values, array_flip(array('status')));
+                if ($values)
+                {
+                    $count = $this->model->where('id', 'in', $ids)->update($values);
+                    if ($count)
+                    {
+                        $this->code = 1;
+                    }
+                }
+            }
+            else
+            {
+                $this->code = 1;
+            }
+        }
+
+        return;
+    }
+
+}

+ 175 - 0
application/admin/controller/general/Configvalue.php

@@ -0,0 +1,175 @@
+<?php
+
+namespace app\admin\controller\general;
+
+use app\common\controller\Backend;
+
+/**
+ * 基本配置
+ *
+ * @icon fa fa-cog
+ * @remark 用于管理一些字典数据,通常以键值格式进行录入,保存的数据格式为JSON
+ */
+class Configvalue extends Backend
+{
+
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = model('Configvalue');
+    }
+
+    /**
+     * 查看
+     */
+    public function index()
+    {
+        if ($this->request->isAjax())
+        {
+            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
+            $total = $this->model
+                    ->where($where)
+                    ->order($sort, $order)
+                    ->count();
+
+            $list = $this->model
+                    ->where($where)
+                    ->order($sort, $order)
+                    ->limit($offset, $limit)
+                    ->select();
+
+            $result = array("total" => $total, "rows" => $list);
+
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                if ($this->request->has('field'))
+                {
+                    //JSON字段
+                    $fieldarr = $valuearr = [];
+                    $field = $this->request->post('field/a');
+                    $value = $this->request->post('value/a');
+                    foreach ($field as $k => $v)
+                    {
+                        if ($v != '')
+                        {
+                            $fieldarr[] = $field[$k];
+                            $valuearr[] = $value[$k];
+                        }
+                    }
+                    $params['content'] = array_combine($fieldarr, $valuearr);
+                }
+                $this->model->save($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit($ids = NULL)
+    {
+        $row = $this->model->get(['id' => $ids]);
+        if (!$row)
+            $this->error(__('No Results were found'));
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                if ($this->request->has('field'))
+                {
+                    //JSON字段
+                    $fieldarr = $valuearr = [];
+                    $field = $this->request->post('field/a');
+                    $value = $this->request->post('value/a');
+                    foreach ($field as $k => $v)
+                    {
+                        if ($v != '')
+                        {
+                            $fieldarr[] = $field[$k];
+                            $valuearr[] = $value[$k];
+                        }
+                    }
+                    $params['content'] = array_combine($fieldarr, $valuearr);
+                }
+                $row->save($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        $this->view->assign("row", $row);
+        return $this->view->fetch();
+    }
+
+    /**
+     * 删除
+     */
+    public function del($ids = "")
+    {
+        $this->code = -1;
+        if ($ids)
+        {
+            $count = $this->model->where('id', 'in', $ids)->delete();
+            if ($count)
+            {
+                $this->code = 1;
+            }
+        }
+
+        return;
+    }
+
+    /**
+     * 批量更新
+     */
+    public function multi($ids = "")
+    {
+        $this->code = -1;
+        $ids = $ids ? $ids : $this->request->param("ids");
+        if ($ids)
+        {
+            if ($this->request->has('params'))
+            {
+                parse_str($this->request->post("params"), $values);
+                $values = array_intersect_key($values, array_flip(array('status')));
+                if ($values)
+                {
+                    $count = $this->model->where('id', 'in', $ids)->update($values);
+                    if ($count)
+                    {
+                        $this->code = 1;
+                    }
+                }
+            }
+            else
+            {
+                $this->code = 1;
+            }
+        }
+
+        return;
+    }
+
+}

+ 147 - 0
application/admin/controller/general/Crontab.php

@@ -0,0 +1,147 @@
+<?php
+
+namespace app\admin\controller\general;
+
+use app\common\controller\Backend;
+
+/**
+ * 定时任务
+ *
+ * @icon fa fa-tasks
+ * @remark 类似于Linux的Crontab定时任务,可以按照设定的时间进行任务的执行,目前仅支持三种任务:请求URL、执行SQL、执行Shell
+ */
+class Crontab extends Backend
+{
+
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = model('Crontab');
+        $this->view->assign('typedata', [
+            'url'   => __('Request Url'),
+            'sql'   => __('Execute Sql Script'),
+            'shell' => __('Execute Shell'),
+        ]);
+    }
+
+    /**
+     * 查看
+     */
+    public function index()
+    {
+        if ($this->request->isAjax())
+        {
+            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
+            $total = $this->model
+                    ->where($where)
+                    ->order($sort, $order)
+                    ->count();
+
+            $list = $this->model
+                    ->where($where)
+                    ->order($sort, $order)
+                    ->limit($offset, $limit)
+                    ->select();
+            $result = array("total" => $total, "rows" => $list);
+
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                $this->model->create($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit($ids = NULL)
+    {
+        $row = $this->model->get(['id' => $ids]);
+        if (!$row)
+            $this->error(__('No Results were found'));
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                $row->save($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        $this->view->assign("row", $row);
+        return $this->view->fetch();
+    }
+
+    /**
+     * 删除
+     */
+    public function del($ids = "")
+    {
+        $this->code = -1;
+        if ($ids)
+        {
+            $count = $this->model->where('id', 'in', $ids)->delete();
+            if ($count)
+            {
+                $this->code = 1;
+            }
+        }
+
+        return;
+    }
+
+    /**
+     * 批量更新
+     */
+    public function multi($ids = "")
+    {
+        $this->code = -1;
+        $ids = $ids ? $ids : $this->request->param("ids");
+        if ($ids)
+        {
+            if ($this->request->has('params'))
+            {
+                parse_str($this->request->post("params"), $values);
+                $values = array_intersect_key($values, array_flip(array('status')));
+                if ($values)
+                {
+                    $count = $this->model->where('id', 'in', $ids)->update($values);
+                    if ($count)
+                    {
+                        $this->code = 1;
+                    }
+                }
+            }
+            else
+            {
+                $this->code = 1;
+            }
+        }
+
+        return;
+    }
+
+}

+ 219 - 0
application/admin/controller/general/Database.php

@@ -0,0 +1,219 @@
+<?php
+
+namespace app\admin\controller\general;
+
+use app\common\controller\Backend;
+use think\Db;
+use think\Debug;
+
+/**
+ * 数据库管理
+ *
+ * @icon fa fa-database
+ * @remark 可在线进行一些简单的数据库表优化或修复,查看表结构和数据。也可以进行SQL语句的操作
+ */
+class Database extends Backend
+{
+
+    /**
+     * 查看
+     */
+    function index()
+    {
+        $tables_data_length = $tables_index_length = $tables_free_length = $tables_data_count = 0;
+        $tables = $list = [];
+        $list = Db::query("SHOW TABLES");
+        foreach ($list as $key => $row)
+        {
+            $tables[] = ['name' => reset($row), 'rows' => 0];
+        }
+        $data['tables'] = $tables;
+        /*
+          $one = Db::table('configvalue')->where('name', 'sql')->find();
+          $saved_sql = [];
+          if ($one && $one['content'])
+          $saved_sql = explode('###', $one['content']);
+
+          $data['saved_sql'] = array_values(array_filter($saved_sql));
+         * */
+        $data['saved_sql'] = [];
+        $this->view->assign($data);
+        return $this->view->fetch();
+    }
+
+    /**
+     * SQL查询
+     */
+    public function query()
+    {
+        $do_action = $this->request->post('do_action');
+
+        echo '<style type="text/css">
+            xmp,body{margin:0;padding:0;line-height:18px;font-size:12px;font-family:"Helvetica Neue", Helvetica, Microsoft Yahei, Hiragino Sans GB, WenQuanYi Micro Hei, sans-serif;}
+            hr{height:1px;margin:5px 1px;background:#e3e3e3;border:none;}
+            </style>';
+        if ($do_action == '')
+            exit(__('Invalid parameters'));
+
+        $tablename = $this->request->post("tablename/a");
+
+        if (in_array($do_action, array('doquery', 'optimizeall', 'repairall')))
+        {
+            $this->$do_action();
+        }
+        else if (count($tablename) == 0)
+        {
+            exit(__('Invalid parameters'));
+        }
+        else
+        {
+            foreach ($tablename as $table)
+            {
+                $this->$do_action($table);
+                echo "<br />";
+            }
+        }
+    }
+
+    private function viewinfo($name)
+    {
+        $row = Db::query("SHOW CREATE TABLE `{$name}`");
+        $row = array_values($row[0]);
+        $info = $row[1];
+        echo "<xmp>{$info};</xmp>";
+    }
+
+    private function viewdata($name = '')
+    {
+        $sqlquery = "SELECT * FROM `{$name}`";
+        $this->doquery($sqlquery);
+    }
+
+    private function optimize($name = '')
+    {
+        if (Db::execute("OPTIMIZE TABLE `{$name}`"))
+        {
+            echo __('Optimize table %s done', $name);
+        }
+        else
+        {
+            echo __('Optimize table %s fail', $name);
+        }
+    }
+
+    private function optimizeall($name = '')
+    {
+        $list = Db::query("SHOW TABLES");
+        foreach ($list as $key => $row)
+        {
+            $name = reset($row);
+            if (Db::execute("OPTIMIZE TABLE {$name}"))
+            {
+                echo __('Optimize table %s done', $name);
+            }
+            else
+            {
+                echo __('Optimize table %s fail', $name);
+            }
+            echo "<br />";
+        }
+    }
+
+    private function repair($name = '')
+    {
+        if (Db::execute("REPAIR TABLE `{$name}`"))
+        {
+            echo __('Repair table %s done', $name);
+        }
+        else
+        {
+            echo __('Repair table %s fail', $name);
+        }
+    }
+
+    private function repairall($name = '')
+    {
+        $list = Db::query("SHOW TABLES");
+        foreach ($list as $key => $row)
+        {
+            $name = reset($row);
+            if (Db::execute("REPAIR TABLE {$name}"))
+            {
+                echo __('Repair table %s done', $name);
+            }
+            else
+            {
+                echo __('Repair table %s fail', $name);
+            }
+            echo "<br />";
+        }
+    }
+
+    private function doquery($sql = null)
+    {
+        $sqlquery = $sql ? $sql : $this->request->post('sqlquery');
+        if ($sqlquery == '')
+            exit(__('SQL can not be empty'));
+        $sqlquery = str_replace("\r", "", $sqlquery);
+        $sqls = preg_split("/;[ \t]{0,}\n/i", $sqlquery);
+        $maxreturn = 100;
+        $r = '';
+        foreach ($sqls as $key => $val)
+        {
+            if (trim($val) == '')
+                continue;
+            $val = rtrim($val, ';');
+            $r .= "SQL:<span style='color:green;'>{$val}</span> ";
+            if (preg_match("/^(select|explain)(.*)/i ", $val))
+            {
+                Debug::remark("begin");
+                $limit = stripos(strtolower($val), "limit") !== false ? true : false;
+                $count = Db::execute($val);
+                if ($count > 0)
+                {
+                    $resultlist = Db::query($val . (!$limit && $count > $maxreturn ? ' LIMIT ' . $maxreturn : ''));
+                }
+                else
+                {
+                    $resultlist = [];
+                }
+                Debug::remark("end");
+                $time = Debug::getRangeTime('begin', 'end', 4);
+
+                $usedseconds = __('Query took %s seconds', $time) . "<br />";
+                if ($count <= 0)
+                {
+                    $r .= __('Query returned an empty result');
+                }
+                else
+                {
+                    $r .= (__('Total:%s', $count) . (!$limit && $count > $maxreturn ? ',' . __('Max output:%s', $maxreturn) : ""));
+                }
+                $r = $r . ',' . $usedseconds;
+                $j = 0;
+                foreach ($resultlist as $m => $n)
+                {
+                    $j++;
+                    if (!$limit && $j > $maxreturn)
+                        break;
+                    $r .= "<hr/>";
+                    $r .= "<font color='red'>" . __('Row:%s', $j) . "</font><br />";
+                    foreach ($n as $k => $v)
+                    {
+                        $r .= "<font color='blue'>{$k}:</font>{$v}<br/>\r\n";
+                    }
+                }
+            }
+            else
+            {
+                Debug::remark("begin");
+                $count = Db::execute($val);
+                Debug::remark("end");
+                $time = Debug::getRangeTime('begin', 'end', 4);
+                $r .= __('Query affected %s rows and took %s seconds', $count, $time) . "<br />";
+            }
+        }
+        echo $r;
+    }
+
+}

+ 68 - 0
application/admin/controller/general/Profile.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace app\admin\controller\general;
+
+use app\common\controller\Backend;
+
+/**
+ * 个人配置
+ *
+ * @icon fa fa-user
+ */
+class Profile extends Backend
+{
+
+    /**
+     * 查看
+     */
+    public function index()
+    {
+        if ($this->request->isAjax())
+        {
+            $model = model('AdminLog');
+            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
+
+            $total = $model
+                    ->where($where)
+                    ->order($sort, $order)
+                    ->count();
+
+            $list = $model
+                    ->where($where)
+                    ->order($sort, $order)
+                    ->limit($offset, $limit)
+                    ->select();
+
+            $result = array("total" => $total, "rows" => $list);
+
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 更新个人信息
+     */
+    public function update()
+    {
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            $params = array_filter(array_intersect_key($params, array_flip(array('email', 'nickname', 'password'))));
+            unset($v);
+            if (isset($params['password']))
+            {
+                $params['salt'] = Random::basic(4);
+                $params['password'] = md5(md5($params['password']) . $params['salt']);
+            }
+            if ($params)
+            {
+                model('admin')->where('id', Auth::id())->update($params);
+                $this->code = 0;
+            }
+        }
+        return;
+    }
+
+}

+ 49 - 0
application/admin/controller/wechat/Autoreply.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace app\admin\controller\wechat;
+
+use app\common\controller\Backend;
+use app\common\model\WechatResponse;
+use think\Db;
+
+/**
+ * 微信自动回复管理
+ *
+ * @icon fa fa-circle-o
+ */
+class Autoreply extends Backend
+{
+
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = model('WechatAutoreply');
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit($ids = NULL)
+    {
+        $row = Db::table($this->table)->where('id', $ids)->get();
+        if (!$row)
+            $this->error(__('No Results were found'));
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                $row->save($params);
+                $this->code = 1;
+            }
+            return FALSE;
+        }
+        $response = WechatResponse::get(['eventkey' => $row['eventkey']]);
+        $this->view->assign("response", $response);
+        $this->view->assign("row", $row);
+    }
+
+}

+ 127 - 0
application/admin/controller/wechat/Config.php

@@ -0,0 +1,127 @@
+<?php
+
+namespace app\admin\controller\wechat;
+
+use app\common\controller\Backend;
+use app\common\model\Configvalue;
+
+/**
+ * 配置管理
+ *
+ * @icon fa fa-list-alt
+ */
+class Config extends Backend
+{
+
+    protected $wechatcfg = NULL;
+    protected $obj = [];
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->wechatcfg = Configvalue::get('wechat');
+        $this->obj = $this->wechatcfg->content;
+    }
+
+    /**
+     * 查看
+     */
+    public function index()
+    {
+        if ($this->request->isAjax())
+        {
+            $configlist = isset($this->obj['config']) ? $this->obj['config'] : [];
+            $list = array();
+            foreach ($configlist as $row)
+            {
+                $list[] = $row;
+            }
+            $total = count($list);
+            $result = array("total" => $total, "rows" => $list);
+
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        if ($this->request->isPost())
+        {
+            $this->obj['config'][] = $this->request->post('row/a');
+            $this->wechatcfg->content = $this->obj;
+            $this->wechatcfg->save();
+            $this->code = 1;
+            return;
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit($ids = NULL)
+    {
+        $row = [];
+        foreach ($this->obj['config'] as $k => $v)
+        {
+            if ($v['id'] == $ids)
+            {
+                $row = $v;
+                break;
+            }
+        }
+        if (!$row)
+            $this->error(__('No Results were found'));
+        if ($this->request->isPost())
+        {
+            $params = $this->request->post('row/a');
+            $this->obj['config'][$k] = $params;
+            $this->obj['config'] = array_values($this->obj['config']);
+            $this->wechatcfg->content = $this->obj;
+            $this->wechatcfg->save();
+            $this->code = 1;
+            return;
+        }
+        $this->view->assign("row", $row);
+        return $this->view->fetch();
+    }
+
+    /**
+     * 删除
+     */
+    public function del($ids = "")
+    {
+        $this->code = -1;
+        if ($ids)
+        {
+            $ids = is_array($ids) ? $ids : explode(',', $ids);
+            foreach ($this->obj['config'] as $k => $v)
+            {
+                if (in_array($v['id'], $ids))
+                {
+                    unset($this->obj['config'][$k]);
+                }
+            }
+            $this->wechatcfg->content = $this->obj;
+            $this->wechatcfg->save();
+            $this->code = 1;
+        }
+
+        return;
+    }
+
+    /**
+     * 批量更新
+     */
+    public function multi($ids = "")
+    {
+        $this->code = -1;
+        //不支持指操作
+        return;
+    }
+
+}

+ 85 - 0
application/admin/controller/wechat/Menu.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace app\admin\controller\wechat;
+
+use app\common\controller\Backend;
+use app\common\model\Configvalue;
+use app\common\model\WechatResponse;
+use EasyWeChat\Foundation\Application;
+use think\Exception;
+
+/**
+ * 菜单管理
+ *
+ * @icon fa fa-list-alt
+ */
+class Menu extends Backend
+{
+
+    protected $wechatcfg = NULL;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->wechatcfg = Configvalue::get('wechat');
+    }
+
+    /**
+     * 查看
+     */
+    public function index()
+    {
+        $responselist = array();
+        $all = WechatResponse::all();
+        foreach ($all as $k => $v)
+        {
+            $responselist[$v['eventkey']] = $v['title'];
+        }
+        $this->view->assign('responselist', $responselist);
+        $this->view->assign('menu', $this->wechatcfg->content['menu']);
+        return $this->view->fetch();
+    }
+
+    /**
+     * 修改
+     */
+    public function edit($ids = NULL)
+    {
+        $menu = $this->request->post("menu");
+        $menu = (array) json_decode($menu, TRUE);
+        $content = $this->wechatcfg->content;
+        $content['menu'] = $menu;
+        $this->wechatcfg->content = $content;
+        $this->wechatcfg->save();
+        $this->code = 1;
+        return;
+    }
+
+    /**
+     * 同步
+     */
+    public function sync($ids = NULL)
+    {
+        $this->code = -1;
+        $app = new Application(Config::get('wechat')->toArray());
+
+        try
+        {
+            $ret = $app->menu->add($this->wechatcfg->content['menu']);
+            if ($ret->errcode == 0)
+            {
+                $this->code = 1;
+            }
+            else
+            {
+                $this->content = $ret->errmsg;
+            }
+        }
+        catch (Exception $e)
+        {
+            $this->content = $e->getMessage();
+        }
+        return;
+    }
+
+}

+ 85 - 0
application/admin/controller/wechat/Response.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace app\admin\controller\wechat;
+
+use app\common\controller\Backend;
+use fast\service\Wechat;
+
+/**
+ * 资源管理
+ *
+ * @icon fa fa-list-alt
+ */
+class Response extends Backend
+{
+
+    protected $model = null;
+
+    public function _initialize()
+    {
+        parent::_initialize();
+        $this->model = model('WechatResponse');
+    }
+
+    /**
+     * 选择素材
+     */
+    public function select()
+    {
+        return $this->view->fetch();
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            $params['eventkey'] = $params['eventkey'] ? $params['eventkey'] : uniqid();
+            $params['content'] = json_encode($params['content']);
+            $params['createtime'] = time();
+            if ($params)
+            {
+                $this->model->save($params);
+                $this->code = 1;
+                $this->content = $params;
+            }
+
+            return;
+        }
+        $appConfig = Wechat::appConfig();
+        $this->view->applist = $appConfig;
+        return $this->view->fetch();
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit($ids = NULL)
+    {
+        $row = $this->model->get($ids);
+        if (!$row)
+            $this->error(__('No Results were found'));
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            $params['eventkey'] = $params['eventkey'] ? $params['eventkey'] : uniqid();
+            $params['content'] = json_encode($params['content']);
+            if ($params)
+            {
+                $row->save($params);
+                $this->code = 1;
+            }
+            return;
+        }
+        $this->view->assign("row", $row);
+        $appConfig = Wechat::appConfig();
+        $this->view->applist = $appConfig;
+        return $this->view->fetch();
+    }
+
+}

+ 111 - 0
application/admin/lang/zh-cn.php

@@ -0,0 +1,111 @@
+<?php
+
+return [
+    'Keep login'                                            => '保持会话',
+    'Sign in'                                               => '登入',
+    'Username'                                              => '用户名',
+    'User id'                                               => '会员ID',
+    'Username'                                              => '用户名',
+    'Nickname'                                              => '昵称',
+    'Password'                                              => '密码',
+    'Sign up'                                               => '注 册',
+    'Sign in'                                               => '登 录',
+    'Sign out'                                              => '注 销',
+    'Keep login'                                            => '保持会话',
+    'Guest'                                                 => '游客',
+    'Welcome'                                               => '%s,你好!',
+    'Add'                                                   => '添加',
+    'Edit'                                                  => '编辑',
+    'Delete'                                                => '删除',
+    'Move'                                                  => '移动',
+    'Name'                                                  => '名称',
+    'Status'                                                => '状态',
+    'Weigh'                                                 => '权重',
+    'Operate'                                               => '操作',
+    'Warning'                                               => '温馨提示',
+    'Default'                                               => '默认',
+    'Article'                                               => '文章',
+    'Page'                                                  => '单页',
+    'OK'                                                    => '确定',
+    'Cancel'                                                => '取消',
+    'Loading'                                               => '加载中',
+    'More'                                                  => '更多',
+    'Normal'                                                => '正常',
+    'Hidden'                                                => '隐藏',
+    'Submit'                                                => '提交',
+    'Reset'                                                 => '重置',
+    'Execute'                                               => '执行',
+    'Close'                                                 => '关闭',
+    'Search'                                                => '搜索',
+    'Refresh'                                               => '刷新',
+    'First'                                                 => '首页',
+    'Previous'                                              => '上一页',
+    'Next'                                                  => '下一页',
+    'Last'                                                  => '末页',
+    'None'                                                  => '无',
+    'Home'                                                  => '主页',
+    'Online'                                                => '在线',
+    'Logout'                                                => '注销',
+    'Profile'                                               => '个人资料',
+    'Index'                                                 => '首页',
+    'Hot'                                                   => '热门',
+    'Recommend'                                             => '推荐',
+    'Dashboard'                                             => '控制台',
+    'Code'                                                  => '编号',
+    'Message'                                               => '内容',
+    'Line'                                                  => '行号',
+    'File'                                                  => '文件',
+    'Menu'                                                  => '菜单',
+    'Name'                                                  => '名称',
+    'Weigh'                                                 => '权重',
+    'Type'                                                  => '类型',
+    'Title'                                                 => '标题',
+    'Content'                                               => '内容',
+    'Status'                                                => '状态',
+    'Operate'                                               => '操作',
+    'Append'                                                => '追加',
+    'Memo'                                                  => '备注',
+    'Parent'                                                => '父级',
+    'Params'                                                => '参数',
+    'Permission'                                            => '权限',
+    'Advance search'                                        => '高级搜索',
+    'Check all'                                             => '选中全部',
+    'Expand all'                                            => '展开全部',
+    'Begin time'                                            => '开始时间',
+    'End time'                                              => '结束时间',
+    'Create time'                                           => '创建时间',
+    'Flag'                                                  => '标志',
+    'Redirect now'                                          => '立即跳转',
+    'Operation completed'                                   => '操作成功!',
+    'Operation failed'                                      => '操作失败!',
+    'Unknown data format'                                   => '未知的数据格式!',
+    'Network error'                                         => '网络错误!',
+    'Issues & Wiki'                                         => '问题交流',
+    'Advanced search'                                       => '高级搜索',
+    '%d second%s ago'                                       => '%d秒前',
+    '%d minute%s ago'                                       => '%d分钟前',
+    '%d hour%s ago'                                         => '%d小时前',
+    '%d day%s ago'                                          => '%d天前',
+    '%d week%s ago'                                         => '%d周前',
+    '%d month%s ago'                                        => '%d月前',
+    '%d year%s ago'                                         => '%d年前',
+    //
+    'Invalid parameters'                                    => '未知参数',
+    'No results were found'                                 => '记录未找到',
+    'Parameter %s can not be empty'                         => '参数%s不能为空',
+    'Are you sure you want to delete the %s selected item?' => '确定删除选中的 %s 项?',
+    'Are you sure you want to delete this item?'            => '确定删除此项?',
+    'Are you sure you want to delete or turncate?'          => '确定删除或清空?',
+    'You have no permission'                                => '你没有权限访问',
+    'Please enter your username'                            => '请输入你的用户名',
+    'Please enter your password'                            => '请输入你的密码',
+    'Please login first'                                    => '请登录后操作',
+    'You\'ve logged in, do not login again'                 => '你已经登录,无需重复登录',
+    'Username or password can not be empty'                 => '用户名密码不能为空',
+    'Username or password is incorrect'                     => '用户名或密码不正确',
+    'Username is incorrect'                                 => '用户名不正确',
+    'Password is incorrect'                                 => '密码不正确',
+    'Verification code is incorrect'                        => '验证码不正确',
+    'An unexpected error occurred'                          => '发生了一个意外错误,程序猿正在紧急处理中',
+    'This page will be re-directed in %s seconds'           => '页面将在 %s 秒后自动跳转',
+];

+ 14 - 0
application/admin/lang/zh-cn/general/attachment.php

@@ -0,0 +1,14 @@
+<?php
+
+return [
+    'Url'         => '物理路径',
+    'Imagewidth'  => '宽度',
+    'Imageheight' => '宽度',
+    'Imagetype'   => '图片类型',
+    'Imageframes' => '图片帧数',
+    'Filesize'    => '文件大小',
+    'Mimetype'    => 'mime类型',
+    'Extparam'    => '透传数据',
+    'Createtime'  => '创建日期',
+    'Uploadtime'  => '上传时间'
+];

+ 30 - 0
application/admin/lang/zh-cn/general/database.php

@@ -0,0 +1,30 @@
+<?php
+
+return [
+    'SQL Result'                                                             => '查询结果',
+    'Basic query'                                                            => '基础查询',
+    'View structure'                                                         => '基础查询',
+    'View data'                                                              => '基础查询',
+    'Optimize'                                                               => '优化表',
+    'Repair'                                                                 => '修复表',
+    'Optimize all'                                                           => '优化全部表',
+    'Repair all'                                                             => '修复全部表',
+    'Table:%s'                                                               => '总计:%s个表',
+    'Record:%s'                                                              => '记录:%s条',
+    'Data:%s'                                                                => '占用:%s',
+    'Index:%s'                                                               => '索引:%s',
+    'SQL Result:'                                                            => '查询结果:',
+    'SQL can not be empty'                                                   => 'SQL语句不能为空',
+    'Max output:%s'                                                          => '最大返回%s条',
+    'Total:%s'                                                               => '共有%s条记录! ',
+    'Row:%s'                                                                 => '记录:%s',
+    'Executes one or multiple queries which are concatenated by a semicolon' => '请输入SQL语句,支持批量查询,多条SQL以分号(,)分格',
+    'Query affected %s rows and took %s seconds'                             => '共影响%s条记录! 耗时:%s秒!',
+    'Query returned an empty result'                                         => '返回结果为空!',
+    'Query took %s seconds'                                                  => '耗时%s秒!',
+    'Optimize table %s done'                                                 => '优化表[%s]成功',
+    'Repair table %s done'                                                   => '修复表[%s]成功',
+    'Optimize table %s fail'                                                 => '优化表[%s]失败',
+    'Repair table %s fail'                                                   => '修复表[%s]失败'
+];
+

+ 23 - 0
application/admin/lang/zh-cn/index.php

@@ -0,0 +1,23 @@
+<?php
+
+return [
+    'Title'                                                      => '标题',
+    'Layout Options'                                             => '布局设定',
+    'Fixed Layout'                                               => '固定布局',
+    'You can\'t use fixed and boxed layouts together'            => '盒子模型和固定布局不能同时启作用',
+    'Boxed Layout'                                               => '盒子布局',
+    'Activate the boxed layout'                                  => '盒子布局最大宽度将被限定为1250px',
+    'Toggle Sidebar'                                             => '切换菜单栏',
+    'Toggle the left sidebar\'s state (open or collapse)'        => '切换菜单栏的展示或收起',
+    'Sidebar Expand on Hover'                                    => '菜单栏自动展开',
+    'Let the sidebar mini expand on hover'                       => '鼠标移到菜单栏自动展开',
+    'Toggle Right Sidebar Slide'                                 => '切换右侧操作栏',
+    'Toggle between slide over content and push content effects' => '切换右侧操作栏覆盖或独占',
+    'Toggle Right Sidebar Skin'                                  => '切换右侧操作栏背景',
+    'Toggle between dark and light skins for the right sidebar'  => '将右侧操作栏背景亮色或深色切换',
+    'Show sub menu'                                              => '显示菜单栏子菜单',
+    'Always show sub menu'                                       => '菜单栏子菜单将始终显示',
+    'Disable top menu badge'                                     => '禁用顶部彩色小角标',
+    'Disable top menu badge without left menu'                   => '左边菜单栏的彩色小角标不受影响',
+    'Skins'                                                      => '皮肤',
+];

+ 16 - 0
application/admin/lang/zh-cn/page.php

@@ -0,0 +1,16 @@
+<?php
+
+return [
+    'id'  =>  'ID',
+    'category_id'  =>  '分类ID',
+    'title'  =>  '标题',
+    'keywords'  =>  '关键字',
+    'flag'  =>  '标志',
+    'image'  =>  '头像',
+    'content'  =>  '内容',
+    'icon'  =>  '图标',
+    'views'  =>  '点击',
+    'comments'  =>  '评论',
+    'weigh'  =>  '权重',
+    'status'  =>  '状态'
+];

+ 205 - 0
application/admin/library/Auth.php

@@ -0,0 +1,205 @@
+<?php
+
+namespace app\admin\library;
+
+use app\admin\model\Admin;
+use fast\Random;
+use think\Cookie;
+use think\Request;
+use think\Session;
+
+class Auth extends \fast\Auth
+{
+
+    protected $requestUri = '';
+
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    public function __get($name)
+    {
+        return Session::get('admin.' . $name);
+    }
+
+    public function login($username, $password, $keeptime = 0)
+    {
+        $admin = Admin::get(['username' => $username]);
+        if (!$admin)
+        {
+            return false;
+        }
+        if ($admin->password != md5(md5($password) . $admin->salt))
+        {
+            $admin->loginfailure++;
+            $admin->save();
+            return false;
+        }
+        $admin->loginfailure = 0;
+        $admin->logintime = time();
+        $admin->token = Random::uuid();
+        $admin->save();
+        Session::set("admin", $admin);
+        $this->keeplogin($keeptime);
+        return true;
+    }
+
+    /**
+     * 注销登录
+     */
+    public function logout()
+    {
+        $admin = Admin::get(intval($this->id));
+        if (!$admin)
+        {
+            return true;
+        }
+        $admin->token = '';
+        $admin->save();
+        Session::delete("admin");
+        Cookie::delete("keeplogin");
+        return true;
+    }
+
+    /**
+     * 自动登录
+     * @return boolean
+     */
+    public function autologin()
+    {
+        $keeplogin = Cookie::get('keeplogin');
+        if (!$keeplogin)
+        {
+            return false;
+        }
+        list($id, $keeptime, $expiretime, $key) = explode('|', $keeplogin);
+        if ($id && $keeptime && $expiretime && $key && $expiretime > time())
+        {
+            $admin = Admin::get($id);
+            if (!$admin)
+            {
+                return false;
+            }
+            //token有变更
+            if ($key != md5(md5($id) . md5($keeptime) . md5($expiretime) . $admin->token))
+            {
+                return false;
+            }
+            Session::set("admin", $admin);
+            //刷新自动登录的时效
+            $this->keeplogin($keeptime);
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    /**
+     * 刷新保持登录的Cookie
+     * @param int $keeptime
+     * @return boolean
+     */
+    protected function keeplogin($keeptime = 0)
+    {
+        if ($keeptime)
+        {
+            $expiretime = time() + $keeptime;
+            $key = md5(md5($this->id) . md5($keeptime) . md5($expiretime) . $this->token);
+            $data = [$this->id, $keeptime, $expiretime, $key];
+            Cookie::set('keeplogin', implode('|', $data));
+            return true;
+        }
+        return false;
+    }
+
+    public function check($name, $uid = '', $relation = 'or', $mode = 'url')
+    {
+        return parent::check($name, $this->id, $relation, $mode);
+    }
+
+    /**
+     * 检测当前控制器和方法是否匹配传递的数组
+     *
+     * @param array $arr 需要验证权限的数组
+     */
+    public function match($arr = [])
+    {
+        $request = Request::instance();
+        $arr = is_array($arr) ? $arr : explode(',', $arr);
+        if (!$arr)
+        {
+            return FALSE;
+        }
+
+        // 是否存在
+        if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr))
+        {
+            return TRUE;
+        }
+
+        // 没找到匹配
+        return FALSE;
+    }
+
+    /**
+     * 检测是否登录
+     *
+     * @return boolean
+     */
+    public function isLogin()
+    {
+        return Session::get('admin') ? true : false;
+    }
+
+    /**
+     * 获取当前请求的URI
+     * @return string
+     */
+    public function getRequestUri()
+    {
+        return $this->requestUri;
+    }
+
+    /**
+     * 设置当前请求的URI
+     * @param string $uri
+     */
+    public function setRequestUri($uri)
+    {
+        $this->requestUri = $uri;
+    }
+
+    public function getGroups($uid = null)
+    {
+        $uid = is_null($uid) ? $this->id : $uid;
+        return parent::getGroups($uid);
+    }
+
+    public function getRuleList($uid = null)
+    {
+        $uid = is_null($uid) ? $this->id : $uid;
+        return parent::getRuleList($uid);
+    }
+
+    public function getUserInfo($uid = null)
+    {
+        $uid = is_null($uid) ? $this->id : $uid;
+
+        return $uid != $this->id ? Admin::get(intval($uid)) : Session::get('admin');
+    }
+
+    public function getRuleIds($uid = null)
+    {
+        $uid = is_null($uid) ? $this->id : $uid;
+        return parent::getRuleIds($uid);
+    }
+
+    public function isSuperAdmin()
+    {
+        return in_array('*', $this->getRuleIds()) ? TRUE : FALSE;
+    }
+
+}

+ 126 - 0
application/admin/library/traits/Backend.php

@@ -0,0 +1,126 @@
+<?php
+
+namespace app\admin\library\traits;
+
+trait Backend
+{
+
+    /**
+     * 查看
+     */
+    public function index()
+    {
+        if ($this->request->isAjax())
+        {
+            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
+            $total = $this->model
+                    ->where($where)
+                    ->order($sort, $order)
+                    ->count();
+
+            $list = $this->model
+                    ->where($where)
+                    ->order($sort, $order)
+                    ->limit($offset, $limit)
+                    ->select();
+            $result = array("total" => $total, "rows" => $list);
+
+            return json($result);
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 添加
+     */
+    public function add()
+    {
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                $this->model->create($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        return $this->view->fetch();
+    }
+
+    /**
+     * 编辑
+     */
+    public function edit($ids = NULL)
+    {
+        $row = $this->model->get(['id' => $ids]);
+        if (!$row)
+            $this->error(__('No Results were found'));
+        if ($this->request->isPost())
+        {
+            $this->code = -1;
+            $params = $this->request->post("row/a");
+            if ($params)
+            {
+                $row->save($params);
+                $this->code = 1;
+            }
+
+            return;
+        }
+        $this->view->assign("row", $row);
+        return $this->view->fetch();
+    }
+
+    /**
+     * 删除
+     */
+    public function del($ids = "")
+    {
+        $this->code = -1;
+        if ($ids)
+        {
+            $count = $this->model->where('id', 'in', $ids)->delete();
+            if ($count)
+            {
+                $this->code = 1;
+            }
+        }
+
+        return;
+    }
+
+    /**
+     * 批量更新
+     */
+    public function multi($ids = "")
+    {
+        $this->code = -1;
+        $ids = $ids ? $ids : $this->request->param("ids");
+        if ($ids)
+        {
+            if ($this->request->has('params'))
+            {
+                parse_str($this->request->post("params"), $values);
+                $values = array_intersect_key($values, array_flip(array('status')));
+                if ($values)
+                {
+                    $count = $this->model->where('id', 'in', $ids)->update($values);
+                    if ($count)
+                    {
+                        $this->code = 1;
+                    }
+                }
+            }
+            else
+            {
+                $this->code = 1;
+            }
+        }
+
+        return;
+    }
+
+}

+ 34 - 0
application/admin/model/Admin.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace app\admin\model;
+
+use think\Model;
+use think\Session;
+
+class Admin extends Model
+{
+
+    // 开启自动写入时间戳字段
+    protected $autoWriteTimestamp = 'int';
+    // 定义时间戳字段名
+    protected $createTime = 'createtime';
+    protected $updateTime = 'updatetime';
+
+    /**
+     * 重置用户密码
+     * @author baiyouwen
+     */
+    public function resetPassword($uid, $NewPassword)
+    {
+        $passwd = $this->encryptPassword($NewPassword);
+        $ret = $this->where(['id' => $uid])->update(['password' => $passwd]);
+        return $ret;
+    }
+
+    // 密码加密
+    protected function encryptPassword($password, $salt = '', $encrypt = 'md5')
+    {
+        return $encrypt($password . $salt);
+    }
+
+}

+ 30 - 0
application/admin/model/AdminLog.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace app\admin\model;
+
+use think\Model;
+
+class AdminLog extends Model
+{
+
+    // 开启自动写入时间戳字段
+    protected $autoWriteTimestamp = 'int';
+    // 定义时间戳字段名
+    protected $createTime = 'createtime';
+    protected $updateTime = '';
+
+    public static function record($title, $content = '', $username = '')
+    {
+        $admin = \think\Session::get('admin');
+        $admin_id = $admin ? $admin->id : 0;
+        $username = $username ? $username : ($admin ? $admin->username : __(''));
+        self::create([
+            'title'    => $title,
+            'content'  => $content,
+            'url'      => request()->url(),
+            'admin_id' => $admin_id,
+            'username' => $username
+        ]);
+    }
+
+}

+ 16 - 0
application/admin/model/AuthGroup.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace app\admin\model;
+
+use think\Model;
+
+class AuthGroup extends Model
+{
+
+    // 开启自动写入时间戳字段
+    protected $autoWriteTimestamp = 'int';
+    // 定义时间戳字段名
+    protected $createTime = 'createtime';
+    protected $updateTime = 'updatetime';
+
+}

+ 10 - 0
application/admin/model/AuthGroupAccess.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace app\admin\model;
+
+use think\Model;
+
+class AuthGroupAccess extends Model
+{
+    //
+}

+ 16 - 0
application/admin/model/AuthRule.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace app\admin\model;
+
+use think\Model;
+
+class AuthRule extends Model
+{
+
+    // 开启自动写入时间戳字段
+    protected $autoWriteTimestamp = 'int';
+    // 定义时间戳字段名
+    protected $createTime = 'createtime';
+    protected $updateTime = 'updatetime';
+
+}

+ 16 - 0
application/admin/model/Page.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace app\admin\model;
+
+use think\Model;
+
+class Page extends Model
+{
+
+    // 自动写入时间戳字段
+    protected $autoWriteTimestamp = false;
+
+    // 定义时间戳字段名
+    protected $createTime = false;
+    protected $updateTime = false;
+}

+ 45 - 0
application/admin/view/auth/admin/add.html

@@ -0,0 +1,45 @@
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="role_id" class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select('group[]', $groupdata, null, ['class'=>'form-control selectpicker', 'multiple'=>'', 'required'=>''])}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="username" class="control-label col-xs-12 col-sm-2">{:__('Username')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="username" name="row[username]" value="" pattern="[A-Za-z0-9_]{3,}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="email" class="control-label col-xs-12 col-sm-2">{:__('Email')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="email" class="form-control" id="email" name="row[email]" value="" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="nickname" name="row[nickname]" value="" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="password" class="control-label col-xs-12 col-sm-2">{:__('Password')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="password" class="form-control" id="password" name="row[password]" value="" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
+        </div>
+    </div>
+    <div class="form-group hidden layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 45 - 0
application/admin/view/auth/admin/edit.html

@@ -0,0 +1,45 @@
+<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="role_id" class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select('group[]', $groupdata, $groupids, ['class'=>'form-control selectpicker', 'multiple'=>''])}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="username" class="control-label col-xs-12 col-sm-2">{:__('Username')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="username" name="row[username]" value="{$row.username}" pattern="[A-Za-z0-9_]{3,}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="email" class="control-label col-xs-12 col-sm-2">{:__('Email')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="email" class="form-control" id="email" name="row[email]" value="{$row.email}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="nickname" name="row[nickname]" value="{$row.nickname}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="password" class="control-label col-xs-12 col-sm-2">{:__('Password')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="password" class="form-control" id="password" name="row[password]" value="" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
+        </div>
+    </div>
+    <div class="form-group hidden layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 21 - 0
application/admin/view/auth/admin/index.html

@@ -0,0 +1,21 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar()}
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover" width="100%">
+
+                    </table>
+
+
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 37 - 0
application/admin/view/auth/group/add.html

@@ -0,0 +1,37 @@
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" data-before-submit="refreshrules" action="">
+    <input type="hidden" name="row[rules]" value="" />
+    <div class="form-group">
+        <label for="pid" class="control-label col-xs-12 col-sm-2">{:__('Parent')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select('row[pid]', $groupdata, null, ['class'=>'form-control selectpicker', 'required'=>''])}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="username" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="name" name="row[name]" value="" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Permission')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <span class="text-muted"><input type="checkbox" name="" id="checkall" /> <label for="checkall"><small>{:__('Check all')}</small></label></span>
+            <span class="text-muted"><input type="checkbox" name="" id="expandall" /> <label for="expandall"><small>{:__('Expand all')}</small></label></span>
+
+            <div id="treeview"></div>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
+        </div>
+    </div>
+    <div class="form-group hidden layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 37 - 0
application/admin/view/auth/group/edit.html

@@ -0,0 +1,37 @@
+<form id="edit-form" class="form-horizontal form-ajax" role="form" method="POST" data-before-submit="refreshrules" action="">
+    <input type="hidden" name="row[rules]" value="" />
+    <div class="form-group">
+        <label for="pid" class="control-label col-xs-12 col-sm-2">{:__('Parent')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select('row[pid]', $groupdata, $row['pid'], ['class'=>'form-control selectpicker', 'required'=>'', 'data-id'=>$row['id'], 'data-pid'=>$row['pid']])}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="username" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="name" name="row[name]" value="{$row.name}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Permission')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <span class="text-muted"><input type="checkbox" name="" id="checkall" /> <label for="checkall"><small>{:__('Check all')}</small></label></span>
+            <span class="text-muted"><input type="checkbox" name="" id="expandall" /> <label for="expandall"><small>{:__('Expand all')}</small></label></span>
+
+            <div id="treeview"></div>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
+        </div>
+    </div>
+    <div class="form-group hidden layer-footer">
+        <label class="control-label col-xs-12 col-sm-2 col-xs-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 19 - 0
application/admin/view/auth/group/index.html

@@ -0,0 +1,19 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar()}
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover" width="100%">
+
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 65 - 0
application/admin/view/auth/rule/add.html

@@ -0,0 +1,65 @@
+<div class="callout callout-info">
+    <h4>{:__('Alert')}!</h4>
+    {:__('If not necessary, use the rebuild node feature directly')}
+</div>
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="pid" class="control-label col-xs-12 col-sm-2">{:__('Parent')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select('row[pid]', $ruledata, null, ['class'=>'form-control selectpicker', 'required'=>''])}
+        </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-8">
+            <input type="text" class="form-control" id="name" name="row[name]" value="" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="module" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="title" name="row[title]" value="" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="icon" class="control-label col-xs-12 col-sm-2">{:__('Icon')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="input-group input-groupp-md">
+                <input type="text" class="form-control" id="icon" name="row[icon]" value="fa fa-dot" />
+                <a href="javascript:;" class="btn-search-icon input-group-addon">搜索图标</a>
+            </div>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="weigh" name="row[weigh]" value="0" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Condition')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea class="form-control" id="condition" name="row[condition]"></textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea class="form-control" id="remark" name="row[remark]"></textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
+        </div>
+    </div>
+    <div class="form-group hidden layer-footer">
+        <div class="col-xs-2"></div>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>
+{include file="auth/rule/tpl" /}

+ 61 - 0
application/admin/view/auth/rule/edit.html

@@ -0,0 +1,61 @@
+<form id="edit-form" class="form-horizontal form-ajax" role="form" method="POST" action="">
+    <div class="form-group">
+        <label for="pid" class="control-label col-xs-12 col-sm-2">{:__('Parent')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select('row[pid]', $ruledata, $row['pid'], ['class'=>'form-control selectpicker', 'required'=>''])}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="action" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="title" name="row[title]" value="{$row.title}" required="required" />
+        </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-8">
+            <input type="text" class="form-control" id="name" name="row[name]" value="{$row.name}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="icon" class="control-label col-xs-12 col-sm-2">{:__('Icon')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="input-group input-groupp-md">
+                <input type="text" class="form-control" id="icon" name="row[icon]" value="{$row.icon}" />
+                <a href="javascript:;" class="btn-search-icon input-group-addon">搜索图标</a>
+            </div>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="weigh" name="row[weigh]" value="{$row.weigh}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Condition')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea class="form-control" id="condition" name="row[condition]">{$row.condition}</textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea class="form-control" id="remark" name="row[remark]">{$row.remark}</textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
+        </div>
+    </div>
+    <div class="form-group hidden layer-footer">
+        <div class="col-xs-2"></div>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>
+{include file="auth/rule/tpl" /}

+ 21 - 0
application/admin/view/auth/rule/index.html

@@ -0,0 +1,21 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar()}
+                        <a href="javascript:;" class="btn btn-danger btn-toggle-all"><i class="fa fa-plus"></i> {:__('Toggle all')}</a>
+                        <a href="javascript:;" class="btn btn-danger btn-rebuild">{:__('Rebuild node')}</a>
+                    </div>
+                    <table id="table" class="table table-bordered table-hover" width="100%">
+
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 42 - 0
application/admin/view/auth/rule/tpl.html

@@ -0,0 +1,42 @@
+<style>
+    #chooseicon {
+        margin:10px;
+    }
+    #chooseicon ul {
+        margin:5px 0 0 0;
+    }
+    #chooseicon ul li{
+        width:30px;height:30px;
+        line-height:30px;
+        border:1px solid #ddd;
+        padding:1px;
+        margin:1px;
+        text-align: center;
+    }
+    #chooseicon ul li:hover{
+        border:1px solid #2c3e50;
+        cursor:pointer;
+    }
+</style>
+<script id="chooseicontpl" type="text/html">
+    <div id="chooseicon">
+        <div>
+            <form onsubmit="return false;">
+                <div class="input-group input-groupp-md">
+                    <div class="input-group-addon">搜索图标</div>
+                    <input class="js-icon-search form-control" type="text" placeholder="">
+                </div>
+            </form>
+        </div>
+        <div>
+            <ul class="list-inline">
+                <% for(var i=0; i<iconlist.length; i++){ %>
+                    <li data-font="<%=iconlist[i]%>" title="<%=iconlist[i]%>">
+                    <i class="fa fa-<%=iconlist[i]%>"></i>
+                </li>
+                <% } %>
+            </ul>
+        </div>
+
+    </div>
+</script>

File diff suppressed because it is too large
+ 191 - 0
application/admin/view/common/control.html


+ 107 - 0
application/admin/view/common/header.html

@@ -0,0 +1,107 @@
+<!-- Logo -->
+<a href="javascript:;" class="logo">
+    <!-- 迷你模式下Logo的大小为50X50 -->
+    <span class="logo-mini"><b>F</b>AST</span>
+    <!-- 普通模式下Logo -->
+    <span class="logo-lg"><b>Fast</b>Admin</span>
+</a>
+<!-- 顶部通栏样式 -->
+<nav class="navbar navbar-static-top">
+    <!-- 边栏切换按钮-->
+    <a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
+        <span class="sr-only">{:__('Toggle navigation')}</span>
+    </a>
+
+    <div id="nav" class="pull-left">
+        <!--如果不想在顶部显示角标,则给ul加上disable-top-badge类即可-->
+        <ul class="nav nav-tabs nav-addtabs disable-top-badge" role="tablist">
+        </ul>
+    </div>
+
+    <div class="navbar-custom-menu">
+        <ul class="nav navbar-nav">
+
+            <li>
+                <a href="{:url('index/index/index')}" target="_blank"><i class="fa fa-home" style="font-size:14px;"></i></a>
+            </li>
+
+            <!-- 通栏下拉框样式 -->
+            <li class="dropdown notifications-menu">
+                <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+                    <i class="fa fa-bell-o"></i>
+                    <span class="label label-warning">2</span>
+                </a>
+                <ul class="dropdown-menu">
+                    <li class="header">You have 10 notifications</li>
+                    <li>
+                        <!-- 下拉条目样式 -->
+                        <ul class="menu">
+                            <li>
+                                <a href="#">
+                                    <i class="fa fa-users text-aqua"></i> 5 new members joined today
+                                </a>
+                            </li>
+                            <li>
+                                <a href="#">
+                                    <i class="fa fa-warning text-yellow"></i> Very long description here that may not fit into the
+                                    page and may cause design problems
+                                </a>
+                            </li>
+                        </ul>
+                    </li>
+                    <li class="footer"><a href="#">View all</a></li>
+                </ul>
+            </li>
+
+            <li>
+                <a href="#" data-toggle="fullscreen"><i class="fa fa-arrows-alt"></i></a>
+            </li>
+
+            <!-- 账号信息下拉框 -->
+            <li class="dropdown user user-menu">
+                <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+                    <img src="{$admin.avatar}" class="user-image" alt="User Image">
+                    <span class="hidden-xs">{$admin.nickname}</span>
+                </a>
+                <ul class="dropdown-menu">
+                    <!-- User image -->
+                    <li class="user-header">
+                        <img src="{$admin.avatar}" class="img-circle" alt="">
+
+                        <p>
+                            {$admin.nickname}
+                            <small>{$admin.logintime|date="Y-m-d H:i:s",###}</small>
+                        </p>
+                    </li>
+                    <!-- Menu Body -->
+                    <li class="user-body">
+                        <div class="row">
+                            <div class="col-xs-4 text-center">
+                                <a href="#">Followers</a>
+                            </div>
+                            <div class="col-xs-4 text-center">
+                                <a href="#">Sales</a>
+                            </div>
+                            <div class="col-xs-4 text-center">
+                                <a href="#">Friends</a>
+                            </div>
+                        </div>
+                    </li>
+                    <!-- Menu Footer-->
+                    <li class="user-footer">
+                        <div class="pull-left">
+                            <a href="{:url('general.profile/index')}" class="btn btn-default btn-flat">{:__('Profile')}</a>
+                        </div>
+                        <div class="pull-right">
+                            <a href="{:url('index/logout')}" class="btn btn-default btn-flat">{:__('Logout')}</a>
+                        </div>
+                    </li>
+                </ul>
+            </li>
+            <!-- 控制栏切换按钮 -->
+            <li>
+                <a href="javascript:;" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a>
+            </li>
+        </ul>
+    </div>
+</nav>

+ 27 - 0
application/admin/view/common/menu.html

@@ -0,0 +1,27 @@
+<!-- sidebar: style can be found in sidebar.less -->
+<section class="sidebar">
+    <!-- Sidebar user panel -->
+    <div class="user-panel hidden-xs">
+        <div class="pull-left image">
+            <img src="{$admin.avatar}" class="img-circle" />
+        </div>
+        <div class="pull-left info">
+            <p>{$admin.nickname}</p>
+            <i class="fa fa-circle text-success"></i> {:__('Online')}
+        </div>
+    </div>
+    <!-- search form -->
+    <form action="#" method="get" class="sidebar-form hidden-xs" style="overflow:visible;border:none;">
+        <select class="form-control fastmenujump btn">
+            <option value="">{:__('Shortcut')}</option>
+        </select>
+    </form>
+    <!-- /.search form -->
+
+    <!-- sidebar menu: : style can be found in sidebar.less -->
+    <!--如果想始终显示子菜单,则给ul加上show-submenu类即可-->
+    <ul class="sidebar-menu">
+        {$menulist}
+    </ul>
+</section>
+<!-- /.sidebar -->

+ 22 - 0
application/admin/view/common/meta.html

@@ -0,0 +1,22 @@
+<meta charset="utf-8">
+<title>{$title|default=''}</title>
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+
+<link rel="shortcut icon" href="__CDN__/assets/img/favicon.ico" />
+<!-- Loading Bootstrap -->
+<link href="__CDN__/assets/build/backend.css?v={$Think.config.site.version}" rel="stylesheet">
+
+<link rel="shortcut icon" href="__CDN__/assets/img/favicon.ico">
+
+<!-- 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>
+  <script src="__CDN__/assets/js/respond.min.js"></script>
+<![endif]-->
+<script type="text/javascript">
+    var require = {
+        config: {
+            'config': {$config|json_encode}
+        }
+    };
+</script>

+ 1 - 0
application/admin/view/common/script.html

@@ -0,0 +1 @@
+<script src="__CDN__/assets/js/require.js" data-main="__CDN__/assets/js/require-backend.js?v={$site.version}"></script>

+ 432 - 0
application/admin/view/dashboard/index.html

@@ -0,0 +1,432 @@
+<style type="text/css">
+    .sm-st {
+        background:#fff;
+        padding:20px;
+        -webkit-border-radius:3px;
+        -moz-border-radius:3px;
+        border-radius:3px;
+        margin-bottom:20px;
+        -webkit-box-shadow: 0 1px 0px rgba(0,0,0,0.05);
+        box-shadow: 0 1px 0px rgba(0,0,0,0.05);
+    }
+    .sm-st-icon {
+        width:60px;
+        height:60px;
+        display:inline-block;
+        line-height:60px;
+        text-align:center;
+        font-size:30px;
+        background:#eee;
+        -webkit-border-radius:5px;
+        -moz-border-radius:5px;
+        border-radius:5px;
+        float:left;
+        margin-right:10px;
+        color:#fff;
+    }
+    .sm-st-info {
+        font-size:12px;
+        padding-top:2px;
+    }
+    .sm-st-info span {
+        display:block;
+        font-size:24px;
+        font-weight:600;
+    }
+    .orange {
+        background:#fa8564 !important;
+    }
+    .tar {
+        background:#45cf95 !important;
+    }
+    .sm-st .green {
+        background:#86ba41 !important;
+    }
+    .pink {
+        background:#AC75F0 !important;
+    }
+    .yellow-b {
+        background: #fdd752 !important;
+    }
+    .stat-elem {
+
+        background-color: #fff;
+        padding: 18px;
+        border-radius: 40px;
+
+    }
+
+    .stat-info {
+        text-align: center;
+        background-color:#fff;
+        border-radius: 5px;
+        margin-top: -5px;
+        padding: 8px;
+        -webkit-box-shadow: 0 1px 0px rgba(0,0,0,0.05);
+        box-shadow: 0 1px 0px rgba(0,0,0,0.05);
+        font-style: italic;
+    }
+
+    .stat-icon {
+        text-align: center;
+        margin-bottom: 5px;
+    }
+
+    .st-red {
+        background-color: #F05050;
+    }
+    .st-green {
+        background-color: #27C24C;
+    }
+    .st-violet {
+        background-color: #7266ba;
+    }
+    .st-blue {
+        background-color: #23b7e5;
+    }
+
+    .stats .stat-icon {
+        color: #28bb9c;
+        display: inline-block;
+        font-size: 26px;
+        text-align: center;
+        vertical-align: middle;
+        width: 50px;
+        float:left;
+    }
+
+    .stat {
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: inline-block;
+        margin-right: 10px; }
+    .stat .value {
+        font-size: 20px;
+        line-height: 24px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        font-weight: 500; }
+    .stat .name {
+        overflow: hidden;
+        text-overflow: ellipsis; }
+    .stat.lg .value {
+        font-size: 26px;
+        line-height: 28px; }
+    .stat.lg .name {
+        font-size: 16px; }
+    .stat-col .progress {height:2px;}
+    .stat-col .progress-bar {line-height:2px;height:2px;}
+
+    .item {
+        padding:30px 0;
+    }
+</style>
+<div class="panel panel-default panel-intro">
+    <div class="panel-heading">
+        <div class="panel-lead"><em>控制台(Dashboard)</em>用于展示当前系统中的统计数据、统计报表及重要实时数据</div>
+        <ul class="nav nav-tabs">
+            <li class="active"><a href="#one" data-toggle="tab">控制台</a></li>
+            <li><a href="#two" data-toggle="tab">微信统计</a></li>
+        </ul>
+    </div>
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+
+                <div class="row">
+                    <div class="col-sm-3 col-xs-6">
+                        <div class="sm-st clearfix">
+                            <span class="sm-st-icon st-red"><i class="fa fa-users"></i></span>
+                            <div class="sm-st-info">
+                                <span>{$totaluser}</span>
+                                总会员数
+                            </div>
+                        </div>
+                    </div>
+                    <div class="col-sm-3 col-xs-6">
+                        <div class="sm-st clearfix">
+                            <span class="sm-st-icon st-violet"><i class="fa fa-book"></i></span>
+                            <div class="sm-st-info">
+                                <span>{$totalviews}</span>
+                                总访问数
+                            </div>
+                        </div>
+                    </div>
+                    <div class="col-sm-3 col-xs-6">
+                        <div class="sm-st clearfix">
+                            <span class="sm-st-icon st-blue"><i class="fa fa-shopping-bag"></i></span>
+                            <div class="sm-st-info">
+                                <span>{$totalorder}</span>
+                                总订单数
+                            </div>
+                        </div>
+                    </div>
+                    <div class="col-sm-3 col-xs-6">
+                        <div class="sm-st clearfix">
+                            <span class="sm-st-icon st-green"><i class="fa fa-cny"></i></span>
+                            <div class="sm-st-info">
+                                <span>{$totalorderamount}</span>
+                                总金额
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="row">
+                    <div class="col-lg-8">
+                        <div id="echart" style="height:200px;width:100%;"></div>
+                    </div>
+                    <div class="col-lg-4">
+                        <div class="card sameheight-item stats">
+                            <div class="card-block">
+                                <div class="row row-sm stats-container">
+                                    <div class="col-xs-6 stat-col">
+                                        <div class="stat-icon"> <i class="fa fa-rocket"></i> </div>
+                                        <div class="stat">
+                                            <div class="value"> {$todayusersignup} </div>
+                                            <div class="name"> 今日注册 </div>
+                                        </div>
+                                        <div class="progress">
+                                            <div class="progress-bar progress-bar-success" style="width: 20%"></div>
+                                        </div>
+                                    </div>
+                                    <div class="col-xs-6 stat-col">
+                                        <div class="stat-icon"> <i class="fa fa-shopping-cart"></i> </div>
+                                        <div class="stat">
+                                            <div class="value"> {$todayuserlogin} </div>
+                                            <div class="name"> 今日登录 </div>
+                                        </div>
+                                        <div class="progress">
+                                            <div class="progress-bar progress-bar-success" style="width: 20%"></div>
+                                        </div>
+                                    </div>
+                                    <div class="col-xs-6  stat-col">
+                                        <div class="stat-icon"> <i class="fa fa-line-chart"></i> </div>
+                                        <div class="stat">
+                                            <div class="value"> {$todayorder} </div>
+                                            <div class="name"> 今日订单 </div>
+                                        </div>
+                                        <div class="progress">
+                                            <div class="progress-bar progress-bar-success" style="width: 20%"></div>
+                                        </div>
+                                    </div>
+                                    <div class="col-xs-6  stat-col">
+                                        <div class="stat-icon"> <i class="fa fa-users"></i> </div>
+                                        <div class="stat">
+                                            <div class="value"> {$todayunsettleorder} </div>
+                                            <div class="name"> 未处理订单 </div>
+                                        </div>
+                                        <div class="progress">
+                                            <div class="progress-bar progress-bar-success" style="width: 20%"></div>
+                                        </div>
+                                    </div>
+                                    <div class="col-xs-6  stat-col">
+                                        <div class="stat-icon"> <i class="fa fa-list-alt"></i> </div>
+                                        <div class="stat">
+                                            <div class="value"> {$sevendnu} </div>
+                                            <div class="name"> 七日新增 </div>
+                                        </div>
+                                        <div class="progress">
+                                            <div class="progress-bar progress-bar-success" style="width: 20%"></div>
+                                        </div>
+                                    </div>
+                                    <div class="col-xs-6 stat-col">
+                                        <div class="stat-icon"> <i class="fa fa-dollar"></i> </div>
+                                        <div class="stat">
+                                            <div class="value"> {$sevendau} </div>
+                                            <div class="name"> 七日活跃 </div>
+                                        </div>
+                                        <div class="progress">
+                                            <div class="progress-bar progress-bar-success" style="width: 20%"></div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="row hidden">
+                    <div class="col-lg-4">
+                        <div class="box">
+                            <div class="box-header"><h3 class="box-title">温馨设置</h3></div>
+                            <div class="box-body">test test</div>
+                        </div>
+                    </div>
+                    <div class="col-lg-4">
+                        <div class="box">
+                            <div class="box-header">cccc</div>
+                            <div class="box-body">test test</div>
+                        </div>
+                    </div>
+                    <div class="col-lg-4">
+                        <div class="box">
+                            <div class="box-header">cccc</div>
+                            <div class="box-body">test test</div>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="row" style="margin-top:15px;">
+
+                    <div class="col-lg-12">
+                        <h4>详细统计</h4>
+                    </div>
+                    <div class="col-xs-6 col-md-3">
+                        <div class="panel bg-blue">
+                            <div class="panel-body">
+                                <div class="panel-title">
+                                    <span class="label label-success pull-right">管理</span>
+                                    <h5>教练统计</h5>
+                                </div>
+                                <div class="panel-content">
+                                    <h1 class="no-margins">1234</h1>
+                                    <div class="stat-percent font-bold text-gray"><i class="fa fa-commenting"></i> 1234</div>
+                                    <small>总评论数</small>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="col-xs-6 col-md-3">
+                        <div class="panel bg-aqua-gradient">
+                            <div class="panel-body">
+                                <div class="ibox-title">
+                                    <span class="label label-info pull-right">管理</span>
+                                    <h5>文章统计</h5>
+                                </div>
+                                <div class="ibox-content">
+                                    <h1 class="no-margins">1234</h1>
+                                    <div class="stat-percent font-bold text-gray"><i class="fa fa-modx"></i> 1234</div>
+                                    <small>总文章数</small>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="col-xs-6 col-md-3">
+                        <div class="panel bg-purple-gradient">
+                            <div class="panel-body">
+                                <div class="ibox-title">
+                                    <span class="label label-primary pull-right">管理</span>
+                                    <h5>动态统计</h5>
+                                </div>
+                                <div class="ibox-content">
+
+                                    <div class="row">
+                                        <div class="col-md-6">
+                                            <h1 class="no-margins">1234</h1>
+                                            <div class="font-bold text-navy"><i class="fa fa-commenting"></i> <small>总评论数</small></div>
+                                        </div>
+                                        <div class="col-md-6">
+                                            <h1 class="no-margins">1234</h1>
+                                            <div class="font-bold text-navy"><i class="fa fa-heart"></i> <small>总动态评论点赞数</small></div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="col-xs-6 col-md-3">
+                        <div class="panel bg-green-gradient">
+                            <div class="panel-body">
+                                <div class="ibox-title">
+                                    <span class="label label-primary pull-right">管理</span>
+                                    <h5>活动统计</h5>
+                                </div>
+                                <div class="ibox-content">
+
+                                    <div class="row">
+                                        <div class="col-md-6">
+                                            <h1 class="no-margins">1234</h1>
+                                            <div class="font-bold text-navy"><i class="fa fa-commenting"></i> <small>总评论数</small></div>
+                                        </div>
+                                        <div class="col-md-6">
+                                            <h1 class="no-margins">1234</h1>
+                                            <div class="font-bold text-navy"><i class="fa fa-user"></i> <small>总参与人数</small></div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+            </div>
+            <div class="tab-pane fade" id="two">
+                <div class="row">
+                    <div class="col-xs-3">
+                        <div class="box box-danger">
+                            <div class="box-header with-border"><span class="label label-success pull-right">Monthly</span>
+                                <div class="box-title">
+                                    统计数据1
+                                </div>
+                            </div>
+                            <div class="box-body">
+                                <div class="ibox-content">
+                                    <h1 class="no-margin no-padding">40 886,200</h1>
+                                    <div class="stat-percent font-bold text-success">98% <i class="fa fa-bolt"></i></div>
+                                    <small>Total income</small>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="col-xs-3">
+                        <div class="box box-success bg-green-gradient">
+                            <div class="box-header"><span class="label label-success pull-right">Monthly</span>
+                                <div class="box-title">
+                                    统计数据2
+                                </div>
+                            </div>
+                            <div class="box-body">
+                                <div class="ibox-content">
+                                    <h1 class="no-margin no-padding">40 886,200</h1>
+                                    <div class="stat-percent font-bold text-success">98% <i class="fa fa-bolt"></i></div>
+                                    <small>Total income</small>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="col-xs-3">
+                        <div class="box box-warning">
+                            <div class="box-header with-border"><span class="label label-success pull-right">Monthly</span>
+                                <div class="box-title">
+                                    统计数据3
+                                </div>
+                            </div>
+                            <div class="box-body">
+                                <div class="ibox-content">
+                                    <h1 class="no-margin no-padding">40 886,200</h1>
+                                    <div class="stat-percent font-bold text-success">98% <i class="fa fa-bolt"></i></div>
+                                    <small>Total income</small>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="col-xs-3">
+                        <div class="box box-info bg-purple-gradient">
+                            <div class="box-header"><span class="label label-success pull-right">Monthly</span>
+                                <div class="box-title">
+                                    统计数据4
+                                </div>
+                            </div>
+                            <div class="box-body">
+                                <div class="ibox-content">
+                                    <h1 class="no-margin no-padding">40 886,200</h1>
+                                    <div class="stat-percent font-bold text-success">98% <i class="fa fa-bolt"></i></div>
+                                    <small>Total income</small>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    var Orderdata = {
+    column: {:json_encode(array_keys($paylist))},
+            paydata: {:json_encode(array_values($paylist))},
+            createdata: {:json_encode(array_values($createlist))},
+    };
+</script>

+ 29 - 0
application/admin/view/general/attachment/add.html

@@ -0,0 +1,29 @@
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="c-upyun" class="control-label col-xs-12 col-sm-2">{:__('Upload')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[upyun]" id="c-upyun" class="form-control" cols="60" data-plupload-id="plupload-upyun-text" />
+        </div>
+    </div>
+
+    <div class="form-group">
+        <label for="c-upyun" class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button id="plupload-upyun" class="btn btn-danger plupload" ><i class="fa fa-upload"></i> {:__("Upload to upyun")}</button>
+        </div>
+    </div>
+
+    <div class="form-group">
+        <label for="c-local" class="control-label col-xs-12 col-sm-2">{:__('Upload')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[local]" id="c-local" class="form-control" cols="60" data-plupload-id="plupload-local-text" />
+        </div>
+    </div>
+
+    <div class="form-group">
+        <label for="c-local" class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button id="plupload-local" class="btn btn-primary plupload" data-url="{:url('ajax/upload')}"><i class="fa fa-upload"></i> {:__("Upload to local")}</button>
+        </div>
+    </div>
+</form>

+ 64 - 0
application/admin/view/general/attachment/edit.html

@@ -0,0 +1,64 @@
+<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label for="c-url" class="control-label col-xs-12 col-sm-2">{:__('Url')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[url]" value="{$row.url}"  id="c-url" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-imagewidth" class="control-label col-xs-12 col-sm-2">{:__('Imagewidth')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[imagewidth]" value="{$row.imagewidth}"  id="c-imagewidth" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-imageheight" class="control-label col-xs-12 col-sm-2">{:__('Imageheight')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[imageheight]" value="{$row.imageheight}"  id="c-imageheight" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-imagetype" class="control-label col-xs-12 col-sm-2">{:__('Imagetype')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[imagetype]" value="{$row.imagetype}"  id="c-imagetype" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-imageframes" class="control-label col-xs-12 col-sm-2">{:__('Imageframes')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[imageframes]" value="{$row.imageframes}"  id="c-imageframes" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-filesize" class="control-label col-xs-12 col-sm-2">{:__('Filesize')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[filesize]" value="{$row.filesize}"  id="c-filesize" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-mimetype" class="control-label col-xs-12 col-sm-2">{:__('Mimetype')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[mimetype]" value="{$row.mimetype}"  id="c-mimetype" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-extparam" class="control-label col-xs-12 col-sm-2">{:__('Extparam')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[extparam]" value="{$row.extparam}"  id="c-extparam" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-uploadtime" class="control-label col-xs-12 col-sm-2">{:__('Uploadtime')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="datetime" name="row[uploadtime]" value="{$row.uploadtime|datetime}"  id="c-uploadtime" class="form-control datetimepicker" />
+        </div>
+    </div>
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 25 - 0
application/admin/view/general/attachment/index.html

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar()}
+                        <div class="dropdown btn-group">
+                            <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
+                            <ul class="dropdown-menu text-left" role="menu">
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> 设为正常</a></li>
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> 设为隐藏</a></li>
+                            </ul>
+                        </div>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover" width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 58 - 0
application/admin/view/general/configvalue/add.html

@@ -0,0 +1,58 @@
+<style type="text/css">
+    #fieldlist dd {display:block;margin:5px 0;}
+    #fieldlist dd input{display: inline-block;width:300px;}
+    #fieldlist dd input:first-child{width:110px;}
+    #fieldlist dd ins{width:110px;display: inline-block;text-decoration:none;font-weight: bold;}
+</style>
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="name" class="control-label col-xs-12 col-sm-2">ID:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="id" name="row[id]" value="" required="required" />
+        </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-8">
+            <input type="text" class="form-control" id="name" name="row[name]" value="" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <dl id="fieldlist" rel="1">
+                <dd>
+                    <ins>{:__('Key')}</ins>
+                    <ins>{:__('Value')}</ins>
+                </dd>
+                <dd>
+                    <input type="text" name="field[0]" class="form-control" id="field-0" value="" size="10" required />
+                    <input type="text" name="value[0]" class="form-control" id="value-0" value="" size="40" required />
+                    <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span>
+                    <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
+                </dd>
+                <dd><a href="javascript:;" class="append btn btn-sm btn-success"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
+            </dl>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="weigh" name="row[weigh]" value="0" required="required" size="6" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
+        </div>
+    </div>
+    <div class="form-group hidden layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+
+</form>

+ 59 - 0
application/admin/view/general/configvalue/edit.html

@@ -0,0 +1,59 @@
+<style type="text/css">
+    #fieldlist dd {display:block;margin:5px 0;}
+    #fieldlist dd input{display: inline-block;width:300px;}
+    #fieldlist dd input:first-child{width:110px;}
+    #fieldlist dd ins{width:110px;display: inline-block;text-decoration:none;font-weight: bold;}
+</style>
+<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="name" class="control-label col-xs-12 col-sm-2">ID:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="id" name="row[id]" value="{$row.id}" required="required" />
+        </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-8">
+            <input type="text" class="form-control" id="name" name="row[name]" value="{$row.name}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <dl id="fieldlist" rel="{$row.content|count}">
+                <dd>
+                    <ins>{:__('Key')}</ins>
+                    <ins>{:__('Value')}</ins>
+                </dd>
+                {foreach $row.content as $key => $vo}
+                <dd class="form-inline">
+                    <input type="text" name="field[{$key}]" class="form-control" id="field-{$key}" value="{$key}" size="10" />
+                    <input type="text" name="value[{$key}]" class="form-control" id="value-{$key}" value="{$vo}" size="40" />
+                    <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span>
+                    <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span>
+                </dd>
+                {/foreach}
+                <dd><a href="javascript:;" class="append btn btn-sm btn-success"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
+            </dl>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
+        <div class="col-xs-2">
+            <input type="text" class="form-control" id="weigh" name="row[weigh]" value="{$row.weigh}" required="required" size="6" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
+        </div>
+    </div>
+    <div class="form-group hidden layer-footer">
+        <div class="col-xs-2"></div>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 26 - 0
application/admin/view/general/configvalue/index.html

@@ -0,0 +1,26 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar()}
+                        <div class="dropdown btn-group">
+                            <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
+                            <ul class="dropdown-menu text-left" role="menu">
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> 设为正常</a></li>
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> 设为隐藏</a></li>
+                            </ul>
+                        </div>
+                        <a class="btn btn-primary btn-danger btn-clear-cache"><i class="fa fa-times"></i> {:__('Clear cache')}</a>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover" width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 76 - 0
application/admin/view/general/crontab/add.html

@@ -0,0 +1,76 @@
+<style type="text/css">
+    #schedulepicker {
+        padding-top:7px;
+    }
+</style>
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="name" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="title" name="row[title]" value="" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="name" class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select('row[type]', $typedata, null, ['class'=>'form-control'])}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea name="row[content]" id="conent" cols="30" rows="5" class="form-control"></textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="schedule" class="control-label col-xs-12 col-sm-2">{:__('Schedule')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div id="schedulepicker"></div>
+            <input type="text" class="form-control hide" id="schedule" name="row[schedule]" value="" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="sleep" class="control-label col-xs-12 col-sm-2">{:__('sleep')}:</label>
+        <div class="col-xs-12 col-sm-4">
+            <input type="number" class="form-control" id="sleep" name="row[sleep]" value="0" required="required" size="6" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="maximums" class="control-label col-xs-12 col-sm-2">{:__('Maximums')}:</label>
+        <div class="col-xs-12 col-sm-4">
+            <input type="number" class="form-control" id="maximums" name="row[maximums]" value="0" required="required" size="6" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="begintime" class="control-label col-xs-12 col-sm-2">{:__('Begin time')}:</label>
+        <div class="col-xs-12 col-sm-4">
+            <input type="text" class="form-control datetimepicker" id="begintime" name="row[begintime]" value="" required="required" size="6" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="endtime" class="control-label col-xs-12 col-sm-2">{:__('End time')}:</label>
+        <div class="col-xs-12 col-sm-4">
+            <input type="text" class="form-control datetimepicker" id="endtime" name="row[endtime]" value="" required="required" size="6" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
+        <div class="col-xs-12 col-sm-4">
+            <input type="text" class="form-control" id="weigh" name="row[weigh]" value="0" required="required" size="6" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
+        </div>
+    </div>
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+
+</form>

+ 70 - 0
application/admin/view/general/crontab/edit.html

@@ -0,0 +1,70 @@
+<style type="text/css">
+    #schedulepicker {
+        padding-top:7px;
+    }
+</style>
+<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="name" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="title" name="row[title]" value="{$row.title}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="name" class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select('row[type]', $typedata, $row['type'], ['class'=>'form-control'])}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea name="row[content]" id="conent" cols="30" rows="5" class="form-control">{$row.content}</textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="schedule" class="control-label col-xs-12 col-sm-2">{:__('Schedule')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div id="schedulepicker"></div>
+            <input type="text" class="form-control hide" id="schedule" name="row[schedule]" value="{$row.schedule}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="sleep" class="control-label col-xs-12 col-sm-2">{:__('sleep')}:</label>
+        <div class="col-xs-12 col-sm-4">
+            <input type="number" class="form-control" id="sleep" name="row[sleep]" value="{$row.sleep}" required="required" size="6" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="maximums" class="control-label col-xs-12 col-sm-2">{:__('Maximums')}:</label>
+        <div class="col-xs-12 col-sm-4">
+            <input type="number" class="form-control" id="maximums" name="row[maximums]" value="{$row.maximums}" required="required" size="6" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="endtime" class="control-label col-xs-12 col-sm-2">{:__('End time')}:</label>
+        <div class="col-xs-12 col-sm-4">
+            <input type="text" class="form-control datetimepicker" id="endtime" name="row[endtime]" value="{$row.endtime|datetime}" required="required" size="6" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
+        <div class="col-xs-12 col-sm-4">
+            <input type="text" class="form-control" id="weigh" name="row[weigh]" value="{$row.weigh}" required="required" size="6" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
+        </div>
+    </div>
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+
+</form>

+ 25 - 0
application/admin/view/general/crontab/index.html

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar()}
+                        <div class="dropdown btn-group">
+                            <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
+                            <ul class="dropdown-menu text-left" role="menu">
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> 设为正常</a></li>
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> 设为隐藏</a></li>
+                            </ul>
+                        </div>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover" width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 80 - 0
application/admin/view/general/database/index.html

@@ -0,0 +1,80 @@
+<style type="text/css">
+    #searchfloat {position:absolute;top:40px;right:20px;background:#F7F0A0;padding:10px;}
+    #saved {position: relative;}
+    #saved_sql {position:absolute;bottom:0;height:300px;background:#F7F0A0;width:100%;overflow:auto;display:none;}
+    #saved_sql li {display:block;clear:both;width:100%;float:left;line-height:18px;padding:1px 0}
+    #saved_sql li a{float:left;text-decoration: none;display:block;padding:0 5px;}
+    #saved_sql li i{display:none;float:left;color:#06f;font-size: 14px;font-style: normal;margin-left:2px;line-height:18px;}
+    #saved_sql li:hover{background:#fff;}
+    #saved_sql li:hover i{display:block;cursor:pointer;}
+    #database #tablename {height:205px;width:100%;padding:5px;}
+    #database #tablename option{height:18px;}
+    #database #subaction {height:210px;width:100%;}
+    #database .select-striped > option:nth-of-type(odd) {background-color: #f9f9f9;}
+    #database .dropdown-menu ul {margin:-3px 0;}
+    #database .dropdown-menu ul li{margin:3px 0;}
+    #database .dropdown-menu.row .col-xs-6{padding:0 5px;}
+    #sqlquery {font-size:12px;color:#444;}
+</style>
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="database" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+
+                    <div class="row">
+                        <div class="col-xs-4">
+                            <h4>{:__('SQL Result')}:</h4>
+                        </div>
+                        <div class="col-xs-8 text-right">
+                            <form action="{:url('general.database/query')}" method="post" name="infoform" target="resultframe">
+                                <input type="hidden" name="do_action" id="topaction" />
+
+                                <div class="btn-group">
+                                    <button data-toggle="dropdown" class="btn btn-primary btn-embossed dropdown-toggle" type="button">{:__('Basic query')} <span class="caret"></span></button>
+                                    <div class="row dropdown-menu pull-right" style="width:300px;">
+                                        <div class="col-xs-6">
+                                            <select class="form-control select-striped" id="tablename" name="tablename[]" multiple="multiple">
+                                                {foreach $tables as $table}
+                                                <option value="{$table.name}" title="">{$table.name}<!--({$table.rows})--></option>
+                                                {/foreach}
+                                            </select>
+                                        </div>
+                                        <div class="col-xs-6">
+                                            <ul id="subaction" class="list-unstyled">
+                                                <li><input type="submit" name="submit1" value="{:__('View structure')}" rel="viewinfo" class="btn btn-primary btn-embossed btn-sm btn-block"/></li>
+                                                <li><input type="submit" name="submit2" value="{:__('View data')}" rel="viewdata" class="btn btn-primary btn-embossed btn-sm btn-block"/></li>
+                                                <li><input type="submit" name="submit3" value="{:__('Optimize')}" rel="optimize" class="btn btn-primary btn-embossed btn-sm btn-block" /></li>
+                                                <li><input type="submit" name="submit4" value="{:__('Repair')}" rel="repair" class="btn btn-primary btn-embossed btn-sm btn-block"/></li>
+                                                <li><input type="submit" name="submit5" value="{:__('Optimize all')}" rel="optimizeall" class="btn btn-primary btn-embossed btn-sm btn-block" /></li>
+                                                <li><input type="submit" name="submit6" value="{:__('Repair all')}" rel="repairall" class="btn btn-primary btn-embossed btn-sm btn-block" /></li>
+                                            </ul>
+                                        </div>
+                                        <div class="clear"></div>
+                                    </div>
+
+                                </div>
+                            </form>
+                        </div>
+
+                    </div>
+                    <div class="well" style="padding:5px;">
+                        <iframe name="resultframe" frameborder="0" id="resultframe" style="height:100%;" width="100%" height="100%"></iframe>
+                    </div>
+                    <form action="{:url('general.database/query')}" method="post" id="sqlexecute" name="form1" target="resultframe">
+                        <input type="hidden" name="do_action" value="doquery" />
+                        <div class="form-group">
+                            <textarea name="sqlquery" placeholder="{:__('Executes one or multiple queries which are concatenated by a semicolon')}" cols="60" rows="5" class="form-control" id="sqlquery"></textarea>
+                        </div>
+
+                        <input type="submit" class="btn btn-success btn-embossed" value="{:__('Execute')}" />
+                        <input type="reset" class="btn btn-default btn-embossed" value="{:__('Reset')}" />
+                    </form>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 61 - 0
application/admin/view/general/profile/index.html

@@ -0,0 +1,61 @@
+<div class="row animated fadeInRight">
+    <div class="col-md-4">
+        <div class="box box-success">
+            <div class="panel-heading">
+                {:__('Profile')}
+            </div>
+            <div class="panel-body">
+                <form id="update-form" role="form" data-toggle="validator" method="POST" action="/general_profile/update">
+                    <div class="form-group">
+                        <label for="username" class="control-label">{:__('Username')}:</label>
+                        <input type="text" class="form-control" name="row[username]" value="{$admin.username}" disabled />
+                    </div>
+                    <div class="form-group">
+                        <label for="email" class="control-label">{:__('Email')}:</label>
+                        <input type="text" class="form-control" name="row[email]" value="{$admin.email}" />
+                    </div>
+                    <div class="form-group">
+                        <label for="nickname" class="control-label">{:__('Nickname')}:</label>
+                        <input type="text" class="form-control" name="row[nickname]" value="{$admin.nickname}" required="required" />
+                    </div>
+                    <div class="form-group">
+                        <label for="password" class="control-label">{:__('Password')}:</label>
+                        <input type="text" class="form-control" placeholder="{:__('Leave password blank if dont want to change')}" name="row[password]" value=""/>
+                    </div>
+                    <div class="form-group">
+                        <button type="submit" class="btn btn-success">{:__('Submit')}</button>
+                        <button type="reset" class="btn btn-default">{:__('Reset')}</button>
+                    </div>
+
+                </form>
+            </div>
+        </div>
+
+    </div>
+    <div class="col-md-8">
+        <div class="panel panel-default panel-intro panel-nav">
+            <div class="panel-heading">
+                <ul class="nav nav-tabs">
+                    <li class="active"><a href="#one" data-toggle="tab"><i class="fa fa-list"></i> {:__('Admin log')}</a></li>
+                </ul>
+            </div>
+            <div class="panel-body">
+                <div id="myTabContent" class="tab-content">
+                    <div class="tab-pane fade active in" id="one">
+                        <div class="widget-body no-padding">
+                            <div id="toolbar" class="toolbar">
+                                {:build_toolbar('refresh')}
+                            </div>
+                            <table id="table" class="table table-striped table-bordered table-hover" width="100%">
+
+                            </table>
+
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+
+    </div>
+</div>

+ 38 - 0
application/admin/view/index/index.html

@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        {include file="common/meta" /}
+    </head>
+    <body class="hold-transition skin-green sidebar-mini fixed" id="tabs">
+        <div class="wrapper">
+
+            <header id="header" class="main-header">
+                {include file='common/header' /}
+            </header>
+            <!-- Left side column. contains the logo and sidebar -->
+            <aside class="main-sidebar">
+                {include file='common/menu' /}
+            </aside>
+
+            <!-- Content Wrapper. Contains page content -->
+            <div class="content-wrapper tab-content tab-addtabs">
+
+            </div>
+            <!-- /.content-wrapper -->
+            <footer class="main-footer hide">
+                <div class="pull-right hidden-xs">
+                </div>
+                <strong>Copyright &copy; 2014-2016 <a href="http://fastadmin.net">Fastadmin</a>.</strong> All rights
+                reserved.
+            </footer>
+
+            <!-- Add the sidebar's background. This div must be placed
+                 immediately after the control sidebar -->
+            <div class="control-sidebar-bg"></div>
+            {include file="common/control" /}
+        </div>
+        <!-- ./wrapper -->
+        <!-- end main content -->
+        {include file="common/script" /}
+    </body>
+</html>

+ 91 - 0
application/admin/view/index/login.html

@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        {include file="common/meta" /}
+
+        <style type="text/css">
+            body {
+                color:#999;
+            }
+            .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 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;
+            }
+
+            #login-form {
+                margin-top:20px;
+            }
+            #login-form .input-group {
+                margin-bottom:15px;
+            }
+
+        </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="/assets/img/avatar.png" />
+                            <p id="profile-name" class="profile-name-card"></p>
+                            <form action="" method="post" id="login-form">
+                                {: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="" name="username" autocomplete="off" required="required" value="admin" />
+                                </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="" name="password" autocomplete="off" required="required" value="123456" />
+                                </div>
+
+                                <div class="form-group">
+                                    <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>
+                    <p class="copyright"><a href="http://www.fastadmin.net?ref=demo">Powered By FastAdmin</a></p>
+                </div>
+            </div>
+        </div>
+        {include file="common/script" /}
+    </body>
+</html>

+ 44 - 0
application/admin/view/layout/default.html

@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        {include file="common/meta" /}
+    </head>
+
+    <body class="inside-header inside-aside {$Think.const.IS_DIALOG ? 'is-dialog' : ''}">
+
+        <div id="main" role="main">
+            <div class="tab-content tab-addtabs">
+                <div id="content">
+                    <div class="row">
+                        <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
+                            <section class="content-header hide">
+                                <h1>
+                                    {:__('Dashboard')}
+                                    <small>{:__('Control panel')}</small>
+                                </h1>
+                            </section>
+                            {if !IS_DIALOG}
+                            <!-- RIBBON -->
+                            <div id="ribbon">
+                                <ol class="breadcrumb pull-left">
+                                    <li><a href="#"><i class="fa fa-dashboard"></i> {:__('Dashboard')}</a></li>
+                                    <li>{$title|default=''}</li>
+                                </ol>
+                                <div class="shortcut pull-right">
+                                    <a href="javascript:;" id="search" onclick="$('.search input').focus();"><i class="fa fa-search"></i> <span class="hidden-mobile">{:__('Search')}</span></a>
+                                    <a href="javascript:;" id="refresh" onclick="location.reload();"><i class="fa fa-refresh"></i> <span class="hidden-mobile">{:__('Refresh')}</span></a>
+                                </div>
+                            </div>
+                            <!-- END RIBBON -->
+                            {/if}
+                            <div class="content">
+                                {__CONTENT__}
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        {include file="common/script" /}
+    </body>
+</html>

+ 79 - 0
application/admin/view/page/add.html

@@ -0,0 +1,79 @@
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label for="c-category_id" class="control-label col-xs-12 col-sm-2">{:__('Category_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-category_id" class="form-control typeahead" name="row[category_id]" type="text" value="0">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-title" class="form-control" name="row[title]" type="text" value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-keywords" class="control-label col-xs-12 col-sm-2">{:__('Keywords')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-keywords" class="form-control" name="row[keywords]" type="text" value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-flag" class="control-label col-xs-12 col-sm-2">{:__('Flag')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select('row[flag]', 'h,i,s', null, ['id'=>'c-flag','class'=>'form-control selectpicker','required'=>''])}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="form-inline">
+                <input id="c-image" class="form-control" data-plupload-id="plupload-image-text" size="50" name="row[image]" type="text" value="">
+                <span><button id="plupload-image" class="btn btn-danger plupload" ><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
+            </div>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea id="c-content" class="form-control summernote" name="row[content]" cols="50" rows="10"></textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-icon" class="control-label col-xs-12 col-sm-2">{:__('Icon')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-icon" class="form-control" name="row[icon]" type="text" value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-views" class="control-label col-xs-12 col-sm-2">{:__('Views')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-views" class="form-control" name="row[views]" type="number" value="0">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-comments" class="control-label col-xs-12 col-sm-2">{:__('Comments')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-comments" class="form-control" name="row[comments]" type="number" value="0">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-weigh" class="form-control" name="row[weigh]" type="number" value="0">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-status" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
+        </div>
+    </div>
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 79 - 0
application/admin/view/page/edit.html

@@ -0,0 +1,79 @@
+<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label for="c-category_id" class="control-label col-xs-12 col-sm-2">{:__('Category_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-category_id" class="form-control typeahead" name="row[category_id]" type="text" value="{$row.category_id}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-title" class="form-control" name="row[title]" type="text" value="{$row.title}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-keywords" class="control-label col-xs-12 col-sm-2">{:__('Keywords')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-keywords" class="form-control" name="row[keywords]" type="text" value="{$row.keywords}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-flag" class="control-label col-xs-12 col-sm-2">{:__('Flag')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select('row[flag]', 'h,i,s', $row['flag'], ['id'=>'c-flag','class'=>'form-control selectpicker','required'=>''])}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="form-inline">
+                <input id="c-image" class="form-control" data-plupload-id="plupload-image-text" size="50" name="row[image]" type="text" value="{$row.image}">
+                <span><button id="plupload-image" class="btn btn-danger plupload" ><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
+            </div>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea id="c-content" class="form-control summernote" name="row[content]" cols="50" rows="10">{$row.content}</textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-icon" class="control-label col-xs-12 col-sm-2">{:__('Icon')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-icon" class="form-control" name="row[icon]" type="text" value="{$row.icon}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-views" class="control-label col-xs-12 col-sm-2">{:__('Views')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-views" class="form-control" name="row[views]" type="number" value="{$row.views}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-comments" class="control-label col-xs-12 col-sm-2">{:__('Comments')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-comments" class="form-control" name="row[comments]" type="number" value="{$row.comments}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-weigh" class="form-control" name="row[weigh]" type="number" value="{$row.weigh}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-status" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
+        </div>
+    </div>
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 25 - 0
application/admin/view/page/index.html

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar()}
+                        <div class="dropdown btn-group">
+                            <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
+                            <ul class="dropdown-menu text-left" role="menu">
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> 设为正常</a></li>
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> 设为隐藏</a></li>
+                            </ul>
+                        </div>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover" width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 64 - 0
application/admin/view/user/third/add.phtml

@@ -0,0 +1,64 @@
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="c-user_id" class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[user_id]" value="0"  id="c-user_id" class="form-control   typeahead " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-platform" class="control-label col-xs-12 col-sm-2">{:__('Platform')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select("row[{'platform'}]", 'weibo,wechat,qq', "", ['id' => 'c-platform', 'class' => 'form-control selectpicker', 'multiple', 'required'])}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-openid" class="control-label col-xs-12 col-sm-2">{:__('Openid')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[openid]" value=""  id="c-openid" class="form-control"  />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-openname" class="control-label col-xs-12 col-sm-2">{:__('Openname')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[openname]" value=""  id="c-openname" class="form-control"  />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-access_token" class="control-label col-xs-12 col-sm-2">{:__('Access_token')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[access_token]" value=""  id="c-access_token" class="form-control"  />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-refresh_token" class="control-label col-xs-12 col-sm-2">{:__('Refresh_token')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[refresh_token]" value=""  id="c-refresh_token" class="form-control"  />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-expires_in" class="control-label col-xs-12 col-sm-2">{:__('Expires_in')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[expires_in]" value="0"  id="c-expires_in" class="form-control    " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-logintime" class="control-label col-xs-12 col-sm-2">{:__('Logintime')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="datetime" name="row[logintime]" value="0"  id="c-logintime" class="form-control datetimepicker   " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-expiretime" class="control-label col-xs-12 col-sm-2">{:__('Expiretime')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="datetime" name="row[expiretime]" value="0"  id="c-expiretime" class="form-control datetimepicker   " />
+        </div>
+    </div>
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+
+</form>

+ 64 - 0
application/admin/view/user/third/edit.phtml

@@ -0,0 +1,64 @@
+<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label for="c-user_id" class="control-label col-xs-12 col-sm-2">{:__('User_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[user_id]" value="{$row.user_id}"  id="c-user_id" class="form-control   typeahead " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-platform" class="control-label col-xs-12 col-sm-2">{:__('Platform')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_select("row[platform]", 'weibo,wechat,qq', $row['platform'], ['id' => 'c-platform', 'class' => 'form-control selectpicker', 'multiple', 'required']);}
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-openid" class="control-label col-xs-12 col-sm-2">{:__('Openid')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[openid]" value="{$row.openid}"  id="c-openid" class="form-control    "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-openname" class="control-label col-xs-12 col-sm-2">{:__('Openname')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[openname]" value="{$row.openname}"  id="c-openname" class="form-control    "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-access_token" class="control-label col-xs-12 col-sm-2">{:__('Access_token')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[access_token]" value="{$row.access_token}"  id="c-access_token" class="form-control    "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-refresh_token" class="control-label col-xs-12 col-sm-2">{:__('Refresh_token')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[refresh_token]" value="{$row.refresh_token}"  id="c-refresh_token" class="form-control    "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-expires_in" class="control-label col-xs-12 col-sm-2">{:__('Expires_in')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[expires_in]" value="{$row.expires_in}"  id="c-expires_in" class="form-control    " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-logintime" class="control-label col-xs-12 col-sm-2">{:__('Logintime')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="datetime" name="row[logintime]" value="{$row.logintime|datetime}"  id="c-logintime" class="form-control datetimepicker   " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-expiretime" class="control-label col-xs-12 col-sm-2">{:__('Expiretime')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="datetime" name="row[expiretime]" value="{$row.expiretime|datetime}"  id="c-expiretime" class="form-control datetimepicker   " />
+        </div>
+    </div>
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 25 - 0
application/admin/view/user/third/index.phtml

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar()}
+                        <div class="dropdown btn-group">
+                            <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
+                            <ul class="dropdown-menu text-left" role="menu">
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> 设为正常</a></li>
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> 设为隐藏</a></li>
+                            </ul>
+                        </div>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover" width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 193 - 0
application/admin/view/user/user/add.phtml

@@ -0,0 +1,193 @@
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="c-partner_id" class="control-label col-xs-12 col-sm-2">{:__('Partner_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[partner_id]" value=""  id="c-partner_id" class="form-control typeahead "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-role_id" class="control-label col-xs-12 col-sm-2">{:__('Role_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[role_id]" value="0"  id="c-role_id" class="form-control typeahead " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-area_id" class="control-label col-xs-12 col-sm-2">{:__('Area_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[area_id]" value="0"  id="c-area_id" class="form-control typeahead " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-editor_id" class="control-label col-xs-12 col-sm-2">{:__('Editor_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[editor_id]" value="0"  id="c-editor_id" class="form-control typeahead " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-editor_id" class="control-label col-xs-12 col-sm-2">{:__('Wx_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[wx_id]" value=""  id="c-wx_id" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-level" class="control-label col-xs-12 col-sm-2">{:__('Level')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[level]" value="0"  id="c-level" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-star" class="control-label col-xs-12 col-sm-2">{:__('Star')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[star]" value="0"  id="c-star" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-username" class="control-label col-xs-12 col-sm-2">{:__('Username')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[username]" value=""  id="c-username" class="form-control  "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[nickname]" value=""  id="c-nickname" class="form-control  "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-password" class="control-label col-xs-12 col-sm-2">{:__('Password')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[password]" value=""  id="c-password" class="form-control  "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-salt" class="control-label col-xs-12 col-sm-2">{:__('Salt')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[salt]" value=""  id="c-salt" class="form-control  "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-email" class="control-label col-xs-12 col-sm-2">{:__('Email')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[email]" value=""  id="c-email" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-mobile" class="control-label col-xs-12 col-sm-2">{:__('Mobile')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[mobile]" value=""  id="c-mobile" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-avatar" class="control-label col-xs-12 col-sm-2">{:__('Avatar')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="form-inline">
+                <input type="text" name="row[avatar]" value=""  id="c-avatar" class="form-control  "required data-plupload-id="plupload-avatar-text" size="50" />
+                <span><button id="plupload-avatar" class="btn btn-danger plupload" ><i class="fa fa-upload"></i> {:__("Upload")}</button></span>
+            </div>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-gender" class="control-label col-xs-12 col-sm-2">{:__('Gender')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[gender]" value="0"  id="c-gender" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-birthday" class="control-label col-xs-12 col-sm-2">{:__('Birthday')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[birthday]" value=""  id="c-birthday" class="form-control  "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-score" class="control-label col-xs-12 col-sm-2">{:__('Score')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[score]" value="0"  id="c-score" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-feeds" class="control-label col-xs-12 col-sm-2">{:__('Feeds')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[feeds]" value="0"  id="c-feeds" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-follows" class="control-label col-xs-12 col-sm-2">{:__('Follows')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[follows]" value="0"  id="c-follows" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-fans" class="control-label col-xs-12 col-sm-2">{:__('Fans')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[fans]" value="0"  id="c-fans" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-prevtime" class="control-label col-xs-12 col-sm-2">{:__('Prevtime')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="datetime" name="row[prevtime]" value="0"  id="c-prevtime" class="form-control datetimepicker   " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-loginfailure" class="control-label col-xs-12 col-sm-2">{:__('Loginfailure')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[loginfailure]" value="0"  id="c-loginfailure" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-logintime" class="control-label col-xs-12 col-sm-2">{:__('Logintime')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="datetime" name="row[logintime]" value="0"  id="c-logintime" class="form-control datetimepicker   " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-loginip" class="control-label col-xs-12 col-sm-2">{:__('Loginip')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[loginip]" value=""  id="c-loginip" class="form-control  "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-joinip" class="control-label col-xs-12 col-sm-2">{:__('Joinip')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[joinip]" value=""  id="c-joinip" class="form-control  "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-jointime" class="control-label col-xs-12 col-sm-2">{:__('Jointime')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="datetime" name="row[jointime]" value="0"  id="c-jointime" class="form-control datetimepicker   " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-address" class="control-label col-xs-12 col-sm-2">{:__('Address')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[address]" value=""  id="c-address" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-receiver" class="control-label col-xs-12 col-sm-2">{:__('Receiver')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[receiver]" value=""  id="c-receiver" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-token" class="control-label col-xs-12 col-sm-2">{:__('Token')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[token]" value=""  id="c-token" class="form-control  "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_status();}
+        </div>
+    </div>
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+
+</form>

+ 187 - 0
application/admin/view/user/user/edit.phtml

@@ -0,0 +1,187 @@
+<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label for="c-partner_id" class="control-label col-xs-12 col-sm-2">{:__('Partner_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[partner_id]" value="{$row.partner_id}"  id="c-partner_id" class="form-control typeahead "required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-role_id" class="control-label col-xs-12 col-sm-2">{:__('Role_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[role_id]" value="{$row.role_id}"  id="c-role_id" class="form-control typeahead " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-area_id" class="control-label col-xs-12 col-sm-2">{:__('Area_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[area_id]" value="{$row.area_id}"  id="c-area_id" class="form-control typeahead " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-editor_id" class="control-label col-xs-12 col-sm-2">{:__('Editor_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[editor_id]" value="{$row.editor_id}"  id="c-editor_id" class="form-control typeahead " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-editor_id" class="control-label col-xs-12 col-sm-2">{:__('Wx_id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[wx_id]" value="{$row.wx_id}"  id="c-wx_id" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-level" class="control-label col-xs-12 col-sm-2">{:__('Level')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[level]" value="{$row.level}"  id="c-level" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-star" class="control-label col-xs-12 col-sm-2">{:__('Star')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[star]" value="{$row.star}"  id="c-star" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-username" class="control-label col-xs-12 col-sm-2">{:__('Username')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[username]" value="{$row.username}"  id="c-username" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[nickname]" value="{$row.nickname}"  id="c-nickname" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-password" class="control-label col-xs-12 col-sm-2">{:__('Password')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[password]" value="{$row.password}"  id="c-password" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-salt" class="control-label col-xs-12 col-sm-2">{:__('Salt')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[salt]" value="{$row.salt}"  id="c-salt" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-email" class="control-label col-xs-12 col-sm-2">{:__('Email')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[email]" value="{$row.email}"  id="c-email" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-mobile" class="control-label col-xs-12 col-sm-2">{:__('Mobile')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[mobile]" value="{$row.mobile}"  id="c-mobile" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-avatar" class="control-label col-xs-12 col-sm-2">{:__('Avatar')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="form-inline">
+                <input type="text" name="row[avatar]" value="{$row.avatar}"  id="c-avatar" class="form-control" required data-plupload-id="plupload-avatar-text" size="50" />
+                <span><button id="plupload-avatar" class="btn btn-danger plupload" ><i class="fa fa-upload"></i> {:__("Upload")}</button></span>
+            </div>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-gender" class="control-label col-xs-12 col-sm-2">{:__('Gender')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[gender]" value="{$row.gender}"  id="c-gender" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-birthday" class="control-label col-xs-12 col-sm-2">{:__('Birthday')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[birthday]" value="{$row.birthday}"  id="c-birthday" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-score" class="control-label col-xs-12 col-sm-2">{:__('Score')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[score]" value="{$row.score}"  id="c-score" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-feeds" class="control-label col-xs-12 col-sm-2">{:__('Feeds')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[feeds]" value="{$row.feeds}"  id="c-feeds" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-follows" class="control-label col-xs-12 col-sm-2">{:__('Follows')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[follows]" value="{$row.follows}"  id="c-follows" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-fans" class="control-label col-xs-12 col-sm-2">{:__('Fans')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[fans]" value="{$row.fans}"  id="c-fans" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-loginfailure" class="control-label col-xs-12 col-sm-2">{:__('Loginfailure')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="number" name="row[loginfailure]" value="{$row.loginfailure}"  id="c-loginfailure" class="form-control  " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-logintime" class="control-label col-xs-12 col-sm-2">{:__('Logintime')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="datetime" name="row[logintime]" value="{$row.logintime|datetime}"  id="c-logintime" class="form-control datetimepicker   " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-loginip" class="control-label col-xs-12 col-sm-2">{:__('Loginip')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[loginip]" value="{$row.loginip}"  id="c-loginip" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-joinip" class="control-label col-xs-12 col-sm-2">{:__('Joinip')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[joinip]" value="{$row.joinip}"  id="c-joinip" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-jointime" class="control-label col-xs-12 col-sm-2">{:__('Jointime')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="datetime" name="row[jointime]" value="{$row.jointime|datetime}"  id="c-jointime" class="form-control datetimepicker   " />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-address" class="control-label col-xs-12 col-sm-2">{:__('Address')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[address]" value="{$row.address}"  id="c-address" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-receiver" class="control-label col-xs-12 col-sm-2">{:__('Receiver')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[receiver]" value="{$row.receiver}"  id="c-receiver" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-token" class="control-label col-xs-12 col-sm-2">{:__('Token')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[token]" value="{$row.token}"  id="c-token" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_status(NULL, $row['status']);}
+        </div>
+    </div>
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 25 - 0
application/admin/view/user/user/index.phtml

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {build_toolbar()}
+                        <div class="dropdown btn-group">
+                            <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
+                            <ul class="dropdown-menu text-left" role="menu">
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> 设为正常</a></li>
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> 设为隐藏</a></li>
+                            </ul>
+                        </div>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover" width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 51 - 0
application/admin/view/wechat/autoreply/add.html

@@ -0,0 +1,51 @@
+<link href="{:$site['cdnurl']}/assets/css/wechat/menu.css?v={:$site['version']}" rel="stylesheet">
+<style>
+    .clickbox {margin:0;text-align: left;}
+    .create-click {
+        margin-left:0;
+    }
+</style>
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="c-title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[title]" value=""  id="c-title" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-text" class="control-label col-xs-12 col-sm-2">{:__('Text')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[text]" value=""  id="c-text" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-content" class="control-label col-xs-12 col-sm-2">{:__('Event key')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[eventkey]" id="c-eventkey" class="form-control" value="" required readonly />
+            <div class="clickbox">
+                <span class="create-click"><a href="{:url('wechat.response/select')}" id="select-resources"><i class="weixin-icon big-add-gray"></i><strong>选择现有资源</strong></a></span>
+                <span class="create-click"><a href="{:url('wechat.response/add')}" id="add-resources"><i class="weixin-icon big-add-gray"></i><strong>添加新资源</strong></a></span>
+            </div>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-remark" class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[remark]" value=""  id="c-remark" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
+        </div>
+    </div>
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+
+</form>

+ 57 - 0
application/admin/view/wechat/autoreply/edit.html

@@ -0,0 +1,57 @@
+<link href="<?= $site['cdnurl'] ?>/assets/css/wechat/menu.css?v=<?= $site['version'] ?>" rel="stylesheet">
+<style>
+    .clickbox {margin:0;text-align: left;}
+    .create-click {
+        margin-left:0;
+    }
+</style>
+<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label for="c-title" class="control-label col-xs-12 col-sm-2"><?= __('Title') ?>:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[title]" value="<?= $row['title'] ?>"  id="c-title" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-text" class="control-label col-xs-12 col-sm-2"><?= __('Text') ?>:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[text]" value="<?= $row['text'] ?>"  id="c-text" class="form-control" required />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-content" class="control-label col-xs-12 col-sm-2"><?= __('Content') ?>:</label>
+        <div class="col-xs-12 col-sm-8">
+            <div class="clickbox">
+                <input type="hidden" name="row[eventkey]" id="c-eventkey" value="<?= $row['eventkey'] ?>" />
+                <span class="create-click"><a href="<?= url('wechat.response/select') ?>" id="select-resources"><i class="weixin-icon big-add-gray"></i><strong>选择现有资源</strong></a><div class="keytitle">资源名:<?= $response['title'] ?></div></span>
+                <span class="create-click"><a href="<?= url('wechat.response/add') ?>" id="add-resources"><i class="weixin-icon big-add-gray"></i><strong>添加新资源</strong></a></span>
+            </div>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-remark" class="control-label col-xs-12 col-sm-2"><?= __('Remark') ?>:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" name="row[remark]" value="<?= $row['remark'] ?>"  id="c-remark" class="form-control" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="c-createtime" class="control-label col-xs-12 col-sm-2"><?= __('Createtime') ?>:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="datetime" name="row[createtime]" value="<?= date("Y-m-d H:i:s", $row['createtime']) ?>"  id="c-createtime" class="form-control datetimepicker" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2"><?= __('Status') ?>:</label>
+        <div class="col-xs-12 col-sm-8">
+            <?= build_status(NULL, $row['status']); ?>
+        </div>
+    </div>
+    <div class="form-group hide layer-footer">
+        <label class="control-label col-xs-12 col-sm-2"></label>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed"><?= __('OK') ?></button>
+            <button type="reset" class="btn btn-default btn-embossed"><?= __('Reset') ?></button>
+        </div>
+    </div>
+</form>

+ 25 - 0
application/admin/view/wechat/autoreply/index.html

@@ -0,0 +1,25 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar()}
+                        <div class="dropdown btn-group">
+                            <a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> <?= __('More') ?></a>
+                            <ul class="dropdown-menu text-left" role="menu">
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> 设为正常</a></li>
+                                <li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> 设为隐藏</a></li>
+                            </ul>
+                        </div>
+                    </div>
+                    <table id="table" class="table table-striped table-bordered table-hover" width="100%">
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 28 - 0
application/admin/view/wechat/config/add.html

@@ -0,0 +1,28 @@
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="module" class="control-label col-xs-12 col-sm-2">{:__('Id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="id" name="row[id]" value="" pattern="[A-Za-z0-9_\.]{3,}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="controller" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="name" name="row[name]" value="" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="action" class="control-label col-xs-12 col-sm-2">{:__('Value')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea class="form-control" id="value" name="row[value]" required="required"></textarea>
+            <a href="javascript:;" class="btn-insertlink">{:__('Insert link')}</a>
+        </div>
+    </div>
+    <div class="form-group hidden layer-footer">
+        <div class="col-xs-2"></div>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 28 - 0
application/admin/view/wechat/config/edit.html

@@ -0,0 +1,28 @@
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="module" class="control-label col-xs-12 col-sm-2">{:__('Id')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="id" name="row[id]" value="{$row.id}" pattern="[A-Za-z0-9_\.]{3,}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="controller" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="name" name="row[name]" value="{$row.name}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="action" class="control-label col-xs-12 col-sm-2">{:__('Value')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea class="form-control" id="value" name="row[value]" required="required">{$row.value}</textarea>
+            <a href="javascript:;" class="btn-insertlink">{:__('Insert link')}</a>
+        </div>
+    </div>
+    <div class="form-group hidden layer-footer">
+        <div class="col-xs-2"></div>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+</form>

+ 19 - 0
application/admin/view/wechat/config/index.html

@@ -0,0 +1,19 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                       {:build_toolbar()}
+                    </div>
+                    <table id="table" class="table table-bordered table-hover" width="100%">
+
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 82 - 0
application/admin/view/wechat/menu/index.html

@@ -0,0 +1,82 @@
+<link href="__CDN__/assets/css/wechat/menu.css?v={$site['version']}" rel="stylesheet">
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div class="weixin-menu-setting">
+                        <div class="mobile-menu-preview">
+                            <div class="mobile-head-title">{$site.name}</div>
+                            <ul class="menu-list" id="menu-list">
+                                <li class="add-item extra" id="add-item">
+                                    <a href="javascript:;" class="menu-link" title="添加菜单"><i class="weixin-icon add-gray"></i></a>
+                                </li>
+                            </ul>
+                        </div>
+                        <div class="weixin-content">
+                            <div class="item-info">
+                                <form id="form-item" class="form-item" data-value="" >
+                                    <div class="item-head">
+                                        <h4 id="current-item-name">添加子菜单</h4>
+                                        <div class="item-delete"><a href="javascript:;" id="item_delete">删除菜单</a></div>
+                                    </div>
+                                    <div style="margin-top: 20px;">
+                                        <dl>
+                                            <dt id="current-item-option"><span class="is-sub-item">子</span>菜单标题:</dt>
+                                            <dd><div class="input-box"><input id="item_title" name="item-title" type="text" value=""></div></dd>
+                                        </dl>
+                                        <dl class="is-item">
+                                            <dt id="current-item-type"><span class="is-sub-item">子</span>菜单内容:</dt>
+                                            <dd>
+                                                <input id="type1" type="radio" name="type" value="click"><label for="type1" data-editing="1"><span class="lbl_content">发送消息</span></label>
+                                                <input id="type2" type="radio" name="type" value="view" ><label for="type2"  data-editing="1"><span class="lbl_content">跳转网页</span></label>
+                                                <input id="type3" type="radio" name="type" value="scancode_push"><label for="type3" data-editing="1"><span class="lbl_content">扫码推</span></label>
+                                                <input id="type4" type="radio" name="type" value="scancode_waitmsg"><label for="type4" data-editing="1"><span class="lbl_content">扫码推提示框</span></label>
+                                                <input id="type5" type="radio" name="type" value="pic_sysphoto"><label for="type5" data-editing="1"><span class="lbl_content">拍照发图</span></label>
+                                                <input id="type6" type="radio" name="type" value="pic_photo_or_album"><label for="type6" data-editing="1"><span class="lbl_content">拍照相册发图</span></label>
+                                                <input id="type7" type="radio" name="type" value="pic_weixin"><label for="type7" data-editing="1"><span class="lbl_content">相册发图</span></label>
+                                                <input id="type8" type="radio" name="type" value="location_select"><label for="type8" data-editing="1"><span class="lbl_content">地理位置选择</span></label>
+                                            </dd>
+                                        </dl>
+                                        <div id="menu-content" class="is-item">
+                                            <div class="viewbox is-view">
+                                                <p class="menu-content-tips">点击该<span class="is-sub-item">子</span>菜单会跳到以下链接</p>
+                                                <dl>
+                                                    <dt>页面地址:</dt>
+                                                    <dd><div class="input-box"><input type="text" id="url" name="url"></div>
+                                                    </dd>
+                                                </dl>
+                                            </div>
+                                            <div class="clickbox is-click" style="display: none;">
+                                                <input type="hidden" name="key" id="key" value="" />
+                                                <span class="create-click"><a href="{:url('wechat.response/select')}" id="select-resources"><i class="weixin-icon big-add-gray"></i><strong>选择现有资源</strong></a></span>
+                                                <span class="create-click"><a href="{:url('wechat.response/add')}" id="add-resources"><i class="weixin-icon big-add-gray"></i><strong>添加新资源</strong></a></span>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </form>
+                            </div>
+
+                        </div>
+                        <div class="no-weixin-content">
+                            点击左侧菜单进行编辑操作
+                        </div>
+                    </div>
+                    <div class="row">
+                        <div class="col-xs-4 text-center text-danger">
+                            <i class="fa fa-lightbulb-o"></i> <small>可直接拖动菜单排序</small>
+                        </div>
+                        <div class="col-xs-8 text-center"><a href="javascript:;" id="menuSyn" class="btn btn-danger">保存并发布</a></div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>
+<script type="text/javascript">
+    var menu = {:json_encode($menu, JSON_UNESCAPED_UNICODE)};
+    var responselist = {:json_encode($responselist, JSON_UNESCAPED_UNICODE)};
+</script>

+ 54 - 0
application/admin/view/wechat/response/add.html

@@ -0,0 +1,54 @@
+<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+    <div class="form-group">
+        <label for="module" class="control-label col-xs-12 col-sm-2">{:__('Resource title')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="title" name="row[title]" value="" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="controller" class="control-label col-xs-12 col-sm-2">{:__('Event key')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="eventkey" name="row[eventkey]" value="" pattern="[A-Za-z0-9_]{1,}" readonly />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Memo')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea class="form-control" id="remark" name="row[remark]"></textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="radio" name="row[type]" value="text" id="type-text" checked />
+            <label for="type-text">{:__('Text')}</label>
+            <input type="radio" name="row[type]" value="app" id="type-app" />
+            <label for="type-app">{:__('App')}</label>
+        </div>
+    </div>
+    <div id="expand">
+
+    </div>
+    <div class="form-group">
+        <label for="status" class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
+        </div>
+    </div>
+    <div class="form-group {:input('get.callback')?'':'hidden layer-footer'}">
+        <div class="col-xs-2"></div>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+    <select name="applist" disabled="true" class="hidden">
+        {foreach $applist as $k => $v}
+            <option value="{$k}">{$v.name}</option>
+        {/foreach}
+    </select>
+</form>
+<script>
+    var apps = {:json_encode($applist)};
+    var datas = {};
+</script>

+ 52 - 0
application/admin/view/wechat/response/edit.html

@@ -0,0 +1,52 @@
+<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
+
+    <div class="form-group">
+        <label for="module" class="control-label col-xs-12 col-sm-2">{:__('Resource title')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type="text" class="form-control" id="title" name="row[title]" value="{$row.title}" required="required" />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="controller" class="control-label col-xs-12 col-sm-2">{:__('Event key')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input type='text' class="form-control" id="eventkey" name="row[eventkey]" value="{$row.eventkey}" pattern="[A-Za-z0-9_]{1,}" required="required" readonly />
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Memo')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <textarea class="form-control" id="remark" name="row[remark]">{$row.remark}</textarea>
+        </div>
+    </div>
+    <div class="form-group">
+        <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[type]', ['text' => __('Text'), 'app' => __('App')], $row['type'])}
+        </div>
+    </div>
+    <div id="expand">
+
+    </div>
+    <div class="form-group">
+        <div class="col-xs-2"></div>
+        <div class="col-xs-12 col-sm-8">
+            {:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
+        </div>
+    </div>
+    <div class="form-group hidden layer-footer">
+        <div class="col-xs-2"></div>
+        <div class="col-xs-12 col-sm-8">
+            <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+            <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+        </div>
+    </div>
+    <select name="applist" disabled="true" class="hidden">
+        {foreach $applist as $k => $v}
+            <option value="{$k}">{$v.name}</option>
+        {/foreach}
+    </select>
+</form>
+<script>
+    var apps = {:json_encode($applist)};
+    var datas = {$row.content};
+</script>

+ 19 - 0
application/admin/view/wechat/response/index.html

@@ -0,0 +1,19 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <div id="toolbar" class="toolbar">
+                        {:build_toolbar();}
+                    </div>
+                    <table id="table" class="table table-bordered table-hover" width="100%">
+
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 16 - 0
application/admin/view/wechat/response/select.html

@@ -0,0 +1,16 @@
+<div class="panel panel-default panel-intro">
+    {:build_heading()}
+
+    <div class="panel-body">
+        <div id="myTabContent" class="tab-content">
+            <div class="tab-pane fade active in" id="one">
+                <div class="widget-body no-padding">
+                    <table id="table" class="table table-bordered table-hover" width="100%">
+
+                    </table>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>

+ 1 - 0
application/api/common.php

@@ -0,0 +1 @@
+<?php

+ 5 - 0
application/api/config.php

@@ -0,0 +1,5 @@
+<?php
+//配置文件
+return [
+
+];

+ 15 - 0
application/api/controller/Index.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace app\api\controller;
+
+use app\common\controller\Api;
+
+class Index extends Api
+{
+
+    public function index()
+    {
+        return json(['code' => 0]);
+    }
+
+}

+ 25 - 0
application/build.php

@@ -0,0 +1,25 @@
+<?php
+
+// +----------------------------------------------------------------------
+// | ThinkPHP [ WE CAN DO IT JUST THINK ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+// +----------------------------------------------------------------------
+// | Author: liu21st <liu21st@gmail.com>
+// +----------------------------------------------------------------------
+
+return [
+// 生成应用公共文件
+    '__file__' => [],
+    // 定义demo模块的自动生成 (按照实际定义的文件名生成)
+    'demo'     => [
+        '__file__'   => ['common.php'],
+        '__dir__'    => ['behavior', 'controller', 'model', 'view'],
+        'controller' => ['Index', 'Test', 'UserType'],
+        'model'      => ['User', 'UserType'],
+        'view'       => ['index/index'],
+    ],
+        // 其他更多的模块定义
+];

+ 0 - 0
application/command.php


Some files were not shown because too many files changed in this diff