Browse Source

项目初始化

linwu 8 months ago
commit
401863f6cf
100 changed files with 7193 additions and 0 deletions
  1. 1 0
      .example.env
  2. 4 0
      .gitignore
  3. 42 0
      .travis.yml
  4. 32 0
      LICENSE.txt
  5. 75 0
      README.md
  6. 1 0
      app/.htaccess
  7. 20 0
      app/AppService.php
  8. 146 0
      app/BaseController.php
  9. 58 0
      app/ExceptionHandle.php
  10. 8 0
      app/Request.php
  11. 62 0
      app/admin/AdminBaseController.php
  12. 8 0
      app/admin/common.php
  13. 18 0
      app/admin/config/view.php
  14. 180 0
      app/admin/controller/Admin.php
  15. 237 0
      app/admin/controller/Article.php
  16. 44 0
      app/admin/controller/Feedback.php
  17. 15 0
      app/admin/controller/Help.php
  18. 71 0
      app/admin/controller/Home.php
  19. 12 0
      app/admin/controller/Index.php
  20. 43 0
      app/admin/controller/Login.php
  21. 79 0
      app/admin/controller/Navigation.php
  22. 77 0
      app/admin/controller/Notice.php
  23. 42 0
      app/admin/controller/Page.php
  24. 63 0
      app/admin/controller/Setting.php
  25. 79 0
      app/admin/controller/Slide.php
  26. 77 0
      app/admin/controller/SmsTemplate.php
  27. 46 0
      app/admin/controller/Upload.php
  28. 133 0
      app/admin/controller/User.php
  29. 17 0
      app/admin/event.php
  30. 10 0
      app/admin/middleware.php
  31. 9 0
      app/admin/provider.php
  32. 20 0
      app/admin/validate/AdminValidate.php
  33. 20 0
      app/admin/validate/ArticleCateValidate.php
  34. 25 0
      app/admin/validate/ArticleValidate.php
  35. 23 0
      app/admin/validate/NavigationValidate.php
  36. 21 0
      app/admin/validate/NoticeValidate.php
  37. 23 0
      app/admin/validate/SlideValidate.php
  38. 19 0
      app/admin/validate/SmsTemplateValidate.php
  39. 26 0
      app/admin/validate/UserValidate.php
  40. 128 0
      app/admin/view/admin/admin_form.html
  41. 187 0
      app/admin/view/admin/index.html
  42. 79 0
      app/admin/view/admin/my_info.html
  43. 64 0
      app/admin/view/admin/my_password.html
  44. 213 0
      app/admin/view/article/article_form.html
  45. 173 0
      app/admin/view/article/cate.html
  46. 69 0
      app/admin/view/article/cate_form.html
  47. 203 0
      app/admin/view/article/index.html
  48. 126 0
      app/admin/view/feedback/index.html
  49. 80 0
      app/admin/view/help/link.html
  50. 177 0
      app/admin/view/home/console.html
  51. 199 0
      app/admin/view/home/homepage1.html
  52. 316 0
      app/admin/view/home/homepage2.html
  53. 118 0
      app/admin/view/home/homepage3.html
  54. 143 0
      app/admin/view/home/index.html
  55. 3 0
      app/admin/view/layout.html
  56. 72 0
      app/admin/view/login/login.html
  57. 178 0
      app/admin/view/navigation/index.html
  58. 148 0
      app/admin/view/navigation/navigation_form.html
  59. 148 0
      app/admin/view/notice/index.html
  60. 89 0
      app/admin/view/notice/notice_form.html
  61. 56 0
      app/admin/view/page/index.html
  62. 3 0
      app/admin/view/public/footer.html
  63. 25 0
      app/admin/view/public/header.html
  64. 67 0
      app/admin/view/public/import.html
  65. 6 0
      app/admin/view/public/ueditor.html
  66. 179 0
      app/admin/view/setting/sms.html
  67. 59 0
      app/admin/view/setting/system.html
  68. 178 0
      app/admin/view/slide/index.html
  69. 148 0
      app/admin/view/slide/slide_form.html
  70. 92 0
      app/admin/view/sms_template/index.html
  71. 66 0
      app/admin/view/sms_template/template_form.html
  72. 83 0
      app/admin/view/user/follow.html
  73. 192 0
      app/admin/view/user/index.html
  74. 167 0
      app/admin/view/user/user_form.html
  75. 121 0
      app/common.php
  76. 39 0
      app/common/model/AdminModel.php
  77. 25 0
      app/common/model/ArticleCateModel.php
  78. 41 0
      app/common/model/ArticleModel.php
  79. 10 0
      app/common/model/BaseModel.php
  80. 29 0
      app/common/model/FeedbackModel.php
  81. 27 0
      app/common/model/MenuModel.php
  82. 29 0
      app/common/model/NavigationModel.php
  83. 24 0
      app/common/model/NoticeModel.php
  84. 67 0
      app/common/model/SettingModel.php
  85. 68 0
      app/common/model/SinglePageModel.php
  86. 29 0
      app/common/model/SlideModel.php
  87. 10 0
      app/common/model/SmsTemplateModel.php
  88. 30 0
      app/common/model/UserFollowModel.php
  89. 55 0
      app/common/model/UserModel.php
  90. 42 0
      app/common/service/QrcodeService.php
  91. 29 0
      app/common/service/SmsService.php
  92. 17 0
      app/event.php
  93. 10 0
      app/middleware.php
  94. 1 0
      app/mobile/.htaccess
  95. 23 0
      app/mobile/MobileBaseController.php
  96. 62 0
      app/mobile/common.php
  97. 18 0
      app/mobile/config/view.php
  98. 49 0
      app/mobile/controller/Article.php
  99. 59 0
      app/mobile/controller/Index.php
  100. 159 0
      app/mobile/controller/Login.php

+ 1 - 0
.example.env

@@ -0,0 +1 @@
+APP_DEBUG = true

[APP]
DEFAULT_TIMEZONE = Asia/Shanghai

[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = test
USERNAME = username
PASSWORD = password
HOSTPORT = 3306
CHARSET = utf8mb4
DEBUG = true

[LANG]
default_lang = zh-cn

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+/.idea
+/.vscode
+*.log
+.env

+ 42 - 0
.travis.yml

@@ -0,0 +1,42 @@
+sudo: false
+
+language: php
+
+branches:
+  only:
+    - stable
+
+cache:
+  directories:
+    - $HOME/.composer/cache
+
+before_install:
+  - composer self-update
+
+install:
+  - composer install --no-dev --no-interaction --ignore-platform-reqs
+  - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
+  - composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
+  - composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
+  - composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
+  - composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
+  - composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
+  - composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
+  - composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
+  - composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
+  - composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
+  - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
+
+script:
+  - php think unit
+
+deploy:
+  provider: releases
+  api_key:
+    secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
+  file:
+    - ThinkPHP_Core.zip
+    - ThinkPHP_Full.zip
+  skip_cleanup: true
+  on:
+    tags: true

+ 32 - 0
LICENSE.txt

@@ -0,0 +1,32 @@
+
+ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
+版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
+All rights reserved。
+ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
+
+Apache Licence是著名的非盈利开源组织Apache采用的协议。
+该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
+允许代码修改,再作为开源或商业软件发布。需要满足
+的条件: 
+1. 需要给代码的用户一份Apache Licence ;
+2. 如果你修改了代码,需要在被修改的文件中说明;
+3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
+带有原来代码中的协议,商标,专利声明和其他原来作者规
+定需要包含的说明;
+4. 如果再发布的产品中包含一个Notice文件,则在Notice文
+件中需要带有本协议内容。你可以在Notice中增加自己的
+许可,但不可以表现为对Apache Licence构成更改。 
+具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.

+ 75 - 0
README.md

@@ -0,0 +1,75 @@
+![](https://box.kancloud.cn/5a0aaa69a5ff42657b5c4715f3d49221) 
+
+ThinkPHP 6.1
+===============
+
+### 主要新特性
+
+* 采用`PHP7`强类型(严格模式)
+* 支持更多的`PSR`规范
+* 原生多应用支持
+* 系统服务注入支持
+* ORM作为独立组件使用
+* 全新的事件系统
+* 模板引擎分离出核心
+* 内部功能中间件化
+* SESSION机制改进
+* 日志多通道支持
+* 规范扩展接口
+* 更强大的控制台
+* 对Swoole以及协程支持改进
+* 对IDE更加友好
+* 统一和精简大量用法
+
+
+> ThinkPHP6.1的运行环境要求PHP7.2.5+,最高兼容PHP8.2
+
+### 安装
+
+~~~
+composer create-project topthink/think tp
+~~~
+
+启动服务
+
+~~~
+cd tp
+php think run
+~~~
+
+然后就可以在浏览器中访问
+
+~~~
+http://localhost:8000
+~~~
+
+如果需要更新框架使用
+~~~
+composer update topthink/framework
+~~~
+
+### 文档
+
+[TP6完全开发手册](https://www.kancloud.cn/manual/thinkphp6_0/content)
+
+VUE3.3.4
+===============
+
+[VUE官方在线手册](https://cn.vuejs.org/)
+
+VANT4.6
+===============
+[VANT官方在线手册](https://vant-ui.github.io/vant/#/zh-CN/)
+
+LAYUI
+===============
+[官方在线手册](https://www.bejson.com/doc/layui/doc/index.html)
+
+其他
+===============
+### 需要写入权限文件
+~~~
+/runtime
+/public/storage
+/public/ueditor
+~~~

+ 1 - 0
app/.htaccess

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

+ 20 - 0
app/AppService.php

@@ -0,0 +1,20 @@
+<?php
+namespace app;
+
+use think\Service;
+
+/**
+ * 应用服务类
+ */
+class AppService extends Service
+{
+    public function register()
+    {
+        // 服务注册
+    }
+
+    public function boot()
+    {
+        // 服务启动
+    }
+}

+ 146 - 0
app/BaseController.php

@@ -0,0 +1,146 @@
+<?php
+declare (strict_types=1);
+
+namespace app;
+
+use think\App;
+use think\exception\ValidateException;
+use think\Validate;
+
+/**
+ * 控制器基础类
+ */
+abstract class BaseController
+{
+    /**
+     * 应用实例
+     * @var \think\App
+     */
+    protected $app;
+
+    /**
+     * 是否批量验证
+     * @var bool
+     */
+    protected $batchValidate = false;
+
+    /**
+     * 控制器中间件
+     * @var array
+     */
+    protected $middleware = [];
+
+    /**
+     * 构造方法
+     * @access public
+     * @param  App $app 应用对象
+     */
+    public function __construct(App $app)
+    {
+        $this->app     = $app;
+        $this->request = $this->app->request;
+
+        // 控制器初始化
+        $this->initialize();
+    }
+
+    // 初始化
+    protected function initialize()
+    {
+    }
+
+    /**
+     * 验证数据
+     * @access protected
+     * @param  array $data 数据
+     * @param  string|array $validate 验证器名或者验证规则数组
+     * @param  array $message 提示信息
+     * @param  bool $batch 是否批量验证
+     * @return array|string|true
+     * @throws ValidateException
+     */
+    protected function validate(array $data, $validate, array $message = [], bool $batch = false)
+    {
+        if (is_array($validate)) {
+            $v = new Validate();
+            $v->rule($validate);
+        } else {
+            if (strpos($validate, '.')) {
+                // 支持场景
+                [$validate, $scene] = explode('.', $validate);
+            }
+            $class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
+            $v     = new $class();
+            if (!empty($scene)) {
+                $v->scene($scene);
+            }
+        }
+
+        $v->message($message);
+
+        // 是否批量验证
+        if ($batch || $this->batchValidate) {
+            $v->batch(true);
+        }
+
+        return $v->failException(true)->check($data);
+    }
+
+
+    /**
+     * 等于条件
+     */
+    protected function dealEqualInput($equal_array, $result = [])
+    {
+        foreach ($equal_array as $k => $v) {
+            if (!is_numeric($k)) {
+                $value = input($k);
+            } else {
+                $value = input($v);
+            }
+            if (!empty($value)) {
+                $result[] = [$v, '=', $value];
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * like条件
+     */
+    protected function dealLikeInput($like_array, $result = [])
+    {
+        foreach ($like_array as $k => $v) {
+            if (!is_numeric($k)) {
+                $value = input($k);
+            } else {
+                $value = input($v);
+            }
+            if (!empty($value)) {
+                $result[] = [$v, 'like', "%{$value}%"];
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * in条件
+     */
+    protected function dealInInput($in_array, $result = [])
+    {
+        foreach ($in_array as $k => $v) {
+            if (!is_numeric($k)) {
+                $value = input($k);
+            } else {
+                $value = input($v);
+            }
+            if (!empty($value)) {
+                $result[] = [$v, 'in', $value];
+            }
+        }
+
+        return $result;
+    }
+}

+ 58 - 0
app/ExceptionHandle.php

@@ -0,0 +1,58 @@
+<?php
+namespace app;
+
+use think\db\exception\DataNotFoundException;
+use think\db\exception\ModelNotFoundException;
+use think\exception\Handle;
+use think\exception\HttpException;
+use think\exception\HttpResponseException;
+use think\exception\ValidateException;
+use think\Response;
+use Throwable;
+
+/**
+ * 应用异常处理类
+ */
+class ExceptionHandle extends Handle
+{
+    /**
+     * 不需要记录信息(日志)的异常类列表
+     * @var array
+     */
+    protected $ignoreReport = [
+        HttpException::class,
+        HttpResponseException::class,
+        ModelNotFoundException::class,
+        DataNotFoundException::class,
+        ValidateException::class,
+    ];
+
+    /**
+     * 记录异常信息(包括日志或者其它方式记录)
+     *
+     * @access public
+     * @param  Throwable $exception
+     * @return void
+     */
+    public function report(Throwable $exception): void
+    {
+        // 使用内置的方式记录异常日志
+        parent::report($exception);
+    }
+
+    /**
+     * Render an exception into an HTTP response.
+     *
+     * @access public
+     * @param \think\Request   $request
+     * @param Throwable $e
+     * @return Response
+     */
+    public function render($request, Throwable $e): Response
+    {
+        // 添加自定义异常处理机制
+
+        // 其他错误交给系统处理
+        return parent::render($request, $e);
+    }
+}

+ 8 - 0
app/Request.php

@@ -0,0 +1,8 @@
+<?php
+namespace app;
+
+// 应用请求对象类
+class Request extends \think\Request
+{
+
+}

+ 62 - 0
app/admin/AdminBaseController.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace app\admin;
+
+use app\BaseController;
+use app\common\model\AdminModel;
+use app\common\model\MenuModel;
+use think\facade\Session;
+use think\facade\View;
+
+/**
+ * 控制器基础类
+ */
+class AdminBaseController extends BaseController
+{
+    // 初始化
+    protected function initialize()
+    {
+        // 验证登陆信息
+        $access_admin = session('access_admin');
+        if (!$access_admin) {
+            $this->adminReturn('请重新登录');
+        }
+
+        // 验证权限
+        if ($access_admin['role'] != AdminModel::ROLE_SUPER && $this->request->controller() != 'Home') {
+            $url   = mb_strtolower($this->request->controller() . '/' . $this->request->action());
+            $check = MenuModel::where('urlstr', $url)->find();
+            if (!empty($check)) {
+                $url_ids = explode(',',$access_admin['powerids']);
+                if (!in_array($check['id'],$url_ids)) {
+                    $this->adminReturn('您没有访问权限');
+                }
+                if ($check['status'] == MenuModel::STATUS_DISABLE) {
+                    $this->adminReturn('您没有访问权限');
+                }
+            }
+        }
+
+        $lay        = mb_strtolower($this->request->controller()) . '-' . $this->request->action();
+        $lay_table  = "lay-{$lay}-table";
+        $lay_btn    = "lay-{$lay}-btn";
+        View::assign([
+            'lay_table'  => $lay_table,
+            'lay_btn'    => $lay_btn,
+        ]);
+    }
+
+    /**
+     * 返回
+     */
+    protected function adminReturn($msg)
+    {
+        if ($this->request->isAjax()) {
+            ajax_return(1001, $msg);
+        } else {
+            $content  = '<script language="javascript" type="text/javascript"> top.location.href="/admin/login/index"; </script>';
+            $response = \think\Response::create($content);
+            throw new \think\exception\HttpResponseException($response);
+        }
+    }
+}

+ 8 - 0
app/admin/common.php

@@ -0,0 +1,8 @@
+<?php
+// 应用公共文件
+
+function list_return($list, $count){
+    $res = ['code'=>0,'data' => $list,'count'=>$count];
+    $response = \think\Response::create($res, 'json');
+    throw new \think\exception\HttpResponseException($response);
+}

+ 18 - 0
app/admin/config/view.php

@@ -0,0 +1,18 @@
+<?php
+// +----------------------------------------------------------------------
+// | 模板设置
+// +----------------------------------------------------------------------
+
+return [
+    'layout_on'          => true,
+    'layout_name'        => 'layout',
+    // 模板常量
+    'tpl_replace_string' => [
+        '__STATIC__'        => '/static',
+        '__COMMON_IMAGES__' => '/static/common/images',
+        '__COMMON_CSS__'    => '/static/common/css',
+        '__COMMON_JS__'     => '/static/common/js',
+        '__ECHOUI__'        => '/static/admin/echoui',
+        '__AIMAGES__'       => '/static/admin/images',
+    ],
+];

+ 180 - 0
app/admin/controller/Admin.php

@@ -0,0 +1,180 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\AdminModel;
+use app\common\model\MenuModel;
+
+use app\admin\validate\AdminValidate;
+use think\exception\ValidateException;
+
+class Admin extends AdminBaseController
+{
+
+    public function index()
+    {
+        return view('', [
+            'role_list' => AdminModel::ROLE,
+        ]);
+    }
+
+    public function adminForm()
+    {
+        $id          = input('id/d, 0');
+        $info       = AdminModel::findOrEmpty($id);
+        $menulist    = MenuModel::where(['mtype' => 'admin', 'status' => 1])->order(['pid' => 'asc', 'priority' => 'asc', 'id' => 'asc'])->select()->toArray();
+        $powerarr    = [];
+        $poweridsarr = ($info->powerids == null || empty($info->powerids)) ? [] : explode(",", $info->powerids);
+        if (!empty($menulist)) {
+            foreach ($menulist as $k => $v) {
+                if ($v['pid'] == 0) {
+                    $v['checked']       = false;
+                    $v['children']      = [];
+                    $v['spread']        = true;
+                    $powerarr[$v['id']] = $v;
+                } else {
+                    $v['checked']                      = in_array($v['id'], $poweridsarr);
+                    $powerarr[$v['pid']]['children'][] = $v;
+                }
+            }
+        }
+        return view('', [
+            'info'    => $info,
+            'powerarr' => json_encode(array_values($powerarr)),
+        ]);
+    }
+
+    public function editAdmin()
+    {
+        $id    = input('id/d');
+        $vdata = [
+            'id'         => $id,
+            'admin_name' => input('admin_name/s'),
+            'realname'   => input('realname/s'),
+            'mobile'     => input('mobile/s'),
+        ];
+        try {
+            validate(AdminValidate::class)->check($vdata);
+        } catch (ValidateException $e) {
+            ajax_return(1, $e->getError());
+        }
+
+        $password = input('password/s');
+        $role     = input('role/d', 2);
+        $powerids = input('powerids/s', "");
+        if ($role == 1) {
+            $idsarr   = MenuModel::where(['mtype' => 'admin', 'status' => 1])->order(['pid' => 'asc', 'priority' => 'asc', 'id' => 'asc'])->column('id');
+            $powerids = implode(",", $idsarr);
+        }
+        $data = [
+            'role'      => $role,
+            'admin_name' => input('admin_name/s', ""),
+            'realname'  => input('realname/s', ""),
+            'mobile'    => input('mobile/s', ""),
+            'status'    => input('status/d') == 1 ? 1 : 2,
+            'powerids'  => $powerids,
+            'remark'    => input('remark', ""),
+        ];
+        if (empty($id)) {
+            $data['password']  = empty($password) ? md5("123456789") : md5($password);
+            $data['join_date'] = time();
+            $data['join_ip']   = $_SERVER['SERVER_ADDR'];
+            $data['last_date'] = time();
+            $data['last_ip']   = $_SERVER['SERVER_ADDR'];
+            AdminModel::create($data);
+        } else {
+            if (!empty($password)) {
+                $data['password'] = md5($password);
+            }
+            AdminModel::update($data, ['id' => $id]);
+        }
+        ajax_return();
+    }
+
+    // 删除管理员
+    public function delAdmin()
+    {
+        $access_admin = session('access_admin');
+        $password     = input('password');
+        if ($access_admin['password'] !== md5($password)) {
+            ajax_return(1, '操作密码验证失败');
+        }
+        $id_arr = input('id_arr/a');
+        if (in_array(1, $id_arr)) {
+            ajax_return(1, '无法删除超级管理员');
+        }
+        AdminModel::destroy($id_arr);
+        ajax_return();
+    }
+
+    public function listAdmin()
+    {
+        $limit      = input('limit');
+        $page       = input('page');
+        $map        = [];
+        $admin_name = input('admin_name');
+        if (!empty($admin_name)) {
+            $map['admin_name'] = $admin_name;
+        }
+        $realname = input('realname');
+        if (!empty($realname)) {
+            $map['realname'] = $realname;
+        }
+        $mobile = input('mobile');
+        if (!empty($mobile)) {
+            $map['mobile'] = $mobile;
+        }
+        $role = input('role');
+        if (!empty($role)) {
+            $map['role'] = $role;
+        }
+        $list  = AdminModel::where($map)->order('id', 'asc')->limit($limit)->page($page)->append(['status_text', 'role_text'])->select();
+        $count = AdminModel::where($map)->count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+
+        list_return($list, $count);
+    }
+
+    // 个人信息
+    public function myInfo()
+    {
+        $access_admin = session('access_admin');
+        $admin        = AdminModel::find($access_admin['id']);
+        return view('', [
+            'admin' => $admin,
+        ]);
+    }
+
+    public function editMyInfo()
+    {
+        $access_admin = session('access_admin');
+        AdminModel::update(['realname' => input('realname'), 'mobile' => input('mobile'), 'remark' => input('remark')], ['id' => $access_admin['id']]);
+        ajax_return();
+    }
+
+    public function myPassword()
+    {
+        return view('');
+    }
+
+    public function editMyPassword()
+    {
+        $access_admin = session('access_admin');
+        $oldpassword  = input('oldpassword');
+        if ($access_admin['password'] !== md5($oldpassword)) {
+            ajax_return(1, '当前密码不正确');
+        }
+        $password   = input('password');
+        $repassword = input('repassword');
+        if ($password !== $repassword) {
+            ajax_return(1, '两次输入的新密码不一致');
+        }
+        AdminModel::update(['password' => md5($password)], ['id' => $access_admin['id']]);
+        session('access_admin', null);
+        ajax_return();
+    }
+
+}

+ 237 - 0
app/admin/controller/Article.php

@@ -0,0 +1,237 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\ArticleModel;
+use app\common\model\ArticleCateModel;
+use app\admin\validate\ArticleCateValidate;
+use app\admin\validate\ArticleValidate;
+use think\exception\ValidateException;
+
+class Article extends AdminBaseController
+{
+    /**
+     * 列表
+     */
+    public function index()
+    {
+        $cate_list = ArticleCateModel::order(['priority' => 'desc', 'id' => 'desc'])->select();
+
+        return view('', [
+            'cate_list'   => $cate_list,
+            'type_list'   => ArticleModel::TYPE,
+            'status_list' => ArticleModel::STATUS,
+        ]);
+    }
+
+    public function articleForm()
+    {
+        $cate_list = ArticleCateModel::order(['priority' => 'desc', 'id' => 'desc'])->select();
+        $id        = input('id/d, 0');
+        $info      = ArticleModel::find($id);
+
+        return view('', [
+            'cate_list'   => $cate_list,
+            'info'        => $info,
+            'type_list'   => ArticleModel::TYPE,
+            'status_list' => ArticleModel::STATUS,
+        ]);
+    }
+
+    public function listArticle()
+    {
+        $map = $this->dealEqualInput(['cate_id', 'type', 'status'], $this->dealLikeInput(['title']));
+
+        $list  = ArticleModel::with('cate')
+            ->where($map)
+            ->order(['priority' => 'desc', 'id' => 'desc'])
+            ->limit(input('limit'))
+            ->page(input('page'))
+            ->append(['type_text', 'status_text'])
+            ->select();
+        $count = ArticleModel::where($map)->count();
+
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+
+    public function delArticle()
+    {
+        $id_arr = input('id_arr/a');
+        ArticleModel::destroy($id_arr);
+        ajax_return();
+    }
+
+    public function editArticle()
+    {
+        $data = input('post.');
+        try {
+            validate(ArticleValidate::class)->check($data);
+        } catch (ValidateException $e) {
+            ajax_return(1, $e->getError());
+        }
+
+        if ($data['type'] == 1 && empty($data['content'])) {
+            ajax_return(1, '详情不能为空');
+        }
+        if ($data['type'] == 2 && empty($data['url'])) {
+            ajax_return(1, '链接不能为空');
+        }
+
+        if (empty($data['id'])) {
+            ArticleModel::create($data, ArticleModel::EDIT_ALLOW);
+        } else {
+            ArticleModel::update($data, ['id' => $data['id']], ArticleModel::EDIT_ALLOW);
+        }
+
+        ajax_return();
+    }
+
+    public function fieldArticle()
+    {
+        $id      = input('id/d', 0);
+        $article = ArticleModel::find($id);
+        if (empty($article)) {
+            ajax_return(1, '信息不存在');
+        } else {
+            $article->save([
+                input('field/s') => input('value/s', ""),
+            ]);
+        }
+        ajax_return();
+    }
+
+
+    /**
+     * 分类
+     */
+    public function cate()
+    {
+        return view('', [
+            'status_list' => ArticleCateModel::STATUS,
+        ]);
+    }
+
+    public function cateForm()
+    {
+        $id   = input('id/d, 0');
+        $info = ArticleCateModel::find($id);
+        return view('', [
+            'info'        => $info,
+            'status_list' => ArticleCateModel::STATUS,
+        ]);
+    }
+
+    public function listCate()
+    {
+        $map   = $this->dealEqualInput(['status']);
+        $list  = ArticleCateModel::where($map)
+            ->order(['priority' => 'desc', 'id' => 'desc'])
+            ->limit(input('limit'))
+            ->page(input('page'))
+            ->append(['status_text'])
+            ->select();
+        $count = ArticleCateModel::where($map)->count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+
+    public function fieldCate()
+    {
+        $id   = input('id/d');
+        $cate = ArticleCateModel::find($id);
+        if (empty($cate)) {
+            ajax_return(1, '分类信息不存在');
+        } else {
+            $cate->save([
+                input('field/s') => input('value/s', ""),
+            ]);
+        }
+        ajax_return();
+    }
+
+    public function editCate()
+    {
+        $data = input('post.');
+        try {
+            validate(ArticleCateValidate::class)->check($data);
+        } catch (ValidateException $e) {
+            ajax_return(1, $e->getError());
+        }
+
+        if (empty($data['id'])) {
+            ArticleCateModel::create($data, ArticleCateModel::EDIT_ALLOW);
+        } else {
+            ArticleCateModel::update($data, ['id' => $data['id']], ArticleCateModel::EDIT_ALLOW);
+        }
+
+        ajax_return();
+    }
+
+    public function delCate()
+    {
+        $id    = input('id/d');
+        $check = ArticleModel::where('cate_id', $id)->find();
+        if (!empty($check)) {
+            ajax_return(1, '该分类下还有文章,无法删除');
+        }
+        ArticleCateModel::destroy($id);
+        ajax_return();
+    }
+
+    public function importCate()
+    {
+        return view('public/import', [
+            'url'           => url('article/importCatePost'),
+            'last_table'    => 'lay-article-cate-table',
+            'template_file' => '/static/common/exl/article_cate.xls',
+        ]);
+    }
+
+    public function importCatePost()
+    {
+        $file_url = input('file_url/s', "");
+        if (!file_exists($file_url)) {
+            ajax_return(1, '文件不存在');
+        }
+
+        $data        = ['title', 'priority'];
+        $list        = import_exl($file_url, $data, 1);
+        $empty_check = [
+            'title' => '分类名称',
+        ];
+
+        foreach ($list as $k => $v) {
+            foreach ($empty_check as $key => $value) {
+                if (empty($v[$key])) {
+                    return ajax_return(1, '第' . ($k + 2) . '行的' . $value . '不能为空');
+                }
+            }
+            $list[$k]['priority'] = empty($v['priority']) ? 255 : (int)$v['priority'];
+        }
+
+        ArticleCateModel::insertAll($list);
+        ajax_return(0);
+    }
+
+    public function exportCate()
+    {
+        $map  = $this->dealInInput(['id'],$this->dealEqualInput(['status']));
+        $list = ArticleCateModel::where($map)
+            ->order(['priority' => 'desc', 'id' => 'desc'])
+            ->select();
+
+        $xlsCell = [
+            ['id', '表ID'],
+            ['title', '分类名称'],
+            ['status_text', '状态'],
+            ['priority', '排序'],
+        ];
+        export_exl("文章分类", $xlsCell, $list);
+    }
+}

+ 44 - 0
app/admin/controller/Feedback.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\FeedbackModel;
+
+class Feedback extends AdminBaseController
+{
+
+    /**
+     * 列表
+     */
+    public function index()
+    {
+        return view('',[
+            'status_list' => FeedbackModel::STATUS,
+        ]);
+    }
+
+    public function listFeedback()
+    {
+        $map = $this->dealEqualInput(['status']);
+        $list  = FeedbackModel::with('user')
+            ->where($map)
+            ->order(['status' => 'desc'])
+            ->limit(input('limit'))
+            ->page(input('page'))
+            ->append(['status_text'])
+            ->select();
+        $count = FeedbackModel::where($map)->count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+
+    public function dealFeedback()
+    {
+        $id_arr = input('id_arr/a');
+        FeedbackModel::update(['status' => 1], ['id' => $id_arr]);
+        ajax_return();
+    }
+}

+ 15 - 0
app/admin/controller/Help.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+
+class Help extends AdminBaseController
+{
+
+    public function link()
+    {
+        return view();
+    }
+
+}

+ 71 - 0
app/admin/controller/Home.php

@@ -0,0 +1,71 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\AdminModel;
+use app\common\model\FeedbackModel;
+use app\common\model\MenuModel;
+use app\common\model\UserModel;
+
+class Home extends AdminBaseController
+{
+
+    public function index()
+    {
+        $access_admin = session('access_admin');
+        $admin        = AdminModel::find($access_admin['id']);
+        $where        = [
+            ['mtype', '=', 'admin'],
+            ['status', '=', 1],
+        ];
+        if ($access_admin['id'] != 1) {
+            $where[] = ['id', 'in', $admin->powerids];
+        }
+        $menu_list = MenuModel::where(['mtype' => 'admin', 'status' => 1])
+            ->where($where)
+            ->order(['pid' => 'asc', 'priority' => 'asc', 'id' => 'asc'])
+            ->select()
+            ->toArray();
+        $powerarr  = [];
+        if (!empty($menu_list)) {
+            foreach ($menu_list as $k => $v) {
+                if ($v['pid'] == 0) {
+                    $v['children']      = [];
+                    $powerarr[$v['id']] = $v;
+                } else {
+                    $powerarr[$v['pid']]['children'][] = $v;
+                }
+            }
+        }
+        return view('', [
+            'access_admin' => $access_admin,
+            'powerarr'     => $powerarr,
+        ]);
+    }
+
+    public function console()
+    {
+        //用户统计
+        $user_count              = [];
+        $user_count['today']     = UserModel::whereDay('create_time')->count();
+        $user_count['yesterday'] = UserModel::whereDay('create_time', 'yesterday')->count();
+        $user_count['week']      = UserModel::whereWeek('create_time')->count();
+        $user_count['month']     = UserModel::whereMonth('create_time')->count();
+        $user_count['total']     = UserModel::count();
+
+        //意见反馈
+        $feedback = FeedbackModel::where('status', FeedbackModel::STATUS_UNREAD)
+            ->limit(5)
+            ->order('create_time', 'desc')
+            ->select();
+
+        return view('home/console', [
+            'access_admin' => session('access_admin'),
+            'user_count'   => $user_count,
+            'feedback'     => $feedback,
+        ]);
+    }
+
+
+}

+ 12 - 0
app/admin/controller/Index.php

@@ -0,0 +1,12 @@
+<?php
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+
+class Index extends AdminBaseController
+{
+    public function index()
+    {
+        return redirect('admin/home');
+    }
+}

+ 43 - 0
app/admin/controller/Login.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\common\model\AdminModel;
+
+class Login extends BaseController
+{
+    public function index()
+    {
+        return view('login/login', [
+            'domain' => request()->domain(),
+        ]);
+    }
+
+
+    public function login()
+    {
+        if (!captcha_check(input('vercode'))) {
+            ajax_return(1, '验证码错误。');
+        }
+        $admin = AdminModel::where(['admin_name' => input('admin_name')])->findOrEmpty()->toArray();
+        if (empty($admin) || $admin['password'] != md5(input('password'))) {
+            ajax_return(1, '账号密码不正确。');
+        }
+        if ($admin['status'] == 2) {
+            ajax_return(1, '该管理员账号已被禁言,如有疑问请联系超级管理员。');
+        }
+        AdminModel::update(['last_date' => time(), 'last_ip' => $_SERVER['SERVER_ADDR']], ['id' => $admin['id']]);
+        session('access_admin', $admin);
+
+        ajax_return();
+    }
+
+
+    public function logout()
+    {
+        session(null);
+        return redirect(url('login/index'));
+    }
+
+}

+ 79 - 0
app/admin/controller/Navigation.php

@@ -0,0 +1,79 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\NavigationModel;
+use app\admin\validate\NavigationValidate;
+use think\exception\ValidateException;
+
+class Navigation extends AdminBaseController
+{
+
+    /**
+     * 列表
+     */
+    public function index()
+    {
+        return view('', [
+            'tab_list'    => NavigationModel::TAB,
+            'status_list' => NavigationModel::STATUS,
+        ]);
+    }
+
+    public function listNavigation()
+    {
+        $map   = $this->dealLikeInput(['title'], $this->dealEqualInput(['tab', 'status']));
+        $list  = NavigationModel::where($map)
+            ->limit(input('limit'))
+            ->page(input('page'))
+            ->order('priority', 'desc')
+            ->append(['tab_text', 'status_text'])
+            ->select();
+        $count = NavigationModel::where($map)->count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+
+    public function delNavigation()
+    {
+        $id_arr = input('id_arr/a');
+        NavigationModel::destroy($id_arr);
+        ajax_return();
+    }
+
+    /**
+     * 编辑
+     */
+    public function navigationForm()
+    {
+        $id   = input('id/d, 0');
+        $info = NavigationModel::find($id);
+
+        return view('', [
+            'info'        => $info,
+            'tab_list'    => NavigationModel::TAB,
+            'status_list' => NavigationModel::STATUS,
+        ]);
+    }
+
+    public function editNavigation()
+    {
+        $data = input('post.');
+        try {
+            validate(NavigationValidate::class)->check($data);
+        } catch (ValidateException $e) {
+            ajax_return(1, $e->getError());
+        }
+
+        if (empty($data['id'])) {
+            NavigationModel::create($data);
+        } else {
+            NavigationModel::update($data, ['id' => $data['id']]);
+        }
+
+        ajax_return();
+    }
+}

+ 77 - 0
app/admin/controller/Notice.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\NoticeModel;
+use app\admin\validate\NoticeValidate;
+use think\exception\ValidateException;
+
+class Notice extends AdminBaseController
+{
+
+    /**
+     * 列表
+     */
+    public function index()
+    {
+        return view('', [
+            'status_list' => NoticeModel::STATUS,
+        ]);
+    }
+
+    public function listNotice()
+    {
+        $map   = $this->dealEqualInput(['status']);
+        $list  = NoticeModel::where($map)
+            ->order(['priority' => 'desc', 'update_time' => 'desc'])
+            ->limit(input('limit'))
+            ->page(input('page'))
+            ->append(['status_text'])
+            ->select();
+        $count = NoticeModel::where($map)->count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+
+    public function delNotice()
+    {
+        $id_arr = input('id_arr/a');
+        NoticeModel::destroy($id_arr);
+        ajax_return();
+    }
+
+    /**
+     * 编辑
+     */
+    public function noticeForm()
+    {
+        $id      = input('id/d, 0');
+        $info = NoticeModel::find($id);
+
+        return view('', [
+            'info'     => $info,
+            'status_list' => NoticeModel::STATUS,
+        ]);
+    }
+
+    public function editNotice()
+    {
+        $data = input('post.');
+        try {
+            validate(NoticeValidate::class)->check($data);
+        } catch (ValidateException $e) {
+            ajax_return(1, $e->getError());
+        }
+
+        if (empty($data['id'])) {
+            NoticeModel::create($data);
+        } else {
+            NoticeModel::update($data, ['id' => $data['id']]);
+        }
+
+        ajax_return();
+    }
+}

+ 42 - 0
app/admin/controller/Page.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\SinglePageModel;
+
+class Page extends AdminBaseController
+{
+    public function index()
+    {
+        $data = SinglePageModel::getConfigValue(SinglePageModel::CODE);
+        return view('', [
+            'data'  => $data,
+            'title' => SinglePageModel::CODE_TITLE,
+        ]);
+    }
+
+    public function edit()
+    {
+        $data = $this->_post(SinglePageModel::CODE);
+        SinglePageModel::setConfigValue($data);
+        ajax_return();
+    }
+
+    /**
+     * 获取数据
+     * @param array $param 要获取的数据
+     * @return array
+     */
+    public function _post(array $param)
+    {
+        $res = [];
+        foreach ($param as $v) {
+            if (!empty(input($v))) {
+                $res[$v] = input($v);
+            }
+        }
+
+        return $res;
+    }
+}

+ 63 - 0
app/admin/controller/Setting.php

@@ -0,0 +1,63 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\SettingModel;
+
+class Setting extends AdminBaseController
+{
+    /**
+     * 短信配置
+     */
+    public function sms()
+    {
+        $sms = SettingModel::getConfigValue(SettingModel::SMS);
+        return view('', [
+            'sms' => $sms,
+            'sms_type' => SettingModel::SMS_TYPE,
+        ]);
+    }
+
+    public function editSms()
+    {
+        $data = $this->_post(SettingModel::SMS);
+        SettingModel::setConfigValue($data);
+        ajax_return();
+    }
+
+    /**
+     * 系统配置
+     */
+    public function system()
+    {
+        $system = SettingModel::getConfigValue(SettingModel::SYSTEM);
+        return view('', [
+            'system' => $system,
+        ]);
+    }
+
+    public function editSystem()
+    {
+        $data = $this->_post(SettingModel::SYSTEM);
+        SettingModel::setConfigValue($data);
+        ajax_return();
+    }
+
+    /**
+     * 获取数据
+     * @param array $param 要获取的数据
+     * @return array
+     */
+    public function _post(array $param)
+    {
+        $res = [];
+        foreach ($param as $v) {
+            if (!empty(input($v))) {
+                $res[$v] = input($v);
+            }
+        }
+
+        return $res;
+    }
+}

+ 79 - 0
app/admin/controller/Slide.php

@@ -0,0 +1,79 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\SlideModel;
+use app\admin\validate\SlideValidate;
+use think\exception\ValidateException;
+
+class Slide extends AdminBaseController
+{
+
+    /**
+     * 列表
+     */
+    public function index()
+    {
+        return view('', [
+            'tab_list'    => SlideModel::TAB,
+            'status_list' => SlideModel::STATUS,
+        ]);
+    }
+
+    public function listSlide()
+    {
+        $map   = $this->dealLikeInput(['title'],$this->dealEqualInput(['tab', 'status']));
+        $list  = SlideModel::where($map)
+            ->limit(input('limit'))
+            ->page(input('page'))
+            ->order('priority','desc')
+            ->append(['tab_text', 'status_text'])
+            ->select();
+        $count = SlideModel::where($map)->count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+
+    public function delSlide()
+    {
+        $id_arr = input('id_arr/a');
+        SlideModel::destroy($id_arr);
+        ajax_return();
+    }
+
+    /**
+     * 编辑
+     */
+    public function slideForm()
+    {
+        $id   = input('id/d, 0');
+        $info = SlideModel::find($id);
+
+        return view('', [
+            'info'        => $info,
+            'tab_list'    => SlideModel::TAB,
+            'status_list' => SlideModel::STATUS,
+        ]);
+    }
+
+    public function editSlide()
+    {
+        $data = input('post.');
+        try {
+            validate(SlideValidate::class)->check($data);
+        } catch (ValidateException $e) {
+            ajax_return(1, $e->getError());
+        }
+
+        if (empty($data['id'])) {
+            SlideModel::create($data);
+        } else {
+            SlideModel::update($data, ['id' => $data['id']]);
+        }
+
+        ajax_return();
+    }
+}

+ 77 - 0
app/admin/controller/SmsTemplate.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\admin\validate\SmsTemplateValidate;
+use app\common\model\ArticleModel;
+use app\common\model\ArticleCateModel;
+use app\admin\validate\ArticleCateValidate;
+use app\admin\validate\ArticleValidate;
+use app\common\model\SmsTemplateModel;
+use think\exception\ValidateException;
+
+class SmsTemplate extends AdminBaseController
+{
+    /**
+     * 列表
+     */
+    public function index()
+    {
+        return view();
+    }
+
+    public function templateForm()
+    {
+        $id   = input('id/d, 0');
+        $info = SmsTemplateModel::find($id);
+        return view('', [
+            'info' => $info,
+        ]);
+    }
+
+    public function listTemplate()
+    {
+        $list  = SmsTemplateModel::limit(input('limit'))
+            ->page(input('page'))
+            ->select();
+        $count = SmsTemplateModel::count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+
+    public function delTemplate()
+    {
+        $id = input('id/d', 0);
+        SmsTemplateModel::destroy($id);
+        ajax_return();
+    }
+
+    public function editTemplate()
+    {
+        $data = input('post.');
+        try {
+            validate(SmsTemplateValidate::class)->check($data);
+        } catch (ValidateException $e) {
+            ajax_return(1, $e->getError());
+        }
+
+        if (empty($data['id'])) {
+            $check = SmsTemplateModel::where('code', $data['code'])->find();
+            if (!empty($check)) {
+                ajax_return(1, '该编号已存在');
+            }
+            SmsTemplateModel::create($data);
+        } else {
+            $check = SmsTemplateModel::where('code', $data['code'])->where('id', '<>', $data['id'])->find();
+            if (!empty($check)) {
+                ajax_return(1, '该编号已存在');
+            }
+            SmsTemplateModel::update($data, ['id' => $data['id']]);
+        }
+
+        ajax_return();
+    }
+}

+ 46 - 0
app/admin/controller/Upload.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+
+class Upload extends AdminBaseController
+{
+
+    /**
+     * 文件上传
+     */
+    public function file()
+    {
+        $file     = request()->file("file");
+        $savename = \think\facade\Filesystem::disk('public')->putFile('files', $file);
+        if ($file) {
+            $filename = str_replace(strrchr($_FILES['file']['name'], "."), "", $_FILES['file']['name']);
+            ajax_return(0, '', [
+                'src'   => request()->domain() . "/storage/" . str_replace("\\", "/", $savename),
+                'path'  => "./storage/" . str_replace("\\", "/", $savename),
+                'title' => $filename,
+            ]);
+        } else {
+            ajax_return(1, '上传失败,请稍后重试');
+        }
+    }
+
+    /**
+     * 图片上传
+     */
+    public function image()
+    {
+        $file     = request()->file("file");
+        $savename = \think\facade\Filesystem::disk('public')->putFile('images', $file);
+        if ($file) {
+            $filename = str_replace(strrchr($_FILES['file']['name'], "."), "", $_FILES['file']['name']);
+            ajax_return(0, '', [
+                'src'   => request()->domain() . "/storage/" . str_replace("\\", "/", $savename),
+                'title' => $filename,
+            ]);
+        } else {
+            ajax_return(1, '上传失败,请稍后重试');
+        }
+    }
+}

+ 133 - 0
app/admin/controller/User.php

@@ -0,0 +1,133 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\admin\AdminBaseController;
+use app\common\model\UserFollowModel;
+use app\common\model\UserModel;
+use app\admin\validate\UserValidate;
+use think\exception\ValidateException;
+
+class User extends AdminBaseController
+{
+    /**
+     * 用户列表
+     */
+    public function index()
+    {
+        $gender_list    = UserModel::GENDER;
+        $gender_list[0] = '全部';
+        return view('', [
+            'status_list' => UserModel::STATUS,
+            'gender_list' => $gender_list,
+        ]);
+    }
+
+    public function listUser()
+    {
+        $map   = $this->dealEqualInput(['gender', 'status'], $this->dealLikeInput(['keywords' => 'account|nickname|realname', 'mobile']));
+        $list  = UserModel::where($map)
+            ->order('id', 'desc')
+            ->limit(input('limit'))
+            ->page(input('page'))
+            ->append(['status_text', 'gender_text'])->select();
+        $count = UserModel::where($map)->count();
+        if ($count == 0) {
+            ajax_return(1, '未查询到数据');
+        }
+        list_return($list, $count);
+    }
+
+    /**
+     * 用户跟进记录
+     */
+    public function follow()
+    {
+        $id   = input('id/d');
+        $user = UserModel::find($id);
+        $list = UserFollowModel::where('user_id', $id)->order('id', 'desc')->limit(100)->select();
+        return view('', [
+            'user'      => $user,
+            'list'      => $list,
+            'type_list' => UserFollowModel::TYPE,
+        ]);
+    }
+
+    public function editFollow()
+    {
+        $id   = input('id/d', 0);
+        $user = UserModel::find($id);
+        if (empty($user)) {
+            ajax_return(1, '用户信息不存在。');
+        }
+        UserFollowModel::create([
+            'user_id' => $id,
+            'type'    => input('type/d', 1),
+            'remark'  => input('remark/s', ""),
+        ]);
+        ajax_return();
+    }
+
+    /**
+     * 编辑用户
+     */
+    public function userForm()
+    {
+        $id   = input('id/d', 0);
+        $info = UserModel::find($id);
+        return view('', [
+            'info'        => $info,
+            'gender_list' => UserModel::GENDER,
+            'status_list' => UserModel::STATUS,
+        ]);
+    }
+
+    public function editUser()
+    {
+        $data = input('post.');
+        try {
+            validate(UserValidate::class)->check($data);
+        } catch (ValidateException $e) {
+            ajax_return(1, $e->getError());
+        }
+
+        //用户名
+        $check_account_where = [['account', '=', $data['account']]];
+        if (!empty($data['id'])) {
+            $check_account_where[] = ['id', '<>', $data['id']];
+        }
+        $check_account = UserModel::where($check_account_where)->find();
+        if (!empty($check_account)) {
+            ajax_return(1, '用户名已存在');
+        }
+
+        //手机号
+        $check_mobile_where = [['mobile', '=', $data['mobile']]];
+        if (!empty($data['id'])) {
+            $check_mobile_where[] = ['id', '<>', $data['id']];
+        }
+        $check_mobile = UserModel::where($check_mobile_where)->find();
+        if (!empty($check_mobile)) {
+            ajax_return(1, '手机号已存在');
+        }
+
+        //密码
+        if (empty($data['id']) && empty($data['password'])) {
+            ajax_return(1, '请输入一个初始密码');
+        }
+        if (empty($data['password'])) {
+            unset($data['password']);
+        } else {
+            $data['salt']     = rand_str();
+            $data['password'] = md5(md5($data['salt']) . $data['password']);
+        }
+
+        if (empty($data['id'])) {
+            UserModel::create($data);
+        } else {
+            UserModel::update($data, ['id' => $data['id']]);
+        }
+
+        ajax_return();
+    }
+}

+ 17 - 0
app/admin/event.php

@@ -0,0 +1,17 @@
+<?php
+// 事件定义文件
+return [
+    'bind'      => [
+    ],
+
+    'listen'    => [
+        'AppInit'  => [],
+        'HttpRun'  => [],
+        'HttpEnd'  => [],
+        'LogLevel' => [],
+        'LogWrite' => [],
+    ],
+
+    'subscribe' => [
+    ],
+];

+ 10 - 0
app/admin/middleware.php

@@ -0,0 +1,10 @@
+<?php
+// 全局中间件定义文件
+return [
+    // 全局请求缓存
+    // \think\middleware\CheckRequestCache::class,
+    // 多语言加载
+    // \think\middleware\LoadLangPack::class,
+    // Session初始化
+     \think\middleware\SessionInit::class
+];

+ 9 - 0
app/admin/provider.php

@@ -0,0 +1,9 @@
+<?php
+use app\ExceptionHandle;
+use app\Request;
+
+// 容器Provider定义文件
+return [
+    'think\Request'          => Request::class,
+    'think\exception\Handle' => ExceptionHandle::class,
+];

+ 20 - 0
app/admin/validate/AdminValidate.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace app\admin\validate;
+
+use think\Validate;
+
+class AdminValidate extends Validate
+{
+    protected $rule = [
+        'admin_name' => 'require|unique:admin',
+        'mobile'    => 'mobile',
+    ];
+
+    protected $message = [
+        'admin_name.require' => '登录名不能为空',
+        'admin_name.unique'  => '登录名不能重复',
+        'mobile.mobile'     => '手机号格式不正确',
+    ];
+
+}

+ 20 - 0
app/admin/validate/ArticleCateValidate.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace app\admin\validate;
+
+use think\Validate;
+
+class ArticleCateValidate extends Validate
+{
+    protected $rule = [
+        'title'    => 'require',
+        'priority' => 'require|number',
+    ];
+
+    protected $message = [
+        'title'            => '分类名称不能为空',
+        'priority.require' => '排序不能为空',
+        'priority.number'  => '排序必须是数字',
+    ];
+
+}

+ 25 - 0
app/admin/validate/ArticleValidate.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace app\admin\validate;
+
+use think\Validate;
+
+class ArticleValidate extends Validate
+{
+    protected $rule = [
+        'cate_id'  => 'require',
+        'title'    => 'require',
+        'priority' => 'require|number',
+        'volume'   => 'require|number',
+    ];
+
+    protected $message = [
+        'cate_id'          => '分类不能为空',
+        'title'            => '标题不能为空',
+        'priority.require' => '排序不能为空',
+        'priority.number'  => '排序必须是数字',
+        'volume.require'   => '浏览量不能为空',
+        'volume.number'    => '浏览量必须是数字',
+    ];
+
+}

+ 23 - 0
app/admin/validate/NavigationValidate.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace app\admin\validate;
+
+use think\Validate;
+
+class NavigationValidate extends Validate
+{
+    protected $rule = [
+        'tab'      => 'require',
+        'title'    => 'require',
+        'image'    => 'require',
+        'priority' => 'require',
+    ];
+
+    protected $message = [
+        'tab'      => '位置不能为空',
+        'title'    => '名称不能为空',
+        'image'    => '图标不能为空',
+        'priority' => '排序不能为空',
+    ];
+
+}

+ 21 - 0
app/admin/validate/NoticeValidate.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace app\admin\validate;
+
+use think\Validate;
+
+class NoticeValidate extends Validate
+{
+    protected $rule = [
+        'title'   => 'require',
+        'content' => 'require',
+        'status'  => 'require',
+    ];
+
+    protected $message = [
+        'title'           => '标题不能为空',
+        'content'         => '内容不能为空',
+        'status'          => '请选择状态',
+    ];
+
+}

+ 23 - 0
app/admin/validate/SlideValidate.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace app\admin\validate;
+
+use think\Validate;
+
+class SlideValidate extends Validate
+{
+    protected $rule = [
+        'tab'      => 'require',
+        'title'    => 'require',
+        'image'    => 'require',
+        'priority' => 'require',
+    ];
+
+    protected $message = [
+        'tab'      => '位置不能为空',
+        'title'    => '名称不能为空',
+        'image'    => '图标不能为空',
+        'priority' => '排序不能为空',
+    ];
+
+}

+ 19 - 0
app/admin/validate/SmsTemplateValidate.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace app\admin\validate;
+
+use think\Validate;
+
+class SmsTemplateValidate extends Validate
+{
+    protected $rule = [
+        'code'    => 'require',
+        'content' => 'require',
+    ];
+
+    protected $message = [
+        'code'    => '编号不能为空',
+        'content' => '内容不能为空',
+    ];
+
+}

+ 26 - 0
app/admin/validate/UserValidate.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace app\admin\validate;
+
+use think\Validate;
+
+class UserValidate extends Validate
+{
+    protected $rule = [
+        'account'  => 'require',
+        'nickname' => 'require',
+        'gender'   => 'require',
+        'mobile'   => 'require|mobile',
+        'status'   => 'require',
+    ];
+
+    protected $message = [
+        'account'        => '用户名不能为空',
+        'nickname'       => '昵称不能为空',
+        'gender'         => '请选择性别',
+        'mobile.require' => '手机号不能为空',
+        'mobile.mobile'  => '手机号格式不正确',
+        'status'         => '请选择状态',
+    ];
+
+}

+ 128 - 0
app/admin/view/admin/admin_form.html

@@ -0,0 +1,128 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">后台管理员</div>
+                <div class="layui-card-body" pad15>
+
+
+                    <div class="layui-form layui-form-pane" lay-filter="{$lay_table}">
+                        <input type="hidden" name="id" value="{:array_get($info,'id')}">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>登录名</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="admin_name" value="{:array_get($info,'admin_name')}" lay-verify="required"
+                                       placeholder="请输入登录名"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>登录密码</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="password" value="" placeholder="请输入登录密码,不修改留空"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>姓名</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="realname" value="{:array_get($info,'realname')}" lay-verify="required"
+                                       placeholder="请输入姓名"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">手机号</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="mobile" value="{:array_get($info,'mobile')}" lay-verify="phone"
+                                       placeholder="请输入号码" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">备注</label>
+                            <div class="layui-input-block">
+                                <textarea name="remark" placeholder="请输入备注内容"
+                                          class="layui-textarea">{:array_get($info,'remark')}</textarea>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">角色</label>
+                            <div class="layui-input-block">
+                                <select lay-filter="adminrole" name="role">
+                                    <option value="1" {:array_get($info,'role')===1 ?'selected' : '' }>超级管理员</option>
+                                    <option value="2" {:array_get($info,'role')!==1 ?'selected' : '' }>普通管理员</option>
+                                </select>
+                                <div class="layui-form-mid layui-word-aux">超级管理员,默认具备所有权限,请谨慎设置。</div>
+                            </div>
+                        </div>
+                        <div class="layui-form-item powerarrbox" style="display: {:array_get($info,'role')===1 ? 'none' : 'block' };"
+                             pane>
+                            <label class="layui-form-label">栏目权限</label>
+                            <div class="layui-input-block" id="powerarr"></div>
+                        </div>
+                        <div class="layui-form-item" pane>
+                            <label class="layui-form-label">状态</label>
+                            <div class="layui-input-block">
+                                <input type="checkbox" lay-filter="switch" name="status" {eq name="info.status|default=1" value="1" }checked{/eq} lay-skin="switch" lay-text="正常|禁用" value="1" />
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <input type="button" lay-submit lay-filter="{$lay_btn}"
+                                       value="确认提交" class="layui-btn">
+                            </div>
+                        </div>
+                    </div>
+
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'upload', 'tree'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const tree = layui.tree;
+        form.render();
+
+        form.on('select(adminrole)', function (data) {
+            const val = data.value;
+            if (val == 1) {
+                $(".powerarrbox").css("display", "none");
+            } else {
+                $(".powerarrbox").css("display", "block");
+            }
+        });
+
+        const defpowerarr = {$powerarr|raw|default= "[]"};
+        tree.render({
+            elem: '#powerarr',
+            data: defpowerarr,
+            showCheckbox: true,
+            id: 'powerarr'
+        });
+
+        form.on('submit({$lay_btn})', function (obj) {
+            const checkedData = tree.getChecked('powerarr');
+            obj.field.powerids = getCheckedId(checkedData);
+
+            const index = parent.layer.getFrameIndex(window.name);
+            admin.req({
+                url: "{:url('admin/editAdmin')}",
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {
+                        icon: 1
+                    });
+                    parent.layui.table.reload('lay-admin-index-table'); //重载表格
+                    parent.layer.close(index);
+                }
+            });
+        });
+    });
+</script>

+ 187 - 0
app/admin/view/admin/index.html

@@ -0,0 +1,187 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-form-pane layui-card-header layuiadmin-card-header-auto">
+            <div class="layui-form-item">
+                <div class="layui-inline">
+                    <label class="layui-form-label">登录名</label>
+                    <div class="layui-input-block">
+                        <input type="text" name="admin_name" placeholder="请输入" autocomplete="off" class="layui-input">
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">姓名</label>
+                    <div class="layui-input-block">
+                        <input type="text" name="realname" placeholder="请输入" autocomplete="off" class="layui-input">
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">手机</label>
+                    <div class="layui-input-block">
+                        <input type="text" name="mobile" placeholder="请输入" autocomplete="off" class="layui-input">
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">角色</label>
+                    <div class="layui-input-block">
+                        <select name="role">
+                            <option value="">全部管理员</option>
+                            {volist name="role_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">
+                        <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
+                    </button>
+                </div>
+            </div>
+        </div>
+
+        <div class="layui-card-body">
+            <div style="padding-bottom: 10px;">
+                <button class="layui-btn layuiadmin-btn layui-btn-danger" data-type="del">删除</button>
+                <button class="layui-btn layuiadmin-btn" data-type="add">添加</button>
+            </div>
+
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="setTpl">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i
+                        class="layui-icon layui-icon-edit"></i>编辑</a>
+                {{#  if(d.id == 1){ }}
+                <a class="layui-btn layui-btn-disabled layui-btn-xs"><i class="layui-icon layui-icon-delete"></i>删除</a>
+                {{#  } else { }}
+                <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i
+                        class="layui-icon layui-icon-delete"></i>删除</a>
+                {{#  } }}
+            </script>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'table'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('admin/listAdmin')}",
+            cols: [
+                [
+                    {type: 'checkbox', fixed: 'left'},
+                    {field: 'id', width: 100, title: '表ID', sort: true},
+                    {field: 'admin_name', title: '登录名'},
+                    {field: 'realname', title: '姓名'},
+                    {field: 'mobile', title: '手机号'},
+                    {field: 'role_text', title: '角色'},
+                    {field: 'last_date', title: '最近登录时间', width: 170, sort: true},
+                    {field: 'status_text', title: '状态', templet: '#statusTpl', minWidth: 80, align: 'center'},
+                    {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#setTpl'}
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        form.on('submit({$lay_btn})', function (data) {
+            table.reload('{$lay_table}', {
+                where: data.field,
+                page: {
+                    curr: 1
+                }
+            });
+        });
+
+        const active = {
+            del: function () {
+                const check_data = table.checkStatus('{$lay_table}').data;
+                if (check_data.length === 0) {
+                    return layer.msg('请选择数据');
+                }
+                let id_arr = [];
+                for (let i = 0; i < check_data.length; i++) {
+                    id_arr.push(check_data[i].id);
+                }
+                layer.prompt({
+                    formType: 1,
+                    title: '敏感操作,请验证密码'
+                }, function (value, index) {
+                    layer.close(index);
+                    layer.confirm('确定删除此管理员吗?', function (index) {
+                        admin.req({
+                            url: "{:url('admin/delAdmin')}",
+                            data: {
+                                password: value,
+                                id_arr: id_arr
+                            },
+                            done: function (res) {
+                                obj.del();
+                                layer.msg('已删除');
+                            }
+                        });
+                        table.reload('{$lay_table}');
+                        layer.msg('已删除');
+                    });
+                });
+            },
+            add: function () {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加管理员',
+                    content: "{:url('admin/adminForm')}",
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        };
+
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'del') {
+                layer.prompt({
+                    formType: 1,
+                    title: '敏感操作,请验证密码'
+                }, function (value, index) {
+                    layer.close(index);
+                    layer.confirm('确定删除此管理员吗?', function (index) {
+                        admin.req({
+                            url: "{:url('admin/delAdmin')}",
+                            data: {
+                                password: value,
+                                id_arr: [data.id]
+                            },
+                            done: function (res) {
+                                obj.del();
+                                layer.msg('已删除');
+                            }
+                        });
+                        layer.close(index);
+                    });
+                });
+            } else if (obj.event === 'edit') {
+                const index = layer.open({
+                    type: 2,
+                    title: '编辑管理员',
+                    content: "{:url('admin/adminForm')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+
+    });
+</script>

+ 79 - 0
app/admin/view/admin/my_info.html

@@ -0,0 +1,79 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">我的资料</div>
+                <div class="layui-card-body" pad15>
+
+                    <div class="layui-form layui-form-pane" lay-filter="{$lay_table}">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">我的角色</label>
+                            <div class="layui-input-inline">
+                                <input type="text" name="admin_name" value="{:array_get($admin,'role_text')}" readonly
+                                       class="layui-input">
+                            </div>
+                            <div class="layui-form-mid layui-word-aux">当前角色不可更改为其它角色</div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">登录名</label>
+                            <div class="layui-input-inline">
+                                <input type="text" name="admin_name" value="{:array_get($admin,'admin_name')}" readonly
+                                       class="layui-input">
+                            </div>
+                            <div class="layui-form-mid layui-word-aux">不可修改,用于后台登录名</div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>姓名</label>
+                            <div class="layui-input-inline">
+                                <input type="text" name="realname" value="{:array_get($admin,'realname')}" lay-verify="required"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">手机号</label>
+                            <div class="layui-input-inline">
+                                <input type="text" name="mobile" value="{:array_get($admin,'mobile')}" lay-verify="phone"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item" pane>
+                            <label class="layui-form-label">备注</label>
+                            <div class="layui-input-block">
+                                <textarea name="remark" placeholder="请输入内容"
+                                          class="layui-textarea">{:array_get($admin,'remark')}</textarea>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">确认修改
+                                </button>
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index'], function () {
+        const admin = layui.admin;
+        const form = layui.form;
+        form.render();
+
+        form.on('submit({$lay_btn})', function (obj) {
+            admin.req({
+                url: "{:url('admin/editmyinfo')}",
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {
+                        icon: 1
+                    });
+                }
+            });
+
+        });
+    });
+</script>

+ 64 - 0
app/admin/view/admin/my_password.html

@@ -0,0 +1,64 @@
+<div class="layui-fluid">
+	<div class="layui-row layui-col-space15">
+		<div class="layui-col-md12">
+			<div class="layui-card">
+				<div class="layui-card-header">修改密码</div>
+				<div class="layui-card-body" pad15>
+
+					<div class="layui-form layui-form-pane" lay-filter="LAY-admin-mypassword-form">
+						<div class="layui-form-item">
+							<label class="layui-form-label">当前密码</label>
+							<div class="layui-input-inline">
+								<input type="password" name="oldpassword" lay-verify="required" lay-verType="tips" class="layui-input">
+							</div>
+						</div>
+						<div class="layui-form-item">
+							<label class="layui-form-label">新密码</label>
+							<div class="layui-input-inline">
+								<input type="password" name="password" lay-verify="pass" lay-verType="tips" autocomplete="off" id="LAY_password"
+								 class="layui-input">
+							</div>
+							<div class="layui-form-mid layui-word-aux">6到16个字符</div>
+						</div>
+						<div class="layui-form-item">
+							<label class="layui-form-label">确认新密码</label>
+							<div class="layui-input-inline">
+								<input type="password" name="repassword" lay-verify="repass" lay-verType="tips" autocomplete="off" class="layui-input">
+							</div>
+						</div>
+						<div class="layui-form-item">
+							<div class="layui-input-block">
+								<button class="layui-btn" lay-submit lay-filter="LAY-admin-mypassword-form-submit">确认修改</button>
+							</div>
+						</div>
+					</div>
+
+				</div>
+			</div>
+		</div>
+	</div>
+</div>
+
+<script>
+	layui.use(['index'], function() {
+		const admin = layui.admin;
+		const form = layui.form;
+		form.render();
+
+		form.on('submit(LAY-admin-mypassword-form-submit)', function(obj) {
+			admin.req({
+				url: "{:url('admin/editmypassword')}",
+				data: obj.field,
+				done: function(res) {
+					layer.msg('密码修改成功,请重新登录。', {
+						icon: 1,
+						time: 1000
+					}, function() {
+						top.location.href = "{:url('login/index')}";
+					});
+				}
+			});
+
+		});
+	});
+</script>

+ 213 - 0
app/admin/view/article/article_form.html

@@ -0,0 +1,213 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">文章资讯信息</div>
+                <div class="layui-card-body" pad15>
+                    <div class="layui-form layui-form-pane" lay-filter="{$lay_table}">
+                        <input type="hidden" name="id" value="{:array_get($info,'id')}">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>分类</label>
+                            <div class="layui-input-block">
+                                <select name="cate_id">
+                                    {volist name="cate_list" id="vo"}
+                                    <option value="{$vo.id}" {:array_get($info,'cate_id')==$vo.id ? 'selected' : '' }>{$vo.title}</option>
+                                    {/volist}
+                                </select>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>标题</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="title" value="{:array_get($info,'title')}" lay-verify="required"
+                                       placeholder="请输入标题" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">头图</label>
+                            <div class="layui-input-block">
+                                <div class="layui-upload">
+                                    <button type="button" class="layui-btn attachment-upload-images"
+                                            data-input="header_image" data-amount="1">上传图片
+                                    </button>
+                                    <div class="layui-inline layui-word-aux"> 最佳尺寸:110px*85px</div>
+                                    <div class="layui-upload-list echo-attachment-image-list" id="header_image">
+                                        {notempty name="info.header_image"}
+                                        <div>
+                                            <input type="hidden" name="header_image" value="{:array_get($info,'header_image')}">
+                                            <img src="{:array_get($info,'header_image')}">
+                                        </div>
+                                        {/notempty}
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">作者</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="author" value="{:array_get($info,'author')}" placeholder="请输入作者"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">概要</label>
+                            <div class="layui-input-block">
+                                <textarea name="summary" placeholder="请输入概要" class="layui-textarea">{:array_get($info,'summary')}</textarea>
+                            </div>
+                        </div>
+                        <div class="layui-form-item" pane>
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>类型</label>
+                            <div class="layui-input-block">
+                                {volist name="type_list" id="v"}
+                                <input type="radio" name="type" lay-filter="type" value="{$key}" title="{$v}" {eq name=":array_get($info,'type',1)" value="$key" }checked{/eq}>
+                                {/volist}
+                            </div>
+                        </div>
+                        <div class="layui-form-item" id="form-content">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>详情</label>
+                            <div class="layui-input-block">
+                                <script id="editor" type="text/plain">{:array_get($info,'content')}</script>
+                            </div>
+                        </div>
+                        <div class="layui-form-item" id="form-url">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>跳转链接</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="url" value="{:array_get($info,'url')}" placeholder="请输入跳转链接"
+                                       autocomplete="off" class="layui-input">
+                                <div class="layui-form-mid layui-word-aux">
+                                    <b>链接:</b>url链接,以“http://”或“https://”开头。
+                                </div>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>排序</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="priority" value="{:array_get($info,'priority',255)}"
+                                       lay-verify="required|number" placeholder="请输入排序"
+                                       autocomplete="off" class="layui-input">
+                                <div class="layui-form-mid layui-word-aux">倒序,值越大越靠前</div>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>状态</label>
+                            <div class="layui-input-block">
+                                {volist name="status_list" id="v"}
+                                <input type="radio" name="status" value="{$key}" title="{$v}" {eq name=":array_get($info,'status',1)" value="$key" }checked{/eq}>
+                                {/volist}
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>浏览量</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="volume" value="{:array_get($info,'volume',0)}"
+                                       lay-verify="required|number" placeholder="请输入浏览量"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <input type="button" lay-submit lay-filter="{$lay_btn}" value="确认提交" class="layui-btn">
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+{include file="public/ueditor" /}
+<script>
+    layui.use(['index', 'form', 'layedit', 'upload'], function () {
+        UE.getEditor('editor');
+        const $ = layui.$;
+        const admin = layui.admin;
+        const layedit = layui.layedit;
+        const form = layui.form;
+        const upload = layui.upload;
+        form.render();
+
+        const content = layedit.build('content', {
+            uploadImage: { url: "{:url('upload/image')}", type: 'post' }
+        });
+
+        form.verify({
+            editcontent: function (value) {
+                layedit.sync(content);
+            }
+        });
+
+        function typeChange(value) {
+            if (value == 1) {
+                $("#form-content").show();
+                $("#form-url").hide();
+            } else {
+                $("#form-content").hide();
+                $("#form-url").show();
+            }
+            ;
+        }
+        typeChange("{:array_get($info,'type',1)}");
+        form.on('radio(type)', function (data) {
+            typeChange(data.value);
+        });
+
+        form.on('submit({$lay_btn})', function (obj) {
+            const index = parent.layer.getFrameIndex(window.name);
+            obj.field.content = UE.getEditor('editor').getContent();
+            admin.req({
+                url: "{:url('article/editArticle')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {
+                        icon: 1
+                    });
+                    parent.layui.table.reload('lay-article-index-table'); //重载表格
+                    parent.layer.close(index);
+                }
+            });
+        });
+
+
+        $('.echo-attachment-image-list').on('click', '.attachment-del', function () {
+            $(this).parent().remove();
+        });
+
+        let upload_input = '';
+        let upload_amount = '';
+        upload.render({
+            elem: '.attachment-upload-images',
+            url: "{:url('upload/image')}",
+            accept: 'images',
+            exits: 'jpg|png|jpeg',
+            acceptMime: 'image/*',
+            size: 2048,
+            number: 1,
+            method: 'post',
+            before: function (obj) {
+                upload_input = $(this.item).data('input');
+                upload_amount = $(this.item).data('amount');
+                layer.load();
+            },
+            done: function (res, index, upload) {
+                layer.closeAll('loading');
+                let html = "";
+                if (upload_amount == 1) {
+                    html += '<div> <input type="hidden" name="' + upload_input + '" value="' + res.data.src + '"> ';
+                    html += '<img src="' + res.data.src + '"></div>';
+                    $("#" + upload_input).html(html);
+                } else {
+                    html += '<div> <input type="hidden" name="' + upload_input + '[]" value="' + res.data.src + '"> ';
+                    html += '<img src="' + res.data.src +
+                        '"> <button type="button" class="attachment-del layui-btn layui-btn-primary layui-btn-xs layui-btn-fluid">删除</button></div>';
+                    $("#" + upload_input).append(html);
+                }
+            },
+            error: function (index, upload) {
+                layer.closeAll('loading');
+            }
+        });
+
+    });
+</script>

+ 173 - 0
app/admin/view/article/cate.html

@@ -0,0 +1,173 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-form-pane layui-card-header layuiadmin-card-header-auto">
+            <div class="layui-inline">
+                <label class="layui-form-label">状态</label>
+                <div class="layui-input-block">
+                    <select name="status">
+                        <option value="">全部状态</option>
+                        {volist name="status_list" id="v"}
+                        <option value="{$key}">{$v}</option>
+                        {/volist}
+                    </select>
+                </div>
+            </div>
+            <div class="layui-inline">
+                <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">
+                    <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
+                </button>
+            </div>
+        </div>
+        <div class="layui-form layui-card-header layuiadmin-card-header-auto">
+            <button class="layui-btn layuiadmin-btn" data-type="add">添加</button>
+            <button class="layui-btn layuiadmin-btn" data-type="import">批量导入</button>
+            <button class="layui-btn layuiadmin-btn" data-type="export">导出</button>
+        </div>
+
+        <div class="layui-card-body">
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="setTpl">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i
+                        class="layui-icon layui-icon-edit"></i>编辑</a>
+                <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i
+                        class="layui-icon layui-icon-delete"></i>删除</a>
+            </script>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'table'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        let search_param = {};
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('article/listCate')}",
+            cols: [
+                [
+                    {type: 'checkbox', fixed: 'left'},
+                    {field: 'id', width: 80,title: '分类ID'},
+                    {field: 'priority', width: 80, title: '排序', sort: true, edit: 'text'},
+                    {field: 'title', title: '分类名称', edit: 'text'},
+                    {field: 'status_text', title: '状态', minWidth: 80, align: 'center'},
+                    {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#setTpl'}
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        //监听搜索
+        form.on('submit({$lay_btn})', function (data) {
+            search_param = data.field;
+            console.log(search_param);
+            table.reload('{$lay_table}', {
+                where: data.field,
+                page: {
+                    curr: 1
+                }
+            });
+        });
+
+        //事件
+        const active = {
+            add: function () {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加分类',
+                    content: "{:url('article/cateForm')}",
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            },
+            import: function() {
+                layer.open({
+                    type: 2,
+                    title: '批量导入',
+                    content: "{:url('article/importCate')}",
+                    maxmin: true,
+                    area: ['750px', '300px']
+                });
+            },
+            export: function() {
+                const check_data = table.checkStatus('{$lay_table}').data;
+                const url = "{:url('article/exportCate')}";
+                if (check_data.length === 0) {
+                    let param = '';
+                    for (let item in search_param) {
+                        param += '&' + item + '=' + search_param[item];
+                    }
+                    if (param === '') {
+                        window.open(url);
+                    } else {
+                        window.open(url + '?' + param.slice(1));
+                    }
+                } else {
+                    let id_arr = [];
+                    for (let i = 0; i < check_data.length; i++) {
+                        id_arr.push(check_data[i].id);
+                    }
+
+                    window.open(url + '?id=' + id_arr.join());
+                }
+            },
+        };
+
+        //监听单元格编辑
+        table.on('edit({$lay_table})', function (obj) {
+            const id = obj.data.id;
+            const field = obj.field;
+            const value = obj.value;
+            admin.req({
+                url: "{:url('article/fieldCate')}",
+                data: {id: id, field: field, value: value},
+                done: function (res) {
+                    layer.msg('修改成功');
+                    layui.table.reload('{$lay_table}');
+                }
+            });
+        });
+
+        //监听工具条
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'del') {
+                layer.confirm('确定删除此分类吗?', function (index) {
+                    admin.req({
+                        url: "{:url('article/delCate')}",
+                        data: {
+                            id: data.id
+                        },
+                        done: function (res) {
+                            obj.del();
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            } else if (obj.event === 'edit') {
+                const index = layer.open({
+                    type: 2,
+                    title: '编辑分类',
+                    content: "{:url('article/cateForm')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+    });
+</script>

+ 69 - 0
app/admin/view/article/cate_form.html

@@ -0,0 +1,69 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">分类信息</div>
+                <div class="layui-card-body" pad15>
+                    <div class="layui-form layui-form-pane" lay-filter="{$lay_table}">
+                        <input type="hidden" name="id" value="{:array_get($info,'id')}">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>分类名称</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="title" value="{:array_get($info,'title')}" lay-verify="required"
+                                       placeholder="请输入分类名称" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>排序</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="priority" value="{:array_get($info,'priority',255)}"
+                                       lay-verify="required" placeholder="请输入排序值(倒序,值越大越靠前)"
+                                       autocomplete="off" class="layui-input">
+                                <div class="layui-form-mid layui-word-aux">倒序,值越大越靠前</div>
+                            </div>
+                        </div>
+                        <div class="layui-form-item" pane>
+                            <label class="layui-form-label">状态</label>
+                            <div class="layui-input-block">
+                                {volist name="status_list" id="v"}
+                                <input type="radio" name="status" value="{$key}" title="{$v}" {eq name=":array_get($info,'status',1)" value="$key" }checked{/eq}>
+                                {/volist}
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <input type="button" lay-submit lay-filter="{$lay_btn}" value="确认提交" class="layui-btn">
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form'], function () {
+        const admin = layui.admin;
+        const form = layui.form;
+        form.render();
+
+        form.on('submit({$lay_btn})', function (obj) {
+            const index = parent.layer.getFrameIndex(window.name);
+            admin.req({
+                url: "{:url('article/editCate')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {
+                        icon: 1
+                    });
+                    parent.layui.table.reload('lay-article-cate-table'); //重载表格
+                    parent.layer.close(index);
+                }
+            });
+        });
+    });
+</script>

+ 203 - 0
app/admin/view/article/index.html

@@ -0,0 +1,203 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-form-pane layui-card-header layuiadmin-card-header-auto">
+            <div class="layui-form-item">
+                <div class="layui-inline">
+                    <label class="layui-form-label">标题</label>
+                    <div class="layui-input-block">
+                        <input type="text" name="title" placeholder="请输入" autocomplete="off" class="layui-input">
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">分类</label>
+                    <div class="layui-input-block">
+                        <select name="cate_id">
+                            <option value="">全部分类</option>
+                            {volist name="cate_list" id="vo"}
+                            <option value="{$vo['id']}">{$vo['title']}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">类型</label>
+                    <div class="layui-input-block">
+                        <select name="type">
+                            <option value="">全部类型</option>
+                            {volist name="type_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">状态</label>
+                    <div class="layui-input-block">
+                        <select name="status">
+                            <option value="">全部状态</option>
+                            {volist name="status_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">
+                        <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
+                    </button>
+                </div>
+            </div>
+        </div>
+
+        <div class="layui-card-body">
+            <div style="padding-bottom: 10px;">
+                <button class="layui-btn layuiadmin-btn layui-btn-danger" data-type="del">删除</button>
+                <button class="layui-btn layuiadmin-btn" data-type="add">添加</button>
+            </div>
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="cateidTpl">
+                {{d.cate.title}}
+            </script>
+            <script type="text/html" id="setTpl">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">
+                    <i class="layui-icon layui-icon-edit"></i>编辑
+                </a>
+                <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">
+                    <i class="layui-icon layui-icon-delete"></i>删除
+                </a>
+            </script>
+        </div>
+
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'table'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        //列表
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('article/listArticle')}",
+            cols: [
+                [
+                    {type: 'checkbox', fixed: 'left'},
+                    {field: 'id', width: 80, title: '表ID', sort: true},
+                    {field: 'cate_id', width: 100, title: '分类', templet: '#cateidTpl'},
+                    {field: 'title', title: '标题', edit: 'text'},
+                    {field: 'type_text', width: 100, title: '类型'},
+                    {field: 'create_time', width: 160, title: '发布时间', sort: true},
+                    {field: 'volume', width: 90, title: '浏览量', sort: true},
+                    {field: 'status_text', width: 90, title: '状态', minWidth: 80, align: 'center'},
+                    {field: 'priority', width: 80, title: '排序'},
+                    {title: '操作', width: 160, align: 'center', fixed: 'right', toolbar: '#setTpl'}
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        //监听搜索
+        form.on('submit({$lay_btn})', function (data) {
+            table.reload('{$lay_table}', {
+                where: data.field,
+                page: {
+                    curr: 1
+                }
+            });
+        });
+
+        //监听单元格编辑
+        table.on('edit({$lay_table})', function (obj) {
+            const id = obj.data.id;
+            const field = obj.field;
+            const value = obj.value;
+            admin.req({
+                url: "{:url('article/fieldArticle')}",
+                data: {id: id, field: field, value: value},
+                done: function (res) {
+                    layer.msg('修改成功');
+                    layui.table.reload('{$lay_table}');
+                }
+            });
+        });
+
+        //事件
+        const active = {
+            del: function () {
+                const check_status = table.checkStatus('{$lay_table}');
+                const check_data = check_status.data; //得到选中的数据
+                if (check_data.length === 0) {
+                    return layer.msg('请选择数据');
+                }
+                let id_arr = [];
+                for (let i = 0; i < check_data.length; i++) {
+                    id_arr.push(check_data[i].id);
+                }
+                layer.confirm('确定删除所选文章资讯吗?', function (index) {
+                    admin.req({
+                        url: "{:url('article/delArticle')}",
+                        data: {
+                            id_arr: id_arr
+                        },
+                        done: function (res) {
+                            table.reload('{$lay_table}');
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            },
+            add: function () {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加文章资讯',
+                    content: "{:url('article/articleForm')}",
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        };
+
+        //监听工具条
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'del') {
+                layer.confirm('确定删除此文章资讯吗?', function (index) {
+                    admin.req({
+                        url: "{:url('article/delArticle')}",
+                        data: {
+                            id_arr: [data.id]
+                        },
+                        done: function (res) {
+                            obj.del();
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            } else if (obj.event === 'edit') {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加文章资讯',
+                    content: "{:url('article/articleForm')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+    });
+</script>

+ 126 - 0
app/admin/view/feedback/index.html

@@ -0,0 +1,126 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-form-pane  layui-card-header layuiadmin-card-header-auto">
+            <div class="layui-form-item">
+                <div class="layui-inline">
+                    <label class="layui-form-label">状态</label>
+                    <div class="layui-input-block">
+                        <select name="status">
+                            <option value="">全部状态</option>
+                            {volist name="status_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">
+                        <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
+                    </button>
+                </div>
+            </div>
+        </div>
+        <div class="layui-form layui-card-header layuiadmin-card-header-auto">
+            <button class="layui-btn layuiadmin-btn" data-type="deal">标记已处理</button>
+        </div>
+
+        <div class="layui-card-body">
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="setTpl">
+                {{# if(d.status == 2){ }}
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="deal">
+                    <i class="layui-icon layui-icon-edit"></i>标记已处理
+                </a>
+                {{# } }}
+            </script>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'admin', 'form', 'table'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('feedback/listFeedback')}",
+            cols: [
+                [
+                    {type: 'checkbox', fixed: 'left'},
+                    {field: 'name', title: '姓名', width: 100},
+                    {field: 'mobile', title: '联系方式', width: 160},
+                    {field: 'content', title: '内容'},
+                    {field: 'status_text', title: '状态', width: 80, align: 'center'},
+                    {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#setTpl'}
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        form.on('submit({$lay_btn})', function (data) {
+            table.reload('{$lay_table}', {
+                where: data.field,
+                page: {
+                    curr: 1
+                }
+            });
+        });
+
+        //事件
+        const active = {
+            deal: function () {
+                const check_data = table.checkStatus('{$lay_table}').data; //得到选中的数据
+                if (check_data.length === 0) {
+                    return layer.msg('请选择数据');
+                }
+                const id_arr = [];
+                for (let i = 0; i < check_data.length; i++) {
+                    id_arr.push(check_data[i].id);
+                }
+                layer.confirm('确定标记为已处理吗?', function (index) {
+                    admin.req({
+                        url: "{:url('feedback/dealFeedback')}",
+                        data: {
+                            id_arr: id_arr
+                        },
+                        done: function (res) {
+                            table.reload('{$lay_table}');
+                        }
+                    });
+                    layer.close(index);
+                });
+            }
+        };
+
+        //监听工具条
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'deal') {
+                layer.confirm('确定标记为已处理吗?', function (index) {
+                    admin.req({
+                        url: "{:url('feedback/dealFeedback')}",
+                        data: {
+                            id_arr: data.id
+                        },
+                        done: function (res) {
+                            layui.table.reload('{$lay_table}');
+                        }
+                    });
+                    layer.close(index);
+                });
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+    });
+</script>

+ 80 - 0
app/admin/view/help/link.html

@@ -0,0 +1,80 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+
+            <div class="layui-card layui-tab  layui-tab-brief" lay-filter="linktab">
+                <ul class="layui-tab-title">
+                    <li class="layui-this">系统</li>
+                    <li>文章</li>
+                </ul>
+                <div class="layui-tab-content">
+                    <div class="layui-tab-item layui-show">
+                        <table class="layui-table">
+                            <colgroup>
+                                <col width="200">
+                                <col>
+                                <col width="200">
+                                <col>
+                            </colgroup>
+                            <thead>
+                            <tr>
+                                <th>名称</th>
+                                <th>链接(点击复制)</th>
+                                <th>名称</th>
+                                <th>链接(点击复制)</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+                            <tr>
+                                <td>首页</td>
+                                <td onclick="JavaScript:copyMobileUrl('{:url("/")}');"> {:url("/")}</td>
+                                <td>个人中心</td>
+                                <td onclick="JavaScript:copyMobileUrl('{:url("/mobile/my/index")}');"> {:url("/mobile/my/index")}</td>
+                            </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                    <div class="layui-tab-item">
+                        <table class="layui-table">
+                            <colgroup>
+                                <col width="200">
+                                <col>
+                                <col width="200">
+                                <col>
+                            </colgroup>
+                            <thead>
+                            <tr>
+                                <th>名称</th>
+                                <th>链接(点击复制)</th>
+                                <th>名称</th>
+                                <th>链接(点击复制)</th>
+                            </tr>
+                            </thead>
+                            <tbody>
+                            <tr>
+                                <td>文章列表</td>
+                                <td onclick="JavaScript:copyMobileUrl('{:url("/mobile/article/index")}?cate_id=');">{:url("/mobile/article/index")}?cate_id=[id]</td>
+                                <td>资讯分类</td>
+                                <td onclick="JavaScript:copyMobileUrl('{:url("/mobile/article/detail")}?id=');">{:url("/mobile/article/detail")}?id=[id]</td>
+                            </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>
+
+<script src="__COMMON_JS__/copyUrl.js"></script>
+
+<script>
+    function copyMobileUrl(url) {
+        CopyToClipboard(url);
+    }
+
+    layui.use(['index'], function () {
+
+    });
+</script>

+ 177 - 0
app/admin/view/home/console.html

@@ -0,0 +1,177 @@
+<div class="layui-fluid">
+	<div class="layui-row layui-col-space15">
+		<div class="layui-col-md4">
+			<div class="layui-card">
+				<div class="layui-card-header">
+					今日新增用户
+					<span class="layui-badge layui-bg-blue layuiadmin-badge">日</span>
+				</div>
+				<div class="layui-card-body layuiadmin-card-list">
+					<p class="layuiadmin-big-font">{$user_count['today']}</p>
+					<p>
+						昨日
+						<span class="layuiadmin-span-color">{$user_count['yesterday']}<i class="layui-inline layui-icon layui-icon-user"></i></span>
+					</p>
+				</div>
+			</div>
+		</div>
+		<div class="layui-col-md4">
+			<div class="layui-card">
+				<div class="layui-card-header">
+					本周新增用户
+					<span class="layui-badge layui-bg-blue layuiadmin-badge">周</span>
+				</div>
+				<div class="layui-card-body layuiadmin-card-list">
+					<p class="layuiadmin-big-font">{$user_count['week']}</p>
+					<p>
+						本月
+						<span class="layuiadmin-span-color">{$user_count['month']} <i class="layui-inline layui-icon layui-icon-user"></i></span>
+					</p>
+				</div>
+			</div>
+		</div>
+		<div class="layui-col-md4">
+			<div class="layui-card">
+				<div class="layui-card-header">
+					用户总数
+					<span class="layui-badge layui-bg-green layuiadmin-badge">总</span>
+				</div>
+				<div class="layui-card-body layuiadmin-card-list">
+					<p class="layuiadmin-big-font">{$user_count['total']}</p>
+					<p>
+						当前时间
+						<span class="layuiadmin-span-color">{:date('Y-m-d H:i:s')} <i class="layui-inline layui-icon layui-icon-time"></i></span>
+					</p>
+				</div>
+			</div>
+		</div>
+		<div class="layui-col-md6">
+			<div class="layui-card">
+				<div class="layui-card-header">意见反馈</div>
+				<div class="layui-card-body">
+					<ul class="layuiadmin-card-status layuiadmin-home2-usernote">
+						{if condition="$feedback->isEmpty()"}
+							<li>
+								<h3>暂无更多数据</h3>
+								<p>所有意见反馈均已处理</p>
+							</li>
+						{else/}
+							{volist name="feedback" id="v"}
+								<li>
+									<h3>{$v.name}</h3>
+									<p>{$v.content}</p>
+									<span>{$v.create_time}</span>
+									<a href="javascript:;" data-id="{$v.id}" class="layui-btn layui-btn-xs layuiadmin-reply deal-feedback">标记为已读</a>
+								</li>
+							{/volist}
+						{/if}
+					</ul>
+				</div>
+			</div>
+		</div>
+		<div class="layui-col-md6">
+			<div class="layui-card">
+				<div class="layui-card-header">系统信息</div>
+				<div class="layui-card-body layui-text">
+					<table class="layui-table">
+						<colgroup>
+							<col width="150" height="120">
+							<col>
+						</colgroup>
+						<tbody>
+						<tr>
+							<td>上次登录时间</td>
+							<td>{$access_admin['last_date']}</td>
+						</tr>
+						<tr>
+							<td>上次登录IP地址</td>
+							<td>{$access_admin['last_ip']}</td>
+						</tr>
+						<tr>
+							<td>当前系统域名</td>
+							<td>{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['HTTP_HOST']}</td>
+						</tr>
+						<tr>
+							<td>运行环境</td>
+							<td>{$_SERVER["SERVER_SOFTWARE"]}</td>
+						</tr>
+						</tbody>
+					</table>
+				</div>
+			</div>
+		</div>
+		<!--<div class="layui-col-md6">
+			<div class="layui-card">
+				<div class="layui-card-header">
+					最近更新
+				</div>
+				<div class="layui-card-body">
+					<div class="layui-row layui-col-space10">
+						<div class="layui-col-xs12 layui-col-sm4">
+							<div class="layuiadmin-card-text">
+								<div class="layui-text-top"><i class="layui-icon layui-icon-water"></i><a lay-href="https://www.layui.com/doc/modules/flow.html">flow</a></div>
+								<p class="layui-text-center">修复开启 isLazyimg:true 后, 图片懒加载但是图片不存在的报错问题</p>
+								<p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/flow.html">流加载</a><span>7 天前</span></p>
+							</div>
+						</div>
+						<div class="layui-col-xs12 layui-col-sm4">
+							<div class="layuiadmin-card-text">
+								<div class="layui-text-top"><i class="layui-icon layui-icon-upload-circle"></i><a lay-href="https://www.layui.com/doc/modules/upload.html">upload</a></div>
+								<p class="layui-text-center">修复开启 size 参数后,文件超出规定大小时,提示信息有误的问题</p>
+								<p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/upload.html">文件上传</a><span>7 天前</span></p>
+							</div>
+						</div>
+						<div class="layui-col-xs12 layui-col-sm4">
+							<div class="layuiadmin-card-text">
+								<div class="layui-text-top"><i class="layui-icon layui-icon-form"></i><a lay-href="https://www.layui.com/doc/modules/form.html#val">form</a></div>
+								<p class="layui-text-center">增加 form.val(filter, fields)方法,用于给指定表单集合的元素初始赋值</p>
+								<p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/form.html">表单</a><span>7 天前</span></p>
+							</div>
+						</div>
+						<div class="layui-col-xs12 layui-col-sm4">
+							<div class="layuiadmin-card-text">
+								<div class="layui-text-top"><i class="layui-icon layui-icon-form"></i><a lay-href="https://www.layui.com/doc/modules/form.html">form</a></div>
+								<p class="layui-text-center">对 select 组件新增上下键(↑ ↓)回车键(Enter)选择功能</p>
+								<p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/form.html">表单</a><span>7 天前</span></p>
+							</div>
+						</div>
+						<div class="layui-col-xs12 layui-col-sm4">
+							<div class="layuiadmin-card-text">
+								<div class="layui-text-top"><i class="layui-icon layui-icon-form"></i><a lay-href="https://www.layui.com/doc/modules/form.html">form</a></div>
+								<p class="layui-text-center">优化 switch 开关组件,让其能根据文本自由伸缩宽</p>
+								<p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/form.html">表单</a><span>7 天前</span></p>
+							</div>
+						</div>
+						<div class="layui-col-xs12 layui-col-sm4">
+							<div class="layuiadmin-card-text">
+								<div class="layui-text-top"><i class="layui-icon layui-icon-form"></i><a lay-href="https://www.layui.com/doc/modules/form.html">form</a></div>
+								<p class="layui-text-center">修复 checkbox 复选框组件在高分辨屏下出现的样式不雅问题</p>
+								<p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/form.html">表单</a><span>7 天前</span></p>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>-->
+	</div>
+</div>
+
+<script>
+	layui.use(['index','admin'], function () {
+		const $ = layui.$;
+		const admin = layui.admin;
+
+		$('.deal-feedback').click(function(){
+			const id = $(this).data('id');
+			admin.req({
+				url: "{:url('feedback/dealFeedback')}",
+				data: {
+					idarr:[id]
+				},
+				success: function (res) {
+					location.reload();
+				}
+			});
+		});
+	});
+</script>

+ 199 - 0
app/admin/view/home/homepage1.html

@@ -0,0 +1,199 @@
+
+
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>layuiAdmin 主页示例模板一</title>
+  <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+</head>
+<body>
+
+  <div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+      <div class="layui-col-md8">    
+        <div class="layui-card">
+          <div class="layui-card-header">
+            最近更新
+            <a lay-href="https://www.layui.com/doc/base/changelog.html" class="layui-a-tips">全部更新</a>
+          </div>
+          <div class="layui-card-body">
+            <div class="layui-row layui-col-space10">
+              <div class="layui-col-xs12 layui-col-sm4">
+                <div class="layuiadmin-card-text">
+                  <div class="layui-text-top"><i class="layui-icon layui-icon-water"></i><a lay-href="https://www.layui.com/doc/modules/flow.html">flow</a></div>
+                  <p class="layui-text-center">修复开启 isLazyimg:true 后, 图片懒加载但是图片不存在的报错问题</p>
+                  <p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/flow.html">流加载</a><span>7 天前</span></p>
+                </div>
+              </div>
+              <div class="layui-col-xs12 layui-col-sm4">
+                <div class="layuiadmin-card-text">
+                  <div class="layui-text-top"><i class="layui-icon layui-icon-upload-circle"></i><a lay-href="https://www.layui.com/doc/modules/upload.html">upload</a></div>
+                  <p class="layui-text-center">修复开启 size 参数后,文件超出规定大小时,提示信息有误的问题</p>
+                  <p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/upload.html">文件上传</a><span>7 天前</span></p>
+                </div>
+              </div>
+              <div class="layui-col-xs12 layui-col-sm4">
+                <div class="layuiadmin-card-text">
+                  <div class="layui-text-top"><i class="layui-icon layui-icon-form"></i><a lay-href="https://www.layui.com/doc/modules/form.html#val">form</a></div>
+                  <p class="layui-text-center">增加 form.val(filter, fields)方法,用于给指定表单集合的元素初始赋值</p>
+                  <p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/form.html">表单</a><span>7 天前</span></p>
+                </div>
+              </div>
+              <div class="layui-col-xs12 layui-col-sm4">
+                <div class="layuiadmin-card-text">
+                  <div class="layui-text-top"><i class="layui-icon layui-icon-form"></i><a lay-href="https://www.layui.com/doc/modules/form.html">form</a></div>
+                  <p class="layui-text-center">对 select 组件新增上下键(↑ ↓)回车键(Enter)选择功能</p>
+                  <p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/form.html">表单</a><span>7 天前</span></p>
+                </div>
+              </div>
+              <div class="layui-col-xs12 layui-col-sm4">
+                <div class="layuiadmin-card-text">
+                  <div class="layui-text-top"><i class="layui-icon layui-icon-form"></i><a lay-href="https://www.layui.com/doc/modules/form.html">form</a></div>
+                  <p class="layui-text-center">优化 switch 开关组件,让其能根据文本自由伸缩宽</p>
+                  <p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/form.html">表单</a><span>7 天前</span></p>
+                </div>
+              </div>
+              <div class="layui-col-xs12 layui-col-sm4">
+                <div class="layuiadmin-card-text">
+                  <div class="layui-text-top"><i class="layui-icon layui-icon-form"></i><a lay-href="https://www.layui.com/doc/modules/form.html">form</a></div>
+                  <p class="layui-text-center">修复 checkbox 复选框组件在高分辨屏下出现的样式不雅问题</p>
+                  <p class="layui-text-bottom"><a lay-href="https://www.layui.com/doc/modules/form.html">表单</a><span>7 天前</span></p>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="layui-card">
+          <div class="layui-card-header">动态</div>
+          <div class="layui-card-body">
+            <dl class="layuiadmin-card-status">
+              <dd>
+                <div class="layui-status-img"><a href="javascript:;"><img src="../../layuiadmin/style/res/logo.png"></a></div>
+                <div>
+                  <p>胡歌 在 <a lay-href="http://fly.layui.com/vipclub/list/layuiadmin/">layuiadmin专区</a> 回答问题</p>
+                  <span>几秒前</span>
+                </div>
+              </dd>
+              <dd>
+                <div class="layui-status-img"><a href="javascript:;"><img src="../../layuiadmin/style/res/logo.png"></a></div>
+                <div>
+                  <p>彭于晏 在 <a lay-href="http://fly.layui.com/vipclub/list/layuiadmin/">layuiadmin专区</a> 进行了 <a lay-href="http://fly.layui.com/vipclub/list/layuiadmin/column/quiz/">提问</a></p>
+                  <span>2天前</span>
+                </div>
+              </dd>
+              <dd>
+                <div class="layui-status-img"><a href="javascript:;"><img src="../../layuiadmin/style/res/logo.png"></a></div>
+                <div>
+                  <p>贤心 将 <a lay-href="https://www.layui.com/">layui</a> 更新至 2.3.0 版本</p>
+                  <span>7天前</span>
+                </div>
+              </dd>
+               <dd>
+                <div class="layui-status-img"><a href="javascript:;"><img src="../../layuiadmin/style/res/logo.png"></a></div>
+                <div>
+                  <p>吴尊 在 <a lay-href="http://fly.layui.com/">Fly社区</a> 发布了 <a lay-href="http://fly.layui.com/column/suggest/">建议</a></p>
+                  <span>7天前</span>
+                </div>
+              </dd>
+              <dd>
+                <div class="layui-status-img"><a href="javascript:;"><img src="../../layuiadmin/style/res/logo.png"></a></div>
+                <div>
+                  <p>许上进 在 <a lay-href="http://fly.layui.com/">Fly社区</a> 发布了 <a lay-href="http://fly.layui.com/column/suggest/">建议</a></p>
+                  <span>8天前</span>
+                </div>
+              </dd>
+              <dd>
+                <div class="layui-status-img"><a href="javascript:;"><img src="../../layuiadmin/style/res/logo.png"></a></div>
+                <div>
+                  <p>小蚊子 在 <a lay-href="http://fly.layui.com/vipclub/list/layuiadmin/">layuiadmin专区</a> 进行了 <a lay-href="http://fly.layui.com/vipclub/list/layuiadmin/column/quiz/">提问</a></p>
+                  <span>8天前</span>
+                </div>
+              </dd>
+            </dl>  
+          </div>
+        </div>     
+      </div>
+      <div class="layui-col-md4">
+        <div class="layui-card">
+          <div class="layui-card-header">便捷导航</div>
+          <div class="layui-card-body">
+            <div class="layuiadmin-card-link">
+              <a href="javascript:;">操作一</a>
+              <a href="javascript:;">操作二</a> 
+              <a href="javascript:;">操作三</a> 
+              <a href="javascript:;">操作四</a> 
+              <a href="javascript:;">操作五</a> 
+              <a href="javascript:;">操作六</a>
+              <button class="layui-btn layui-btn-primary layui-btn-xs">
+                <i class="layui-icon layui-icon-add-1" style="position: relative; top: -1px;"></i>添加
+              </button>
+            </div>        
+          </div>
+        </div>
+        <div class="layui-card">
+          <div class="layui-card-header">八卦新闻</div>
+          <div class="layui-card-body">
+
+              <div class="layui-carousel layadmin-carousel layadmin-dataview" data-anim="fade" lay-filter="LAY-index-pageone">
+                <div carousel-item id="LAY-index-pageone">
+                  <div><i class="layui-icon layui-icon-loading1 layadmin-loading"></i></div>
+                </div>
+              </div> 
+
+          </div>
+        </div>
+        <div class="layui-card">
+          <div class="layui-card-header">重点组件</div>
+          <div class="layui-card-body">
+            <ul class="layui-row layuiadmin-card-team">
+              <li class="layui-col-xs6">
+                <a lay-href="https://www.layui.com/doc/modules/table.html">
+                  <span class="layui-team-img"><img src="../../layuiadmin/style/res/logo.png"></span> 
+                  <span>数据表格</span>
+                </a>
+              </li>
+              <li class="layui-col-xs6">
+                <a lay-href="https://www.layui.com/doc/modules/layim.html">
+                  <span class="layui-team-img"><img src="../../layuiadmin/style/res/logo.png"></span> 
+                  <span>即时通讯</span>
+                </a>
+              </li>
+              <li class="layui-col-xs6">
+                <a lay-href="https://www.layui.com/doc/modules/form.html">
+                  <span class="layui-team-img"><img src="../../layuiadmin/style/res/logo.png"></span> 
+                  <span>表单</span>
+                </a>
+              </li>
+              <li class="layui-col-xs6">
+                <a lay-href="https://www.layui.com/doc/modules/layer.html">
+                  <span class="layui-team-img"><img src="../../layuiadmin/style/res/logo.png"></span> 
+                  <span>弹出层</span>
+                </a>
+              </li>
+              <li class="layui-col-xs6">
+                <a lay-href="https://www.layui.com/doc/modules/upload.html">
+                  <span class="layui-team-img"><img src="../../layuiadmin/style/res/logo.png"></span> 
+                  <span>文件上传</span>
+                </a>
+              </li>
+              <li class="layui-col-xs6">
+                <a lay-href="https://www.layui.com/doc/modules/rate.html">
+                  <span class="layui-team-img"><img src="../../layuiadmin/style/res/logo.png"></span> 
+                  <span>评分</span>
+                </a>
+              </li>
+            </ul>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <script>
+  layui.use(['index', 'sample']);
+  </script>
+</body>
+</html>

+ 316 - 0
app/admin/view/home/homepage2.html

@@ -0,0 +1,316 @@
+
+
+<!DOCTYPE html>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>layuiAdmin 主页示例模板二</title>
+  <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+</head>
+<body>
+
+  <div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+      
+      <div class="layui-col-sm6 layui-col-md3">
+        <div class="layui-card">
+          <div class="layui-card-header">
+            访问量
+            <span class="layui-badge layui-bg-blue layuiadmin-badge">周</span>
+          </div>
+          <div class="layui-card-body layuiadmin-card-list">
+            <p class="layuiadmin-big-font">9,999,666</p>
+            <p>
+              总计访问量 
+              <span class="layuiadmin-span-color">88万 <i class="layui-inline layui-icon layui-icon-flag"></i></span>
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="layui-col-sm6 layui-col-md3">
+        <div class="layui-card">
+          <div class="layui-card-header">
+            下载
+            <span class="layui-badge layui-bg-cyan layuiadmin-badge">月</span>
+          </div>
+          <div class="layui-card-body layuiadmin-card-list">
+            <p class="layuiadmin-big-font">33,555</p>
+            <p>
+              新下载 
+              <span class="layuiadmin-span-color">10% <i class="layui-inline layui-icon layui-icon-face-smile-b"></i></span>
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="layui-col-sm6 layui-col-md3">
+        <div class="layui-card">
+          <div class="layui-card-header">
+            收入
+            <span class="layui-badge layui-bg-green layuiadmin-badge">年</span>
+          </div>
+          <div class="layui-card-body layuiadmin-card-list">
+
+            <p class="layuiadmin-big-font">999,666</p>
+            <p>
+              总收入 
+              <span class="layuiadmin-span-color">*** <i class="layui-inline layui-icon layui-icon-dollar"></i></span>
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="layui-col-sm6 layui-col-md3">
+        <div class="layui-card">
+          <div class="layui-card-header">
+            活跃用户
+            <span class="layui-badge layui-bg-orange layuiadmin-badge">月</span>
+          </div>
+          <div class="layui-card-body layuiadmin-card-list">
+
+            <p class="layuiadmin-big-font">66,666</p>
+            <p>
+              最近一个月 
+              <span class="layuiadmin-span-color">15% <i class="layui-inline layui-icon layui-icon-user"></i></span>
+            </p>
+          </div>
+        </div>
+      </div>   
+      <div class="layui-col-sm12">
+        <div class="layui-card">
+          <div class="layui-card-header">
+            访问量
+            <div class="layui-btn-group layuiadmin-btn-group">
+              <a href="javascript:;" class="layui-btn layui-btn-primary layui-btn-xs">去年</a>
+              <a href="javascript:;" class="layui-btn layui-btn-primary layui-btn-xs">今年</a>
+            </div>
+          </div>
+          <div class="layui-card-body">
+            <div class="layui-row">
+              <div class="layui-col-sm8">
+                  <div class="layui-carousel layadmin-carousel layadmin-dataview" data-anim="fade" lay-filter="LAY-index-pagetwo">
+                    <div carousel-item id="LAY-index-pagetwo">
+                      <div><i class="layui-icon layui-icon-loading1 layadmin-loading"></i></div>
+                    </div>
+                  </div>
+              </div>
+              <div class="layui-col-sm4">
+                <div class="layuiadmin-card-list">
+                  <p class="layuiadmin-normal-font">月访问数</p>
+                  <span>同上期增长</span>
+                  <div class="layui-progress layui-progress-big" lay-showPercent="yes">
+                    <div class="layui-progress-bar" lay-percent="30%"></div>
+                  </div>
+                </div>
+                <div class="layuiadmin-card-list">
+                  <p class="layuiadmin-normal-font">月下载数</p>
+                  <span>同上期增长</span>
+                  <div class="layui-progress layui-progress-big" lay-showPercent="yes">
+                    <div class="layui-progress-bar" lay-percent="20%"></div>
+                  </div>
+                </div>
+                <div class="layuiadmin-card-list">
+                  <p class="layuiadmin-normal-font">月收入</p>
+                  <span>同上期增长</span>
+                  <div class="layui-progress layui-progress-big" lay-showPercent="yes">
+                    <div class="layui-progress-bar" lay-percent="25%"></div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="layui-col-sm4">
+        <div class="layui-card">
+          <div class="layui-card-header">用户留言</div>
+          <div class="layui-card-body">
+            <ul class="layuiadmin-card-status layuiadmin-home2-usernote">
+              <li>
+                <h3>贤心</h3>
+                <p>作为 layui 官方推出的后台模板,从初版的饱受争议,到后续的埋头丰富,逐步占据了国内后台系统应用的主要市场。</p>
+                <span>5月30日 00:00</span>
+                <a href="javascript:;" layadmin-event="replyNote" data-id="7" class="layui-btn layui-btn-xs layuiadmin-reply">回复</a>
+              </li>
+              <li>
+                <h3>诸葛亮</h3>
+                <p>皓首匹夫!苍髯老贼!你枉活九十有六,一生未立寸功,只会摇唇鼓舌!助曹为虐!一条断脊之犬,还敢在我军阵前狺狺狂吠,我从未见过有如此厚颜无耻之人!</p>
+                <span>5月02日 00:00</span>
+                <a href="javascript:;" layadmin-event="replyNote" data-id="5" class="layui-btn layui-btn-xs layuiadmin-reply">回复</a>
+              </li>
+              <li>
+                <h3>胡歌</h3>
+                <p>你以为只要长得漂亮就有男生喜欢?你以为只要有了钱漂亮妹子就自己贴上来了?你以为学霸就能找到好工作?我告诉你吧,这些都是真的!</p>
+                <span>5月11日 00:00</span>
+                <a href="javascript:;" layadmin-event="replyNote" data-id="6" class="layui-btn layui-btn-xs layuiadmin-reply">回复</a>
+              </li>
+              <li>
+                <h3>杜甫</h3>
+                <p>人才虽高,不务学问,不能致圣。刘向十日画一水,五日画一石。</p>
+                <span>4月11日 00:00</span>
+                <a href="javascript:;" layadmin-event="replyNote" data-id="2" class="layui-btn layui-btn-xs layuiadmin-reply">回复</a>
+              </li>
+              <li>
+                <h3>鲁迅</h3>
+                <p>路本是无所谓有和无的,走的人多了,就没路了。。</p>
+                <span>4月28日 00:00</span>
+                <a href="javascript:;" layadmin-event="replyNote" data-id="4" class="layui-btn layui-btn-xs layuiadmin-reply">回复</a>
+              </li>
+              <li>
+                <h3>张爱玲</h3>
+                <p>于千万人之中遇到你所要遇到的人,于千万年之中,时间的无涯的荒野中,没有早一步,也没有晚一步,刚巧赶上了,那也没有别的话好说,唯有轻轻的问一声:“噢,原来你也在这里?”</p>
+                <span>4月11日 00:00</span>
+                <a href="javascript:;" layadmin-event="replyNote" data-id="1" class="layui-btn layui-btn-xs layuiadmin-reply">回复</a>
+              </li>
+            </ul>
+          </div>
+        </div>
+      </div>
+      <div class="layui-col-sm8">
+        <div class="layui-row layui-col-space15">
+          <div class="layui-col-sm6">
+            <div class="layui-card">
+              <div class="layui-card-header">本周活跃用户列表</div>
+              <div class="layui-card-body">
+                <table class="layui-table layuiadmin-page-table" lay-skin="line">
+                  <thead>
+                    <tr>
+                      <th>用户名</th>
+                      <th>最后登录时间</th>
+                      <th>状态</th>
+                      <th>获得赞</th>
+                    </tr> 
+                  </thead>
+                  <tbody>
+                    <tr>
+                      <td><span class="first">胡歌</span></td>
+                      <td><i class="layui-icon layui-icon-log"> 11:20</i></td>
+                      <td><span>在线</span></td>
+                      <td>22 <i class="layui-icon layui-icon-praise"></i></td>
+                    </tr>
+                    <tr>
+                      <td><span class="second">彭于晏</span></td>
+                      <td><i class="layui-icon layui-icon-log"> 10:40</i></td>
+                      <td><span>在线</span></td>
+                      <td>21 <i class="layui-icon layui-icon-praise"></i></td>
+                    </tr>
+                    <tr>
+                      <td><span class="third">靳东</span></td>
+                      <td><i class="layui-icon layui-icon-log"> 01:30</i></td>
+                      <td><i>离线</i></td>
+                      <td>66 <i class="layui-icon layui-icon-praise"></i></td>
+                    </tr>
+                    <tr>
+                      <td>吴尊</td>
+                      <td><i class="layui-icon layui-icon-log"> 21:18</i></td>
+                      <td><i>离线</i></td>
+                      <td>45 <i class="layui-icon layui-icon-praise"></i></td>
+                    </tr>
+                    <tr>
+                      <td>许上进</td>
+                      <td><i class="layui-icon layui-icon-log"> 09:30</i></td>
+                      <td><span>在线</span></td>
+                      <td>21 <i class="layui-icon layui-icon-praise"></i></td>
+                    </tr>
+                    <tr>
+                      <td>小蚊子</td>
+                      <td><i class="layui-icon layui-icon-log"> 21:18</i></td>
+                      <td><i>在线</i></td>
+                      <td>45 <i class="layui-icon layui-icon-praise"></i></td>
+                    </tr>
+                    <tr>
+                      <td>贤心</td>
+                      <td><i class="layui-icon layui-icon-log"> 09:30</i></td>
+                      <td><span>在线</span></td>
+                      <td>21 <i class="layui-icon layui-icon-praise"></i></td>
+                    </tr>
+                  </tbody>
+                </table>
+              </div>
+            </div>
+          </div>
+          <div class="layui-col-sm6">
+            <div class="layui-card">
+              <div class="layui-card-header">项目进展</div>
+              <div class="layui-card-body">
+                <div class="layui-tab-content">
+                  <div class="layui-tab-item layui-show">
+                    <table id="LAY-index-prograss"></table>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="layui-col-sm12">
+            <div class="layui-card">
+              <div class="layui-card-header">用户全国分布</div>
+              <div class="layui-card-body">
+                <div class="layui-row layui-col-space15">
+                  <div class="layui-col-sm4">
+                    <table class="layui-table layuiadmin-page-table" lay-skin="line">
+                      <thead>
+                        <tr>
+                          <th>排名</th>
+                          <th>地区</th>
+                          <th>人数</th>
+                        </tr> 
+                      </thead>
+                      <tbody>
+                        <tr>
+                          <td>1</td>
+                          <td>浙江</td>
+                          <td>62310</td>
+                        </tr>
+                        <tr>
+                          <td>2</td>
+                          <td>上海</td>
+                          <td>59190</td>
+                        </tr>
+                        <tr>
+                          <td>3</td>
+                          <td>广东</td>
+                          <td>55891</td>
+                        </tr>
+                        <tr>
+                          <td>4</td>
+                          <td>北京</td>
+                          <td>51919</td>
+                        </tr>  
+                        <tr>
+                          <td>5</td>
+                          <td>山东</td>
+                          <td>39231</td>
+                        </tr>
+                        <tr>
+                          <td>6</td>
+                          <td>湖北</td>
+                          <td>37109</td>
+                        </tr>
+                      </tbody>
+                    </table>
+                  </div>
+                  <div class="layui-col-sm8">
+
+                    <div class="layui-carousel layadmin-carousel layadmin-dataview" data-anim="fade" lay-filter="LAY-index-pagethree">
+                      <div carousel-item id="LAY-index-pagethree">
+                        <div><i class="layui-icon layui-icon-loading1 layadmin-loading"></i></div>
+                      </div>
+                    </div>
+      
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+        
+      </div>
+    </div>
+  </div>
+
+  <script>
+  layui.use(['index', 'sample']);
+  </script>
+</body>
+</html>

+ 118 - 0
app/admin/view/home/homepage3.html

@@ -0,0 +1,118 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md8">
+            <div class="layui-row layui-col-space15">
+                <div class="layui-col-md12">
+                    <div class="layui-card">
+                        <div class="layui-card-header">用户数据统计</div>
+                        <div class="layui-card-body">
+                            <ul class="layui-row layui-col-space30">
+                                <li class="layui-col-xs3">
+                                    <a class="layadmin-backlog-body">
+                                        <h3>今日新增</h3>
+                                        <p><cite>{$usertol['today']}</cite></p>
+                                    </a>
+                                </li>
+                                <li class="layui-col-xs3">
+                                    <a class="layadmin-backlog-body">
+                                        <h3>昨日新增</h3>
+                                        <p><cite>{$usertol['yesterday']}</cite></p>
+                                    </a>
+                                </li>
+                                <li class="layui-col-xs3">
+                                    <a class="layadmin-backlog-body">
+                                        <h3>本周新增</h3>
+                                        <p><cite>{$usertol['week']}</cite></p>
+                                    </a>
+                                </li>
+                                <li class="layui-col-xs3">
+                                    <a class="layadmin-backlog-body">
+                                        <h3>本月新增</h3>
+                                        <p><cite>{$usertol['month']}</cite></p>
+                                    </a>
+                                </li>
+                            </ul>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="layui-col-md4">
+            <div class="layui-card">
+                <div class="layui-card-header">系统信息</div>
+                <div class="layui-card-body layui-text">
+                    <table class="layui-table">
+                        <colgroup>
+                            <col width="150" height="120">
+                            <col>
+                        </colgroup>
+                        <tbody>
+                        <tr>
+                            <td>上次登录时间</td>
+                            <td>{$access_admin['last_date']}</td>
+                        </tr>
+                        <tr>
+                            <td>上次登录IP地址</td>
+                            <td>{$access_admin['last_ip']}</td>
+                        </tr>
+                        <tr>
+                            <td>当前系统域名</td>
+                            <td>{$_SERVER['REQUEST_SCHEME']}://{$_SERVER['HTTP_HOST']}</td>
+                        </tr>
+                        <tr>
+                            <td>运行环境</td>
+                            <td>{$_SERVER["SERVER_SOFTWARE"]}</td>
+                        </tr>
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'admin', 'carousel', 'echarts'], function () {
+        const $ = layui.$;
+        const carousel = layui.carousel;
+        const element = layui.element;
+        const device = layui.device();
+        //轮播切换
+        $('.layadmin-carousel').each(function () {
+            const othis = $(this);
+            carousel.render({
+                elem: this,
+                width: '100%',
+                arrow: 'none',
+                interval: othis.data('interval'),
+                autoplay: othis.data('autoplay') === true,
+                trigger: (device.ios || device.android) ? 'click' : 'hover',
+                anim: othis.data('anim')
+            });
+        });
+        element.render('progress');
+
+
+        //没找到DOM,终止执行
+        if (!elemDataView[0]) return;
+        renderDataView(0);
+
+        //监听数据概览轮播
+        let carouselIndex = 0;
+        carousel.on('change(LAY-index-dataview)', function (obj) {
+            renderDataView(carouselIndex = obj.index);
+        });
+
+        //监听侧边伸缩
+        layui.admin.on('side', function () {
+            setTimeout(function () {
+                renderDataView(carouselIndex);
+            }, 300);
+        });
+
+        //监听路由
+        layui.admin.on('hash(tab)', function () {
+            layui.router().path.join('') || renderDataView(carouselIndex);
+        });
+    });
+</script>

+ 143 - 0
app/admin/view/home/index.html

@@ -0,0 +1,143 @@
+<div id="LAY_app">
+	<div class="layui-layout layui-layout-admin">
+		<div class="layui-header">
+			<!-- 头部区域 -->
+			<ul class="layui-nav layui-layout-left">
+				<li class="layui-nav-item layadmin-flexible" lay-unselect>
+					<a href="javascript:;" layadmin-event="flexible" title="侧边伸缩">
+						<i class="layui-icon layui-icon-shrink-right" id="LAY_app_flexible"></i>
+					</a>
+				</li>
+				<li class="layui-nav-item layui-hide-xs" lay-unselect>
+					<a href="/" target="_blank" title="前台">
+						<i class="layui-icon layui-icon-website"></i>
+					</a>
+				</li>
+				<li class="layui-nav-item" lay-unselect>
+					<a href="javascript:;" layadmin-event="refresh" title="刷新">
+						<i class="layui-icon layui-icon-refresh-3"></i>
+					</a>
+				</li>
+			</ul>
+			<ul class="layui-nav layui-layout-right" lay-filter="layadmin-layout-right">
+				<!-- <li class="layui-nav-item" lay-unselect>
+					<a lay-href="{:url('/admin/message')}" layadmin-event="message" lay-text="消息中心">
+						<i class="layui-icon layui-icon-notice"></i>
+						<span class="layui-badge-dot"></span>
+					</a>
+				</li> -->
+				<li class="layui-nav-item layui-hide-xs" lay-unselect>
+					<a href="javascript:;" layadmin-event="theme">
+						<i class="layui-icon layui-icon-theme"></i>
+					</a>
+				</li>
+				<li class="layui-nav-item layui-hide-xs" lay-unselect>
+					<a href="javascript:;" layadmin-event="note">
+						<i class="layui-icon layui-icon-note"></i>
+					</a>
+				</li>
+				<li class="layui-nav-item" lay-unselect>
+					<a href="javascript:;">
+						<cite>{$access_admin['admin_name']}【{$access_admin['realname']}】</cite>
+					</a>
+					<dl class="layui-nav-child">
+						<dd style="text-align: center;"><a lay-href="{:url('admin/myinfo')}">我的信息</a></dd>
+						<dd style="text-align: center;"><a lay-href="{:url('admin/mypassword')}">修改密码</a></dd>
+						<hr>
+						<dd style="text-align: center;"><a href="{:url('login/logout')}">退出</a></dd>
+					</dl>
+				</li>
+				<li class="layui-nav-item layui-hide-xs" lay-unselect>
+					<a href="javascript:;" layadmin-event="fullscreen">
+						<i class="layui-icon layui-icon-screen-full"></i>
+					</a>
+				</li>
+				<li class="layui-nav-item layui-hide-xs" lay-unselect>
+					<a href="javascript:;" layadmin-event="about"><i class="layui-icon layui-icon-more-vertical"></i></a>
+				</li>
+				<li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-unselect>
+					<a href="javascript:;" layadmin-event="more"><i class="layui-icon layui-icon-more-vertical"></i></a>
+				</li>
+			</ul>
+		</div>
+
+		<!-- 侧边菜单 -->
+		<div class="layui-side layui-side-menu">
+			<div class="layui-side-scroll">
+				<div class="layui-logo" lay-href="home/console.html">
+					<span>后台</span>
+				</div>
+
+				<ul class="layui-nav layui-nav-tree" lay-shrink="all" id="LAY-system-side-menu" lay-filter="layadmin-system-side-menu">
+					<li data-name="home" class="layui-nav-item layui-nav-itemed">
+						<a href="javascript:;" lay-tips="主页" lay-direction="2">
+							<i class="layui-icon layui-icon-home"></i>
+							<cite>主页</cite>
+						</a>
+						<dl class="layui-nav-child">
+							<dd data-name="console" class="layui-this">
+								<a lay-href="{:url('home/console')}">控制台</a>
+							</dd>
+						</dl>
+					</li>
+
+					{volist name="powerarr" id="pmenu"}
+					<li class="layui-nav-item">
+						<a href="javascript:;" lay-tips="{$pmenu.title}">
+							<i class="layui-icon {$pmenu.layicon}"></i>
+							<cite>{$pmenu.title}</cite>
+						</a>
+						<dl class="layui-nav-child">
+							{volist name="pmenu.children" id="menu"}
+							<dd>
+								<a lay-href="{:url($menu.urlstr, $menu.urlarr)}" lay-text="{$menu.title}">{$menu.title}</a>
+							</dd>
+							{/volist}
+						</dl>
+					</li>
+					{/volist}
+				</ul>
+			</div>
+		</div>
+
+		<!-- 页面标签 -->
+		<div class="layadmin-pagetabs" id="LAY_app_tabs">
+			<div class="layui-icon layadmin-tabs-control layui-icon-prev" layadmin-event="leftPage"></div>
+			<div class="layui-icon layadmin-tabs-control layui-icon-next" layadmin-event="rightPage"></div>
+			<div class="layui-icon layadmin-tabs-control layui-icon-down">
+				<ul class="layui-nav layadmin-tabs-select" lay-filter="layadmin-pagetabs-nav">
+					<li class="layui-nav-item" lay-unselect>
+						<a href="javascript:;"></a>
+						<dl class="layui-nav-child layui-anim-fadein">
+							<dd layadmin-event="closeThisTabs"><a href="javascript:;">关闭当前标签页</a></dd>
+							<dd layadmin-event="closeOtherTabs"><a href="javascript:;">关闭其它标签页</a></dd>
+							<dd layadmin-event="closeAllTabs"><a href="javascript:;">关闭全部标签页</a></dd>
+						</dl>
+					</li>
+				</ul>
+			</div>
+			<div class="layui-tab" lay-unauto lay-allowClose="true" lay-filter="layadmin-layout-tabs">
+				<ul class="layui-tab-title" id="LAY_app_tabsheader">
+					<li lay-id="{:url('home/console')}" lay-attr="{:url('home/console')}" class="layui-this"><i class="layui-icon layui-icon-home"></i></li>
+				</ul>
+			</div>
+		</div>
+
+
+		<!-- 主体内容 -->
+		<div class="layui-body" id="LAY_app_body">
+			<div class="layadmin-tabsbody-item layui-show">
+				<iframe src="{:url('home/console')}" frameborder="0" class="layadmin-iframe"></iframe>
+			</div>
+		</div>
+
+		<!-- 辅助元素,一般用于移动设备下遮罩 -->
+		<div class="layadmin-body-shade" layadmin-event="shade"></div>
+	</div>
+</div>
+
+<script>
+	layui.use(['index'],function(){
+
+	});
+</script>

+ 3 - 0
app/admin/view/layout.html

@@ -0,0 +1,3 @@
+{include file="public/header" /}
+ {__CONTENT__}
+{include file="public/footer" /}

+ 72 - 0
app/admin/view/login/login.html

@@ -0,0 +1,72 @@
+<style>
+    body {background-image:url("__AIMAGES__/bg.jpeg");background-size: cover ;background-attachment: fixed ;background-position: center center;}
+</style>
+<div class="layadmin-user-login layadmin-user-display-show" id="LAY-login-login" style="display: none;">
+    <div class="layadmin-user-login-main">
+        <div class="layadmin-user-login-box layadmin-user-login-header">
+            <h2>后台</h2>
+            <p>管理系统</p>
+        </div>
+        <div class="layadmin-user-login-box layadmin-user-login-body layui-form">
+            <div class="layui-form-item">
+                <label class="layadmin-user-login-icon layui-icon layui-icon-username"
+                       for="LAY-login-login-admin_name"></label>
+                <input type="text" name="admin_name" id="LAY-login-login-admin_name" lay-verify="required"
+                       placeholder="登录账号" class="layui-input">
+            </div>
+            <div class="layui-form-item">
+                <label class="layadmin-user-login-icon layui-icon layui-icon-password"
+                       for="LAY-login-login-password"></label>
+                <input type="password" name="password" id="LAY-login-login-password" lay-verify="required"
+                       placeholder="登录密码" class="layui-input">
+            </div>
+            <div class="layui-form-item">
+                <div class="layui-row">
+                    <div class="layui-col-xs7">
+                        <label class="layadmin-user-login-icon layui-icon layui-icon-vercode"
+                               for="LAY-login-login-vercode"></label>
+                        <input type="text" name="vercode" id="LAY-login-login-vercode" lay-verify="required"
+                               placeholder="图形验证码" class="layui-input">
+                    </div>
+                    <div class="layui-col-xs5">
+                        <div style="margin-left: 10px;" class="echoui-login-captcha">
+                            {:captcha_img()}
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="layui-form-item">
+                <button class="layui-btn layui-btn-fluid" lay-submit lay-filter="LAY-login-login-submit">登 录</button>
+            </div>
+        </div>
+    </div>
+
+    <div class="layui-trans layadmin-user-login-footer">
+        <p>© 2019 - {:date('Y')} <a href="{$domain}" target="_blank">{$_SERVER['HTTP_HOST']}</a></p>
+        <p> &nbsp; </p>
+    </div>
+</div>
+
+
+<script>
+    layui.use(['index', 'user'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        form.render();
+
+        form.on('submit(LAY-login-login-submit)', function (obj) {
+            admin.req({
+                url: "{:url('login/login')}",
+                data: obj.field,
+                success: function (res) {
+                    if (res.code == 0) {
+                        location.href = "{:url('home/index')}";
+                    } else {
+                        $('.echoui-login-captcha img').click();
+                    }
+                }
+            });
+        });
+    });
+</script>

+ 178 - 0
app/admin/view/navigation/index.html

@@ -0,0 +1,178 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-form-pane layui-card-header layuiadmin-card-header-auto">
+            <div class="layui-form-item">
+                <div class="layui-inline">
+                    <label class="layui-form-label">标题</label>
+                    <div class="layui-input-block">
+                        <input type="text" name="title" placeholder="请输入" autocomplete="off" class="layui-input">
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">位置</label>
+                    <div class="layui-input-block">
+                        <select name="tab">
+                            <option value="">全部位置</option>
+                            {volist name="tab_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">状态</label>
+                    <div class="layui-input-block">
+                        <select name="status">
+                            <option value="">全部状态</option>
+                            {volist name="status_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">
+                        <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
+                    </button>
+                </div>
+            </div>
+        </div>
+
+        <div class="layui-card-body">
+            <div style="padding-bottom: 10px;">
+                <button class="layui-btn layuiadmin-btn layui-btn-danger" data-type="del">删除</button>
+                <button class="layui-btn layuiadmin-btn" data-type="add">添加</button>
+            </div>
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="tilpicTpl">
+                <div id="pic{{d.id}}" lay-event="pic">
+                    <img style="width: 100%; height: 100%;" src="{{d.image}}" alt="{{d.title}}">
+                </div>
+            </script>
+            <script type="text/html" id="setTpl">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i
+                        class="layui-icon layui-icon-edit"></i>编辑</a>
+                <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i
+                        class="layui-icon layui-icon-delete"></i>删除</a>
+            </script>
+        </div>
+
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'table'], function () {
+        const $ = layui.$;
+        const setter = layui.setter;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('navigation/listNavigation')}",
+            cols: [
+                [
+                    {type: 'checkbox', fixed: 'left'},
+                    {field: 'priority', width: 80, title: '排序', sort: true},
+                    {field: 'tab_text', width: 120, title: '位置'},
+                    {field: 'image', width: 60, title: '图片', templet: '#tilpicTpl'},
+                    {field: 'title', title: '标题'},
+                    {field: 'url', title: '跳转链接'},
+                    {field: 'status_text',  width: 60, title: '状态'},
+                    {title: '操作', width: 200, align: 'center', fixed: 'right', toolbar: '#setTpl'}
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        form.on('submit({$lay_btn})', function (data) {
+            table.reload('{$lay_table}', {
+                where: data.field,
+                page: {
+                    curr: 1
+                }
+            });
+        });
+
+        var active = {
+            del: function () {
+                const check_data = table.checkStatus('{$lay_table}').data;
+                if (check_data.length === 0) {
+                    return layer.msg('请选择数据');
+                }
+                let id_arr = [];
+                for (let i = 0; i < check_data.length; i++) {
+                    id_arr.push(check_data[i].id);
+                }
+                layer.confirm('确定删除所选页面导航吗?', function (index) {
+                    admin.req({
+                        url: "{:url('navigation/delNavigation')}",
+                        data: {
+                            id_arr: id_arr
+                        },
+                        done: function (res) {
+                            table.reload('{$lay_table}');
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            },
+            add: function () {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加页面导航',
+                    content: "{:url('navigation/navigationForm')}",
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        };
+
+        //监听工具条
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'del') {
+                layer.confirm('确定删除此页面导航吗?', function (index) {
+                    admin.req({
+                        url: "{:url('navigation/delNavigation')}",
+                        data: {
+                            id_arr: [data.id]
+                        },
+                        done: function (res) {
+                            obj.del();
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            } else if (obj.event === 'edit') {
+                const index = layer.open({
+                    type: 2,
+                    title: '编辑页面导航',
+                    content: "{:url('navigation/navigationForm')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            } else if (obj.event === 'pic') {
+                layer.photos({
+                    photos: '#pic' + data.id,
+                    anim: 5,
+                });
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+
+    });
+</script>

+ 148 - 0
app/admin/view/navigation/navigation_form.html

@@ -0,0 +1,148 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">页面导航</div>
+                <div class="layui-card-body" pad15>
+
+                    <div class="layui-form layui-form-pane">
+                        <input type="hidden" name="id" value="{:array_get($info,'id')}">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>位置</label>
+                            <div class="layui-input-block">
+                                <select name="tab">
+                                    {volist name="tab_list" id="v"}
+                                    <option value="{$key}" {eq name=":array_get($info,'tab',1)" value="$key" }selected{/eq}>{$v}</option>
+                                    {/volist}
+                                </select>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>标题</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="title" value="{:array_get($info,'title')}" lay-verify="required"
+                                       placeholder="请输入标题"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>标图</label>
+                            <div class="layui-input-block">
+                                <div class="layui-upload">
+                                    <button type="button" class="layui-btn attachment-upload-images" data-input="image"
+                                            data-amount="1">上传图片
+                                    </button>
+                                    <div class="layui-inline layui-word-aux"> 最佳尺寸:240px*240px</div>
+                                    <div class="layui-upload-list echo-attachment-image-list" id="image">
+                                        {notempty name="info.image"}
+                                        <div>
+                                            <input type="hidden" name="image" value="{:array_get($info,'image')}">
+                                            <img src="{:array_get($info,'image')}">
+                                        </div>
+                                        {/notempty}
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">跳转链接</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="url" value="{:array_get($info,'url')}"
+                                       placeholder="请输入跳转链接"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>状态</label>
+                            <div class="layui-input-block">
+                                {volist name="status_list" id="v"}
+                                <input type="radio" name="status" value="{$key}" title="{$v}" {eq name=":array_get($info,'status',1)" value="$key" }checked{/eq}>
+                                {/volist}
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>排序</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="priority" value="{:array_get($info,'priority',255)}"
+                                       lay-verify="required" placeholder="请输入排序值(倒序,值越大越靠前)"
+                                       autocomplete="off" class="layui-input">
+                                <div class="layui-form-mid layui-word-aux">倒序,值越大越靠前</div>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <input type="button" lay-submit lay-filter="{$lay_btn}" value="确认提交" class="layui-btn">
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'upload'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const upload = layui.upload;
+        form.render();
+
+        form.on('submit({$lay_btn})', function (obj) {
+            var index = parent.layer.getFrameIndex(window.name);
+            admin.req({
+                url: "{:url('navigation/editNavigation')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {icon: 1});
+                    parent.layui.table.reload('lay-navigation-index-table'); //重载表格
+                    parent.layer.close(index);
+                }
+            });
+        });
+
+        $('.echo-attachment-image-list').on('click', '.attachmentdel', function () {
+            $(this).parent().remove();
+        });
+
+        let upload_input = '';
+        let upload_amount = '';
+        upload.render({
+            elem: '.attachment-upload-images',
+            url: "{:url('upload/image')}",
+            accept: 'images',
+            exits: 'jpg|png|jpeg',
+            acceptMime: 'image/*',
+            size: 2048,
+            number: 1,
+            method: 'post',
+            before: function (obj) {
+                const item = this.item;
+                upload_input = $(item).data('input');
+                upload_amount = $(item).data('amount');
+                layer.load();
+            },
+            done: function (res, index, upload) {
+                layer.closeAll('loading');
+                let html = "";
+                if (upload_amount == 1) {
+                    html += '<div> <input type="hidden" name="' + upload_input + '" value="' + res.data.src + '"> ';
+                    html += '<img src="' + res.data.src + '"></div>';
+                    $("#" + upload_input).html(html);
+                } else {
+                    html += '<div> <input type="hidden" name="' + upload_input + '[]" value="' + res.data.src + '"> ';
+                    html += '<img src="' + res.data.src +
+                        '"> <button type="button" class="attachmentdel layui-btn layui-btn-primary layui-btn-xs layui-btn-fluid">删除</button></div>';
+                    $("#" + upload_input).append(html);
+                }
+            },
+            error: function (index, upload) {
+                layer.closeAll('loading');
+            }
+        });
+
+    });
+</script>

+ 148 - 0
app/admin/view/notice/index.html

@@ -0,0 +1,148 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-form-pane  layui-card-header layuiadmin-card-header-auto">
+            <div class="layui-form-item">
+                <div class="layui-inline">
+                    <label class="layui-form-label">状态</label>
+                    <div class="layui-input-block">
+                        <select name="status">
+                            <option value="">全部状态</option>
+                            {volist name="status_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">
+                        <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
+                    </button>
+                </div>
+            </div>
+        </div>
+        <div class="layui-form layui-card-header layuiadmin-card-header-auto">
+            <button class="layui-btn layuiadmin-btn layui-btn-danger" data-type="del">删除</button>
+            <button class="layui-btn layuiadmin-btn" data-type="add">添加</button>
+        </div>
+
+        <div class="layui-card-body">
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="setTpl">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">
+                    <i class="layui-icon layui-icon-edit"></i>编辑
+                </a>
+                <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">
+                    <i class="layui-icon layui-icon-delete"></i>删除
+                </a>
+            </script>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'admin', 'form', 'table'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('notice/listNotice')}",
+            cols: [
+                [
+                    {type: 'checkbox', fixed: 'left'},
+                    {field: 'title', title: '标题', width: 100},
+                    {field: 'priority', title: '排序', width: 160},
+                    {field: 'content', title: '内容'},
+                    {field: 'status_text', title: '状态', width: 80, align: 'center'},
+                    {field: 'update_time', title: '发布时间', width: 160, align: 'center'},
+                    {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#setTpl'}
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        form.on('submit({$lay_btn})', function (data) {
+            table.reload('{$lay_table}', {
+                where: data.field,
+                page: {
+                    curr: 1
+                }
+            });
+        });
+
+        //事件
+        const active = {
+            del: function () {
+                const check_data = table.checkStatus('{$lay_table}').data; //得到选中的数据
+                if (check_data.length === 0) {
+                    return layer.msg('请选择数据');
+                }
+                const id_arr = [];
+                for (let i = 0; i < check_data.length; i++) {
+                    id_arr.push(check_data[i].id);
+                }
+                layer.confirm('确定删除吗?', function (index) {
+                    admin.req({
+                        url: "{:url('notice/delNotice')}",
+                        data: {
+                            id_arr: id_arr
+                        },
+                        done: function (res) {
+                            table.reload('{$lay_table}');
+                        }
+                    });
+                    layer.close(index);
+                });
+            },
+            add: function () {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加系统消息',
+                    content: "{:url('notice/noticeForm')}",
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        };
+
+        //监听工具条
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'del') {
+                layer.confirm('确定删除吗?', function (index) {
+                    admin.req({
+                        url: "{:url('notice/delNotice')}",
+                        data: {
+                            id_arr: data.id
+                        },
+                        done: function (res) {
+                            layui.table.reload('{$lay_table}');
+                        }
+                    });
+                    layer.close(index);
+                });
+            } else if (obj.event === 'edit') {
+                const index = layer.open({
+                    type: 2,
+                    title: '编辑系统消息',
+                    content: "{:url('notice/noticeForm')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+    });
+</script>

+ 89 - 0
app/admin/view/notice/notice_form.html

@@ -0,0 +1,89 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">系统通知信息</div>
+                <div class="layui-card-body" pad15>
+                    <div class="layui-form layui-form-pane" lay-filter="{$lay_table}">
+                        <input type="hidden" name="id" value="{:array_get($info,'id')}">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>标题</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="title" value="{:array_get($info,'title')}" lay-verify="required"
+                                       placeholder="请输入标题" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item" id="form-content">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>内容</label>
+                            <div class="layui-input-block">
+                                <script id="editor" type="text/plain">{:array_get($info,'content')}</script>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>排序</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="priority" value="{:array_get($info,'priority',255)}"
+                                       lay-verify="required|number" placeholder="请输入排序"
+                                       autocomplete="off" class="layui-input">
+                                <div class="layui-form-mid layui-word-aux">倒序,值越大越靠前</div>
+                            </div>
+                        </div>
+                        <div class="layui-form-item" pane>
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>状态</label>
+                            <div class="layui-input-block">
+                                {volist name="status_list" id="v"}
+                                <input type="radio" name="status" value="{$key}" title="{$v}" {eq name=":array_get($info,'status',1)" value="$key" }checked{/eq}>
+                                {/volist}
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <input type="button" lay-submit lay-filter="{$lay_btn}" value="确认提交" class="layui-btn">
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+{include file="public/ueditor" /}
+<script>
+    layui.use(['index', 'form', 'layedit', 'upload'], function () {
+        UE.getEditor('editor');
+        const admin = layui.admin;
+        const layedit = layui.layedit;
+        const form = layui.form;
+        form.render();
+
+        const content = layedit.build('content', {
+            uploadImage: { url: "{:url('upload/image')}", type: 'post' }
+        });
+
+        form.verify({
+            editcontent: function (value) {
+                layedit.sync(content);
+            }
+        });
+
+        form.on('submit({$lay_btn})', function (obj) {
+            const index = parent.layer.getFrameIndex(window.name);
+            obj.field.content = UE.getEditor('editor').getContent();
+            admin.req({
+                url: "{:url('notice/editNotice')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {
+                        icon: 1
+                    });
+                    parent.layui.table.reload('lay-notice-index-table'); //重载表格
+                    parent.layer.close(index);
+                }
+            });
+        });
+
+    });
+</script>

+ 56 - 0
app/admin/view/page/index.html

@@ -0,0 +1,56 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">单页内容</div>
+                <div class="layui-card-body" pad15>
+                    <div class="layui-form layui-form-pane">
+                        {volist name="title" id="vo"}
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">{$vo}</label>
+                            <div class="layui-input-block">
+                                <script id="{$key}" type="text/plain">{:array_get($data,$key)}</script>
+                            </div>
+                        </div>
+                        {/volist}
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">确认修改</button>
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+{include file="public/ueditor" /}
+<script>
+    let form_field = {:json_encode($title)};
+    layui.use(['index', 'form'], function () {
+        for (let key in form_field) {
+            UE.getEditor(key);
+        }
+
+        const admin = layui.admin;
+        const form = layui.form;
+        form.render();
+
+        form.on('submit({$lay_btn})', function (obj) {
+            for (let key in form_field) {
+                obj.field[key] = UE.getEditor(key).getContent();
+            }
+            admin.req({
+                url: "{:url('page/edit')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {icon: 1});
+                }
+            });
+
+        });
+    });
+</script>

+ 3 - 0
app/admin/view/public/footer.html

@@ -0,0 +1,3 @@
+
+	</body>
+</html>

+ 25 - 0
app/admin/view/public/header.html

@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta charset="utf-8">
+		<title>管理后台</title>
+		<meta name="renderer" content="webkit">
+		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+		<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+		<link rel="stylesheet" href="__ECHOUI__/layui/css/layui.css" media="all">
+		<link rel="stylesheet" href="__ECHOUI__/style/admin.css" media="all">
+		<link rel="stylesheet" href="__ECHOUI__/style/login.css" media="all">
+		<link rel="stylesheet" href="__ECHOUI__/echoui.css" media="all">
+		<script src="__ECHOUI__/layui/layui.js"></script>
+		<script src="__ECHOUI__/layui/xm-select.js"></script>
+		<script src="__ECHOUI__/echoui.js"></script>
+		<script>
+			layui.config({
+				base: '__ECHOUI__/',
+			}).extend({
+				index: 'lib/index'
+			});
+		</script>
+	</head>
+	<body>
+	

+ 67 - 0
app/admin/view/public/import.html

@@ -0,0 +1,67 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">导入</div>
+                <div class="layui-card-body" pad15>
+                    <div class="layui-form layui-form-pane" lay-filter="{$lay_table}">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">文件名</label>
+                            <div class="layui-input-block">
+                                <input type="text" id="file_name" autocomplete="off" readonly placeholder="请点击上传文件按钮" class="layui-input">
+                            </div>
+                        </div>
+                        <input type="hidden" name="file_url" value="" id="file_url">
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <a href="{$template_file}" target="_blank">
+                                    <button type="button" class="layui-btn layui-btn-normal" id="test3">下载模板</button>
+                                </a>
+                                <button type="button" class="layui-btn layui-btn-normal" id="upload"><i class="layui-icon"></i>上传文件</button>
+                                <input type="button" lay-submit lay-filter="{$lay_btn}" value="确认提交" class="layui-btn">
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+
+<script>
+    layui.use(['index', 'form', 'upload'], function() {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const upload = layui.upload;
+        const form = layui.form;
+        form.render();
+
+        form.on('submit({$lay_btn})', function(obj) {
+            var index = parent.layer.getFrameIndex(window.name);
+            admin.req({
+                url:  "{$url}",
+                data: obj.field,
+                type: 'post',
+                done: function(res) {
+                    layer.msg("导入成功", {
+                        icon: 1
+                    });
+                    parent.layui.table.reload('{$last_table}'); //重载表格
+                    parent.layer.close(index);
+                }
+            });
+        });
+
+        upload.render({
+            elem: '#upload'
+            ,url: "{:url('upload/file')}" //此处配置你自己的上传接口即可
+            ,accept: 'file' //普通文件
+            ,done: function(res){
+                $('#file_url').val(res.data.path);
+                $('#file_name').val(res.data.title);
+            }
+        });
+    });
+</script>

+ 6 - 0
app/admin/view/public/ueditor.html

@@ -0,0 +1,6 @@
+<script>
+    window.UEDITOR_HOME_URL = "/ueditor/";
+</script>
+<script type="text/javascript" src="/ueditor/ueditor.config.js"></script>
+<script type="text/javascript" src="/ueditor/ueditor.all.min.js"></script>
+<script type="text/javascript" charset="utf-8" src="/ueditor/lang/zh-cn/zh-cn.js"></script>

+ 179 - 0
app/admin/view/setting/sms.html

@@ -0,0 +1,179 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+
+            <div class="layui-card layui-tab  layui-tab-brief" lay-filter="linktab">
+                <ul class="layui-tab-title">
+                    <li class="layui-this">短信</li>
+                    <li>创蓝</li>
+                    <!--<li>阿里</li>-->
+                </ul>
+                <div class="layui-tab-content">
+                    <div class="layui-tab-item layui-show">
+                        <div class="layui-card">
+                            <div class="layui-card-header">短信配置</div>
+                            <div class="layui-card-body" pad15>
+                                <div class="layui-form layui-form-pane">
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label"><span style="color:#f90c05;">*</span>短信</label>
+                                        <div class="layui-input-block">
+                                            {volist name="sms_type" id="v"}
+                                            <input type="radio" name="sms_type" value="{$v.value}" title="{$v.text}" {eq name=":array_get($sms,'sms_type')" value="$v['value']" }checked{/eq}>
+                                            {/volist}
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label"><span style="color:#f90c05;">*</span>过期时间</label>
+                                        <div class="layui-input-block">
+                                            <input type="number" placeholder="短信验证码过期时间"
+                                                   name="sms_verify_expire"
+                                                   value="{:array_get($sms,'sms_verify_expire')}"
+                                                   lay-verify="required"
+                                                   class="layui-input">
+                                            <div class="layui-form-mid layui-word-aux">登录验证码的过期时间,单位秒,建议于验证码短信模板保持一致</div>
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <div class="layui-input-block">
+                                            <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">确认修改</button>
+                                        </div>
+                                    </div>
+                                </div>
+
+                            </div>
+                        </div>
+                    </div>
+                    <div class="layui-tab-item">
+                        <div class="layui-card">
+                            <div class="layui-card-header">创蓝短信接口参数</div>
+                            <div class="layui-card-body" pad15>
+                                <div class="layui-form layui-form-pane">
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label"><span style="color:#f90c05;">*</span>密钥 ID</label>
+                                        <div class="layui-input-block">
+                                            <input type="text" placeholder="请输入 AccessKey ID"
+                                                   name="sms_chuanglan_appkey"
+                                                   value="{:array_get($sms,'sms_chuanglan_appkey')}"
+                                                   lay-verify="required"
+                                                   class="layui-input">
+                                            <div class="layui-form-mid layui-word-aux">访问创蓝API的密钥:app key</div>
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label"><span style="color:#f90c05;">*</span>密钥 Secret</label>
+                                        <div class="layui-input-block">
+                                            <input type="text" placeholder="请输入 AccessKey Secret"
+                                                   name="sms_chuanglan_secret"
+                                                   value="{:array_get($sms,'sms_chuanglan_secret')}"
+                                                   lay-verify="required"
+                                                   class="layui-input">
+                                            <div class="layui-form-mid layui-word-aux">访问创蓝API的密钥:secret key</div>
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <div class="layui-input-block">
+                                            <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">确认修改</button>
+                                        </div>
+                                    </div>
+                                </div>
+
+                            </div>
+                        </div>
+                    </div>
+                    <!--<div class="layui-tab-item">
+                        <div class="layui-card">
+                            <div class="layui-card-header">阿里云短信接口参数</div>
+                            <div class="layui-card-body" pad15>
+                                <div class="layui-form layui-form-pane">
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label"><span style="color:#f90c05;">*</span>密钥 ID</label>
+                                        <div class="layui-input-block">
+                                            <input type="text" placeholder="请输入 AccessKey ID"
+                                                   name="sms_ali_accesskeyid"
+                                                   lay-verify="required"
+                                                   value="{:array_get($sms,'sms_ali_accesskeyid')}"
+                                                   class="layui-input">
+                                            <div class="layui-form-mid layui-word-aux">访问阿里云API的密钥:AccessKey ID</div>
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label"><span style="color:#f90c05;">*</span>密钥 Secret</label>
+                                        <div class="layui-input-block">
+                                            <input type="text" placeholder="请输入 AccessKey Secret"
+                                                   name="sms_ali_accesskeysecret"
+                                                   lay-verify="required"
+                                                   value="{:array_get($sms,'sms_ali_accesskeysecret')}"
+                                                   class="layui-input">
+                                            <div class="layui-form-mid layui-word-aux">访问阿里云API的密钥:AccessKey Secret
+                                            </div>
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label">签名名称</label>
+                                        <div class="layui-input-block">
+                                            <input type="text" name="sms_ali_signname"
+                                                   value="{:array_get($sms,'sms_ali_signname')}" class="layui-input">
+                                            <div class="layui-form-mid layui-word-aux"></div>
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label">注册验证</label>
+                                        <div class="layui-input-block">
+                                            <input type="text" name="sms_ali_register"
+                                                   value="{:array_get($sms,'sms_ali_register')}" class="layui-input">
+                                            <div class="layui-form-mid layui-word-aux">注册验证模版CODE,验证码变量名称:code</div>
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label">密码重置</label>
+                                        <div class="layui-input-block">
+                                            <input type="text" name="sms_ali_getpassword"
+                                                   value="{:array_get($sms,'sms_ali_getpassword')}" class="layui-input">
+                                            <div class="layui-form-mid layui-word-aux">密码重置模版CODE,验证码变量名称:code</div>
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label">登录验证</label>
+                                        <div class="layui-input-block">
+                                            <input type="text" name="sms_ali_mobilelogin"
+                                                   value="{:array_get($sms,'sms_ali_mobilelogin')}" class="layui-input">
+                                            <div class="layui-form-mid layui-word-aux">登录验证模版CODE,验证码变量名称:code</div>
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <div class="layui-input-block">
+                                            <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">确认修改</button>
+                                        </div>
+                                    </div>
+                                </div>
+
+                            </div>
+                        </div>
+                    </div>-->
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form'], function () {
+        const admin = layui.admin;
+        const form = layui.form;
+        form.render();
+
+        form.on('submit({$lay_btn})', function (obj) {
+            console.log(obj);
+            admin.req({
+                url: "{:url('setting/editSms')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {icon: 1});
+                }
+            });
+
+        });
+    });
+</script>

+ 59 - 0
app/admin/view/setting/system.html

@@ -0,0 +1,59 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+
+            <div class="layui-card layui-tab  layui-tab-brief" lay-filter="linktab">
+                <ul class="layui-tab-title">
+                    <li class="layui-this">系统</li>
+                </ul>
+                <div class="layui-tab-content">
+                    <div class="layui-tab-item layui-show">
+                        <div class="layui-card">
+                            <div class="layui-card-header">系统参数配置</div>
+                            <div class="layui-card-body" pad15>
+                                <div class="layui-form layui-form-pane">
+                                    <div class="layui-form-item">
+                                        <label class="layui-form-label"><span style="color:#f90c05;">*</span>网站名称</label>
+                                        <div class="layui-input-block">
+                                            <input type="text" placeholder="请输入网站名称"
+                                                   name="site_name"
+                                                   value="{:array_get($system,'site_name')}"
+                                                   lay-verify="required"
+                                                   class="layui-input">
+                                        </div>
+                                    </div>
+                                    <div class="layui-form-item">
+                                        <div class="layui-input-block">
+                                            <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">确认修改</button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form'], function () {
+        const admin = layui.admin;
+        const form = layui.form;
+        form.render();
+
+        form.on('submit({$lay_btn})', function (obj) {
+            admin.req({
+                url: "{:url('setting/editSystem')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {icon: 1});
+                }
+            });
+
+        });
+    });
+</script>

+ 178 - 0
app/admin/view/slide/index.html

@@ -0,0 +1,178 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-form-pane layui-card-header layuiadmin-card-header-auto">
+            <div class="layui-form-item">
+                <div class="layui-inline">
+                    <label class="layui-form-label">标题</label>
+                    <div class="layui-input-block">
+                        <input type="text" name="title" placeholder="请输入" autocomplete="off" class="layui-input">
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">位置</label>
+                    <div class="layui-input-block">
+                        <select name="tab">
+                            <option value="">全部位置</option>
+                            {volist name="tab_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">状态</label>
+                    <div class="layui-input-block">
+                        <select name="status">
+                            <option value="">全部状态</option>
+                            {volist name="status_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">
+                        <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
+                    </button>
+                </div>
+            </div>
+        </div>
+
+        <div class="layui-card-body">
+            <div style="padding-bottom: 10px;">
+                <button class="layui-btn layuiadmin-btn layui-btn-danger" data-type="del">删除</button>
+                <button class="layui-btn layuiadmin-btn" data-type="add">添加</button>
+            </div>
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="tilpicTpl">
+                <div id="pic{{d.id}}" lay-event="pic">
+                    <img style="width: 100%; height: 100%;" src="{{d.image}}" alt="{{d.title}}">
+                </div>
+            </script>
+            <script type="text/html" id="setTpl">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i
+                        class="layui-icon layui-icon-edit"></i>编辑</a>
+                <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i
+                        class="layui-icon layui-icon-delete"></i>删除</a>
+            </script>
+        </div>
+
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'table'], function () {
+        const $ = layui.$;
+        const setter = layui.setter;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('slide/listSlide')}",
+            cols: [
+                [
+                    {type: 'checkbox', fixed: 'left'},
+                    {field: 'priority', width: 80, title: '排序', sort: true},
+                    {field: 'tab_text', width: 120, title: '位置'},
+                    {field: 'image', width: 60, title: '图片', templet: '#tilpicTpl'},
+                    {field: 'title', title: '标题'},
+                    {field: 'url', title: '跳转链接'},
+                    {field: 'status_text',  width: 60, title: '状态'},
+                    {title: '操作', width: 200, align: 'center', fixed: 'right', toolbar: '#setTpl'}
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        form.on('submit({$lay_btn})', function (data) {
+            table.reload('{$lay_table}', {
+                where: data.field,
+                page: {
+                    curr: 1
+                }
+            });
+        });
+
+        var active = {
+            del: function () {
+                const check_data = table.checkStatus('{$lay_table}').data;
+                if (check_data.length === 0) {
+                    return layer.msg('请选择数据');
+                }
+                let id_arr = [];
+                for (let i = 0; i < check_data.length; i++) {
+                    id_arr.push(check_data[i].id);
+                }
+                layer.confirm('确定删除所选轮播图片吗?', function (index) {
+                    admin.req({
+                        url: "{:url('slide/delSlide')}",
+                        data: {
+                            id_arr: id_arr
+                        },
+                        done: function (res) {
+                            table.reload('{$lay_table}');
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            },
+            add: function () {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加轮播图片',
+                    content: "{:url('slide/slideForm')}",
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        };
+
+        //监听工具条
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'del') {
+                layer.confirm('确定删除此轮播图片吗?', function (index) {
+                    admin.req({
+                        url: "{:url('slide/delSlide')}",
+                        data: {
+                            id_arr: [data.id]
+                        },
+                        done: function (res) {
+                            obj.del();
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            } else if (obj.event === 'edit') {
+                const index = layer.open({
+                    type: 2,
+                    title: '编辑轮播图片',
+                    content: "{:url('slide/slideForm')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            } else if (obj.event === 'pic') {
+                layer.photos({
+                    photos: '#pic' + data.id,
+                    anim: 5,
+                });
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+
+    });
+</script>

+ 148 - 0
app/admin/view/slide/slide_form.html

@@ -0,0 +1,148 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">轮播图片</div>
+                <div class="layui-card-body" pad15>
+
+                    <div class="layui-form layui-form-pane">
+                        <input type="hidden" name="id" value="{:array_get($info,'id')}">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>位置</label>
+                            <div class="layui-input-block">
+                                <select name="tab">
+                                    {volist name="tab_list" id="v"}
+                                    <option value="{$key}" {eq name=":array_get($info,'tab',1)" value="$key" }checked{/eq}>{$v}</option>
+                                    {/volist}
+                                </select>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>标题</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="title" value="{:array_get($info,'title')}" lay-verify="required"
+                                       placeholder="请输入标题"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>标图</label>
+                            <div class="layui-input-block">
+                                <div class="layui-upload">
+                                    <button type="button" class="layui-btn attachment-upload-images" data-input="image"
+                                            data-amount="1">上传图片
+                                    </button>
+                                    <div class="layui-inline layui-word-aux"> 最佳尺寸:750px*280px</div>
+                                    <div class="layui-upload-list echo-attachment-image-list" id="image">
+                                        {notempty name="info.image"}
+                                        <div>
+                                            <input type="hidden" name="image" value="{:array_get($info,'image')}">
+                                            <img src="{:array_get($info,'image')}">
+                                        </div>
+                                        {/notempty}
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">跳转链接</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="url" value="{:array_get($info,'url')}"
+                                       placeholder="请输入跳转链接"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>状态</label>
+                            <div class="layui-input-block">
+                                {volist name="status_list" id="v"}
+                                <input type="radio" name="status" value="{$key}" title="{$v}" {eq name=":array_get($info,'status',1)" value="$key" }checked{/eq}>
+                                {/volist}
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>排序</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="priority" value="{:array_get($info,'priority',255)}"
+                                       lay-verify="required" placeholder="请输入排序值(倒序,值越大越靠前)"
+                                       autocomplete="off" class="layui-input">
+                                <div class="layui-form-mid layui-word-aux">倒序,值越大越靠前</div>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <input type="button" lay-submit lay-filter="{$lay_btn}" value="确认提交" class="layui-btn">
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'upload'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const upload = layui.upload;
+        form.render();
+
+        form.on('submit({$lay_btn})', function (obj) {
+            var index = parent.layer.getFrameIndex(window.name);
+            admin.req({
+                url: "{:url('slide/editSlide')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {icon: 1});
+                    parent.layui.table.reload('lay-slide-index-table'); //重载表格
+                    parent.layer.close(index);
+                }
+            });
+        });
+
+        $('.echo-attachment-image-list').on('click', '.attachmentdel', function () {
+            $(this).parent().remove();
+        });
+
+        let upload_input = '';
+        let upload_amount = '';
+        upload.render({
+            elem: '.attachment-upload-images',
+            url: "{:url('upload/image')}",
+            accept: 'images',
+            exits: 'jpg|png|jpeg',
+            acceptMime: 'image/*',
+            size: 2048,
+            number: 1,
+            method: 'post',
+            before: function (obj) {
+                const item = this.item;
+                upload_input = $(item).data('input');
+                upload_amount = $(item).data('amount');
+                layer.load();
+            },
+            done: function (res, index, upload) {
+                layer.closeAll('loading');
+                let html = "";
+                if (upload_amount == 1) {
+                    html += '<div> <input type="hidden" name="' + upload_input + '" value="' + res.data.src + '"> ';
+                    html += '<img src="' + res.data.src + '"></div>';
+                    $("#" + upload_input).html(html);
+                } else {
+                    html += '<div> <input type="hidden" name="' + upload_input + '[]" value="' + res.data.src + '"> ';
+                    html += '<img src="' + res.data.src +
+                        '"> <button type="button" class="attachmentdel layui-btn layui-btn-primary layui-btn-xs layui-btn-fluid">删除</button></div>';
+                    $("#" + upload_input).append(html);
+                }
+            },
+            error: function (index, upload) {
+                layer.closeAll('loading');
+            }
+        });
+
+    });
+</script>

+ 92 - 0
app/admin/view/sms_template/index.html

@@ -0,0 +1,92 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-card-header layuiadmin-card-header-auto">
+            <button class="layui-btn layuiadmin-btn" data-type="add">添加</button>
+        </div>
+
+        <div class="layui-card-body">
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="setTpl">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i
+                        class="layui-icon layui-icon-edit"></i>编辑</a>
+                <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i
+                        class="layui-icon layui-icon-delete"></i>删除</a>
+            </script>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'table'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('sms_template/listTemplate')}",
+            cols: [
+                [
+                    {field: 'id', width: 80,title: 'ID'},
+                    {field: 'code', width: 160, title: '编号', sort: true},
+                    {field: 'comment', title: '备注'},
+                    {title: '操作', width: 150, align: 'center', fixed: 'right', toolbar: '#setTpl'}
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        //事件
+        const active = {
+            add: function () {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加模板',
+                    content: "{:url('sms_template/templateForm')}",
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            },
+        };
+
+        //监听工具条
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'del') {
+                layer.confirm('确定删除此模板吗?', function (index) {
+                    admin.req({
+                        url: "{:url('sms_template/delTemplate')}",
+                        data: {
+                            id: data.id
+                        },
+                        done: function (res) {
+                            obj.del();
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            } else if (obj.event === 'edit') {
+                const index = layer.open({
+                    type: 2,
+                    title: '编辑模板',
+                    content: "{:url('sms_template/templateForm')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+    });
+</script>

+ 66 - 0
app/admin/view/sms_template/template_form.html

@@ -0,0 +1,66 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">短信模板</div>
+                <div class="layui-card-body" pad15>
+                    <div class="layui-form layui-form-pane" lay-filter="{$lay_table}">
+                        <input type="hidden" name="id" value="{:array_get($info,'id')}">
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>编号</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="code" value="{:array_get($info,'code')}" lay-verify="required"
+                                       placeholder="请输入编号" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">短信内容</label>
+                            <div class="layui-input-block">
+                                <textarea name="content" placeholder="请输入..." lay-verify="required" rows="15" class="layui-textarea">{:array_get($info,'content')}</textarea>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>备注</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="comment" value="{:array_get($info,'comment')}" lay-verify="required"
+                                       placeholder="请输入备注" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <input type="button" lay-submit lay-filter="{$lay_btn}" value="确认提交" class="layui-btn">
+                            </div>
+                        </div>
+                    </div>
+
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form'], function () {
+        const admin = layui.admin;
+        const form = layui.form;
+        form.render();
+
+        form.on('submit({$lay_btn})', function (obj) {
+            const index = parent.layer.getFrameIndex(window.name);
+            admin.req({
+                url: "{:url('sms_template/editTemplate')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {
+                        icon: 1
+                    });
+                    parent.layui.table.reload('lay-smstemplate-index-table'); //重载表格
+                    parent.layer.close(index);
+                }
+            });
+        });
+    });
+</script>

+ 83 - 0
app/admin/view/user/follow.html

@@ -0,0 +1,83 @@
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-card-header">用户授权信息</div>
+        <div class="layui-card-body">
+
+            <div class="layui-form layui-form-pane" lay-filter="{$lay_table}">
+                <input type="hidden" name="id" value="{$user.id}">
+                <div class="layui-form-item">
+                    <label class="layui-form-label">用户信息</label>
+                    <div class="layui-input-block">
+                        <input type="text" value="{$user.nickname} - {$user.mobile}" readonly
+                               class="layui-input">
+                    </div>
+                </div>
+                <div class="layui-form-item" pane>
+                    <label class="layui-form-label">跟进方式</label>
+                    <div class="layui-input-block">
+                        {volist name="type_list" id="v"}
+                        <input type="radio" name="type" value="{$key}" title="{$v}" {eq name="key" value="1" }checked{/eq} />
+                        {/volist}
+                    </div>
+                </div>
+                <div class="layui-form-item">
+                    <label class="layui-form-label"><span style="color:#f90c05;">*</span>跟进备注</label>
+                    <div class="layui-input-block">
+                        <textarea name="remark" lay-verify="required" placeholder="请输入..."
+                                  class="layui-textarea"></textarea>
+                    </div>
+                </div>
+                <div class="layui-form-item">
+                    <div class="layui-input-block">
+                        <input type="button" lay-submit lay-filter="{$lay_btn}" value="确认"
+                               class="layui-btn">
+                    </div>
+                </div>
+            </div>
+
+            <fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
+                <legend>以往跟进记录</legend>
+            </fieldset>
+            <ul class="layui-timeline">
+                {volist name="list" id="vo"}
+                <li class="layui-timeline-item">
+                    <i class="layui-icon layui-timeline-axis"></i>
+                    <div class="layui-timeline-content layui-text">
+                        <h3 class="layui-timeline-title">
+                            {$vo.create_time} 【{$vo.type_text}】
+                        </h3>
+                        <p>{$vo.remark}</p>
+                    </div>
+                </li>
+                {/volist}
+                <li class="layui-timeline-item">
+                    <i class="layui-icon layui-timeline-axis"></i>
+                    <div class="layui-timeline-content layui-text">
+                        <div class="layui-timeline-title">已加载完 ( 最多显示最近100条跟进记录 )</div>
+                    </div>
+                </li>
+            </ul>
+
+
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'set', 'table'], function () {
+        const admin = layui.admin;
+        const form = layui.form;
+        form.render();
+
+        form.on('submit({$lay_btn})', function (obj) {
+            admin.req({
+                url: "{:url('user/editFollow')}",
+                data: obj.field,
+                done: function (res) {
+                    location.reload();
+                }
+            });
+        });
+
+    });
+</script>

+ 192 - 0
app/admin/view/user/index.html

@@ -0,0 +1,192 @@
+<style>
+    .layui-table-cell {height:45px;line-height:unset;}
+    .user-box {display:flex;}
+    .user-box .avatar{width:45px;height:45px;}
+    .user-box .content {margin-left:10px;}
+    .user-box .content .account {font-size:18px;color:#000;}
+    .user-box .content .sex {font-size:14px;color:red;}
+    .user-box .content .info {font-size:14px;margin-top:5px;}
+</style>
+<div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-form layui-form-pane  layui-card-header layuiadmin-card-header-auto">
+            <div class="layui-form-item">
+                <div class="layui-inline">
+                    <label class="layui-form-label">关键字</label>
+                    <div class="layui-input-block">
+                        <input type="text" name="keywords" placeholder="请输入账号/昵称/姓名" autocomplete="off" class="layui-input">
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">状态</label>
+                    <div class="layui-input-block">
+                        <select name="status">
+                            <option value="">全部状态</option>
+                            {volist name="status_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <label class="layui-form-label">性别</label>
+                    <div class="layui-input-block">
+                        <select name="gender">
+                            {volist name="gender_list" id="v"}
+                            <option value="{$key}">{$v}</option>
+                            {/volist}
+                        </select>
+                    </div>
+                </div>
+                <div class="layui-inline">
+                    <button class="layui-btn" lay-submit lay-filter="{$lay_btn}">
+                        <i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
+                    </button>
+                </div>
+            </div>
+        </div>
+        <div class="layui-form layui-card-header layuiadmin-card-header-auto">
+            <button class="layui-btn layuiadmin-btn layui-btn-danger" data-type="del">删除</button>
+            <button class="layui-btn layuiadmin-btn" data-type="add">添加新用户</button>
+        </div>
+
+        <div class="layui-card-body">
+            <table id="{$lay_table}" lay-filter="{$lay_table}"></table>
+            <script type="text/html" id="userTpl">
+                <div class="user-box">
+                    <img src="{{d.avatar ? d.avatar : '__COMMON_IMAGES__/default_avatar.png'}}" class="avatar">
+                    <div class="content">
+                        <div class="account">{{d.account}}<span class="sex">({{d.gender_text}})</span></div>
+                        <div class="info">昵称:{{d.nickname}},真实姓名:{{d.realname}}</div>
+                    </div>
+                </div>
+            </script>
+            <script type="text/html" id="setTpl">
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit"><i class="layui-icon layui-icon-edit"></i>编辑</a>
+                <a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="follow"><i class="layui-icon layui-icon-engine"></i>跟进</a>
+                <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i>删除</a>
+            </script>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'admin', 'form', 'table'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const table = layui.table;
+        form.render();
+
+        table.render({
+            elem: '#{$lay_table}',
+            url: "{:url('user/listUser')}",
+            cols: [
+                [
+                    {type: 'checkbox', fixed: 'left'},
+                    {field: 'account', title: '用户信息' ,width: 320, templet: '#userTpl'},
+                    {field: 'mobile', title: '手机号', width: 160},
+                    {field: 'birthday', title: '生日', width: 160},
+                    {field: 'status_text', title: '状态', width: 80, align: 'center'},
+                    {field: 'last_login_ip', title: '最后登录IP', width: 160},
+                    {field: 'last_login_time', title: '最后登录时间', width: 160},
+                    {field: 'create_time', title: '注册时间'},
+                    {title: '操作', width: 240, align: 'center', fixed: 'right', toolbar: '#setTpl'}
+                ]
+            ],
+            page: true,
+            limit: 50,
+            cellMinWidth: 150,
+            text: '对不起,加载出现异常!'
+        });
+
+        form.on('submit({$lay_btn})', function (data) {
+            table.reload('{$lay_table}', {
+                where: data.field,
+                page: {
+                    curr: 1
+                }
+            });
+        });
+
+        //事件
+        const active = {
+            add: function () {
+                const index = layer.open({
+                    type: 2,
+                    title: '添加用户',
+                    content: "{:url('user/userForm')}",
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            },
+            del: function () {
+                const check_data = table.checkStatus('{$lay_table}').data;
+                if (check_data.length === 0) {
+                    return layer.msg('请选择数据');
+                }
+                let id_arr = [];
+                for (let i = 0; i < check_data.length; i++) {
+                    id_arr.push(check_data[i].id);
+                }
+                layer.confirm('确定删除所选用户吗?', function (index) {
+                    admin.req({
+                        url: "{:url('user/delUser')}",
+                        data: {
+                            id_arr: id_arr
+                        },
+                        done: function (res) {
+                            table.reload('{$lay_table}');
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            },
+        };
+
+        //监听工具条
+        table.on('tool({$lay_table})', function (obj) {
+            const data = obj.data;
+            if (obj.event === 'del') {
+                layer.confirm('确定删除此用户吗?', function (index) {
+                    admin.req({
+                        url: "{:url('user/delUser')}",
+                        data: {
+                            id: [data.id]
+                        },
+                        done: function (res) {
+                            obj.del();
+                            layer.msg('已删除');
+                        }
+                    });
+                    layer.close(index);
+                });
+            } else if (obj.event === 'edit') {
+                const index = layer.open({
+                    type: 2,
+                    title: '编辑用户',
+                    content: "{:url('user/userForm')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            } else if (obj.event === 'follow') {
+                const index = layer.open({
+                    type: 2,
+                    title: '跟进记录',
+                    content: "{:url('user/follow')}?id=" + data.id,
+                    maxmin: true,
+                    area: ['550px', '550px']
+                });
+                layer.full(index);
+            }
+        });
+
+        $('.layui-btn.layuiadmin-btn').on('click', function () {
+            const type = $(this).data('type');
+            active[type] ? active[type].call(this) : '';
+        });
+    });
+</script>

+ 167 - 0
app/admin/view/user/user_form.html

@@ -0,0 +1,167 @@
+<div class="layui-fluid">
+    <div class="layui-row layui-col-space15">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-header">用户信息</div>
+                <div class="layui-card-body" pad15>
+                    <div class="layui-form layui-form-pane" lay-filter="{$lay_table}">
+                        <input type="hidden" name="id" value="{:array_get($info,'id')}" />
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>用户名</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="account" value="{:array_get($info,'account')}" lay-verify="required" placeholder="请输入用户名"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">密码</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="password" placeholder="请输入登录密码,不修改留空" autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">头像</label>
+                            <div class="layui-input-block">
+                                <div class="layui-upload">
+                                    <button type="button" class="layui-btn attachment-upload-images" data-input="avatar" data-amount="1">上传图片</button>
+                                    <div class="layui-inline layui-word-aux"> 最佳尺寸:320px*320px </div>
+                                    <div class="layui-upload-list echo-attachment-image-list" id="avatar">
+                                        {notempty name="info.avatar"}
+                                        <div>
+                                            <input type="hidden" name="avatar" value="{:array_get($info,'avatar')}">
+                                            <img src="{:array_get($info,'avatar')}">
+                                        </div>
+                                        {/notempty}
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>昵称</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="nickname" value="{:array_get($info,'nickname')}" lay-verify="required" placeholder="请输入用户昵称"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item" pane>
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>性别</label>
+                            <div class="layui-input-block">
+                                {volist name="gender_list" id="v"}
+                                <input type="radio" name="gender" lay-filter="type" value="{$key}" title="{$v}" {eq name=":array_get($info,'gender',1)" value="$key" }checked{/eq}>
+                                {/volist}
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>手机号</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="mobile" value="{:array_get($info,'mobile')}" lay-verify="required|phone" placeholder="请输入手机号"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">真实姓名</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="realname" value="{:array_get($info,'realname')}" placeholder="请输入真实姓名"
+                                       autocomplete="off" class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">出生日期</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="birthday" id="birthday" value="{:array_get($info,'birthday')}" placeholder="请选择出生日期" autocomplete="off"
+                                       class="layui-input">
+                            </div>
+                        </div>
+                        <div class="layui-form-item" pane>
+                            <label class="layui-form-label"><span style="color:#f90c05;">*</span>状态</label>
+                            <div class="layui-input-block">
+                                {volist name="status_list" id="v"}
+                                <input type="radio" name="status" lay-filter="type" value="{$key}" title="{$v}" {eq name=":array_get($info,'status',1)" value="$key" }checked{/eq}>
+                                {/volist}
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">审核备注</label>
+                            <div class="layui-input-block">
+                                <textarea name="remark" placeholder="请输入审核备注" class="layui-textarea">{:array_get($info,'remark')}</textarea>
+                            </div>
+                        </div>
+                        <div class="layui-form-item">
+                            <div class="layui-input-block">
+                                <input type="button" lay-submit lay-filter="{$lay_btn}" value="确认提交" class="layui-btn">
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script>
+    layui.use(['index', 'form', 'upload', 'laydate'], function () {
+        const $ = layui.$;
+        const admin = layui.admin;
+        const form = layui.form;
+        const upload = layui.upload;
+        const laydate = layui.laydate;
+        form.render();
+
+        laydate.render({
+            elem: '#birthday',
+            type: 'date'
+        });
+
+        form.on('submit({$lay_btn})', function (obj) {
+            const index = parent.layer.getFrameIndex(window.name);
+            admin.req({
+                url: "{:url('user/editUser')}",
+                type: 'post',
+                data: obj.field,
+                done: function (res) {
+                    layer.msg("提交成功", {
+                        icon: 1
+                    });
+                    parent.layui.table.reload('lay-user-index-table'); //重载表格
+                    parent.layer.close(index);
+                }
+            });
+        });
+
+        let upload_input = '';
+        let upload_amount = '';
+        upload.render({
+            elem: '.attachment-upload-images',
+            url: "{:url('upload/image')}",
+            accept: 'images',
+            exits: 'jpg|png|jpeg',
+            acceptMime: 'image/*',
+            size: 2048,
+            number: 1,
+            method: 'post',
+            before: function(obj) {
+                var item = this.item;
+                upload_input = $(item).data('input');
+                upload_amount = $(item).data('amount');
+                layer.load();
+            },
+            done: function(res, index, upload) {
+                layer.closeAll('loading');
+                let html = "";
+                if (upload_amount == 1) {
+                    html += '<div> <input type="hidden" name="' + upload_input + '" value="' + res.data.src + '"> ';
+                    html += '<img src="' + res.data.src + '"></div>';
+                    $("#" + upload_input).html(html);
+                } else {
+                    html += '<div> <input type="hidden" name="' + upload_input + '[]" value="' + res.data.src + '"> ';
+                    html += '<img src="' + res.data.src +
+                        '"> <button type="button" class="attachment-del layui-btn layui-btn-primary layui-btn-xs layui-btn-fluid">删除</button></div>';
+                    $("#" + upload_input).append(html);
+                }
+            },
+            error: function(index, upload) {
+                layer.closeAll('loading');
+            }
+        });
+    });
+</script>

+ 121 - 0
app/common.php

@@ -0,0 +1,121 @@
+<?php
+// 应用公共文件
+
+function ajax_return($code = 0, $msg = '', $data = [])
+{
+    $res      = ['code' => $code, 'msg' => $msg, 'data' => $data];
+    $response = \think\Response::create($res, 'json');
+    throw new \think\exception\HttpResponseException($response);
+}
+
+function url(string $url = '', array $vars = [], $suffix = true, $domain = true)
+{
+    return \think\facade\Route::buildUrl($url, $vars)->suffix($suffix)->domain($domain);
+}
+
+function rand_str($len = 6)
+{
+    $str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    $res = '';
+    for ($i = 0; $i < $len; $i++) {
+        $key = rand(0, strlen($str));
+        $res .= $str[$key];
+    }
+    return $res;
+}
+
+function array_get($array, $key, $default = null)
+{
+    return isset($array[$key]) ? $array[$key] : $default;
+}
+
+/**
+ * 公共数据导出实现功能
+ * @param string $expTitle
+ * @param array $expCellName [['a','A']]
+ * @param array $expTableData [['a'=>1]]
+ * @param array $textValue ['a']
+ */
+function export_exl($expTitle, $expCellName, $expTableData, $textValue=[]) {
+    $fileName    = $expTitle . date('_YmdHis'); //or $xlsTitle 文件名称可根据自己情况设定
+    $cellNum     = count($expCellName);
+    $dataNum     = count($expTableData);
+    $objPHPExcel = new \PHPExcel();
+    $cellName    = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ'];
+    for ($i = 0; $i < $cellNum; $i++) {
+        $objPHPExcel->setActiveSheetIndex(0)->setCellValue($cellName[$i] . '1', $expCellName[$i][1]);
+    }
+// Miscellaneous glyphs, UTF-8
+    for ($i = 0; $i < $dataNum; $i++) {
+        for ($j = 0; $j < $cellNum; $j++) {
+            if (in_array($expCellName[$j][0],$textValue)) {
+                $objPHPExcel->getActiveSheet(0)->setCellValueExplicit($cellName[$j] . ($i + 2), $expTableData[$i][$expCellName[$j][0]],\PHPExcel_Cell_DataType::TYPE_STRING);
+            } else {
+                $objPHPExcel->getActiveSheet(0)->setCellValue($cellName[$j] . ($i + 2), $expTableData[$i][$expCellName[$j][0]]);
+            }
+        }
+    }
+    ob_end_clean();
+    header('pragma:public');
+    header('Content-type:application/vnd.ms-excel');
+    header("Content-Disposition:attachment;filename=$fileName.xls"); //attachment新窗口打印inline本窗口打印
+    $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
+    $objWriter->save('php://output');
+    exit;
+}
+
+
+
+/**
+ * @param string $file
+ * @param array $cell
+ * @param int $crop
+ * @param int $sheet
+ * @return array
+ */
+function import_exl($file = '', $cell = [], $crop = 0, $sheet = 0)
+{
+    $file = iconv("utf-8", "gb2312", $file);   //转码
+    if (empty($file) OR !file_exists($file)) {
+        die('file not exists!');
+    }
+
+    $objRead = new PHPExcel_Reader_Excel2007();   //建立reader对象
+    if (!$objRead->canRead($file)) {
+        $objRead = new PHPExcel_Reader_Excel5();
+        if (!$objRead->canRead($file)) {
+            die('No Excel!');
+        }
+    }
+
+    $cellName  = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ'];
+    $obj       = $objRead->load($file);  //建立excel对象
+    $currSheet = $obj->getSheet($sheet);   //获取指定的sheet表
+    $columnH   = $currSheet->getHighestColumn();   //取得最大的列号
+    $columnCnt = array_search($columnH, $cellName);
+    $rowCnt    = $currSheet->getHighestRow();   //获取总行数
+
+    $data = [];
+    for ($_row = 1; $_row <= $rowCnt; $_row++) {  //读取内容
+        if ($_row > $crop) {
+            for ($_column = 0; $_column <= $columnCnt; $_column++) {
+                $cellId    = $cellName[$_column] . $_row;
+                $cellValue = $currSheet->getCell($cellId)->getValue();
+                //$cellValue = $currSheet->getCell($cellId)->getCalculatedValue();  #获取公式计算的值
+                if ($cellValue instanceof PHPExcel_RichText) {   //富文本转换字符串
+                    $cellValue = $cellValue->__toString();
+                } else {
+                    $cellValue = (string)$cellValue;
+                }
+                if (!empty($cell[$_column])) {
+                    $data[$_row][$cell[$_column]] = $cellValue;
+                } else {
+                    $data[$_row][] = $cellValue;
+                }
+            }
+        }
+    }
+
+    return array_values($data);
+
+}

+ 39 - 0
app/common/model/AdminModel.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace app\common\model;
+
+class AdminModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'admin';
+
+    //自动完成
+    protected $autoWriteTimestamp = true;
+
+    // 设置字段自动转换类型
+    protected $type = [
+        'join_date' => 'timestamp:Y-m-d H:i:s',
+        'last_date' => 'timestamp:Y-m-d H:i:s',
+    ];
+
+    // 常量
+    const STATUS = [1 => '正常', 2 => '禁用'];
+    const ROLE   = [1 => '超级管理员', 2 => '普通管理员'];
+
+    const STATUS_NORMAL  = 1;
+    const STATUS_DISABLE = 2;
+    const ROLE_SUPER     = 1;
+    const ROLE_NORMAL    = 2;
+
+    public function getStatusTextAttr($value, $data)
+    {
+        return self::STATUS[$data['status']];
+    }
+
+    public function getRoleTextAttr($value, $data)
+    {
+        return self::ROLE[$data['role']];
+    }
+
+
+}

+ 25 - 0
app/common/model/ArticleCateModel.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace app\common\model;
+
+class ArticleCateModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'article_cate';
+
+    // 常量
+    const STATUS = [1 => '显示', 2 => '隐藏'];
+
+    const STATUS_SHOW = 1;
+    const STATUS_HIDE = 2;
+
+    //允许修改
+    const EDIT_ALLOW = ['title','priority','status'];
+
+    public function getStatusTextAttr($value, $data)
+    {
+        return self::STATUS[$data['status']];
+    }
+
+
+}

+ 41 - 0
app/common/model/ArticleModel.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace app\common\model;
+
+class ArticleModel extends BaseModel
+{
+    //设置表名
+    protected $name = 'article';
+
+    //自动完成
+    protected $autoWriteTimestamp = true;
+
+    //常量
+    const STATUS = [1 => '已发布', 2 => '待修改'];
+    const TYPE   = [1 => '文章详情', 2 => '链接'];
+
+    const STATUS_PUBLISH = 1;
+    const STATUS_MODIFY  = 2;
+    const TYPE_ARTICLE   = 1;
+    const TYPE_LINK      = 2;
+
+    //允许修改
+    const EDIT_ALLOW = ['cate_id','title','header_image','author','summary','type','content','url','priority','status','volume'];
+
+    public function getStatusTextAttr($value, $data)
+    {
+        return self::STATUS[$data['status']];
+    }
+
+    public function getTypeTextAttr($value, $data)
+    {
+        return self::TYPE[$data['type']];
+    }
+
+    // 关联ArticleCate
+    public function Cate()
+    {
+        return $this->hasOne(ArticleCateModel::class, "id", "cate_id");
+    }
+
+}

+ 10 - 0
app/common/model/BaseModel.php

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

+ 29 - 0
app/common/model/FeedbackModel.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace app\common\model;
+
+class FeedbackModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'feedback';
+
+    //自动完成
+    protected $autoWriteTimestamp = true;
+
+    // 常量
+    const STATUS = [1 => '已读', 2 => '未读'];
+
+    const STATUS_READ  = 1;
+    const STATUS_UNREAD = 2;
+
+    public function getStatusTextAttr($value, $data)
+    {
+        return self::STATUS[$data['status']];
+    }
+
+    public function User()
+    {
+        return $this->hasMany(UserModel::class, "id", "user_id");
+    }
+
+}

+ 27 - 0
app/common/model/MenuModel.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace app\common\model;
+
+class MenuModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'menu';
+
+    // 设置字段自动转换类型
+    protected $type = [
+        'urlarr' => 'array',
+    ];
+
+    // 常量
+    const STATUS = [1 => '正常', 2 => '禁用'];
+
+    const STATUS_NORMAL  = 1;
+    const STATUS_DISABLE = 2;
+
+    public function getStatusTextAttr($value, $data)
+    {
+        return self::STATUS[$data['status']];
+    }
+
+
+}

+ 29 - 0
app/common/model/NavigationModel.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace app\common\model;
+
+class NavigationModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'navigation';
+
+    // 常量
+    const TAB    = [1 => '系统首页'];
+    const STATUS = [1 => '显示', 2 => '隐藏'];
+
+    const TAB_INDEX   = 1;
+    const STATUS_SHOW = 1;
+    const STATUS_HIDE = 2;
+
+    public function getTabTextAttr($value, $data)
+    {
+        return self::TAB[$data['tab']];
+    }
+
+    public function getStatusTextAttr($value, $data)
+    {
+        return self::STATUS[$data['status']];
+    }
+
+
+}

+ 24 - 0
app/common/model/NoticeModel.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace app\common\model;
+
+class NoticeModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'notice';
+
+    //自动完成
+    protected $autoWriteTimestamp = true;
+
+    // 常量
+    const STATUS = [1 => '已发布', 2 => '待修改'];
+
+    const STATUS_PUBLISH = 1;
+    const STATUS_MODIFY  = 2;
+
+    public function getStatusTextAttr($value, $data)
+    {
+        return self::STATUS[$data['status']];
+    }
+
+}

+ 67 - 0
app/common/model/SettingModel.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace app\common\model;
+
+class SettingModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'setting';
+
+    // 短信配置
+    const SMS      = [
+        'sms_chuanglan_appkey',
+        'sms_chuanglan_secret',
+        'sms_type',
+        'sms_verify_expire',
+    ];
+    const SYSTEM   = [
+        'site_name',
+    ];
+    const SMS_TYPE = [
+        ['value' => '\\chuanglan\\Chuanglan', 'text' => '创蓝短信'],
+    ];
+
+    public static function getConfigValue($code)
+    {
+        $res = [];
+        if (is_array($code)) {
+            $list = self::where('code', 'in', $code)->select();
+            if ($list->isEmpty()) {
+                return [];
+            }
+            foreach ($list as $v) {
+                $res[$v['code']] = $v['value'];
+            }
+        } elseif (is_string($code)) {
+            $info = self::where('code', $code)->find();
+            if (empty($info)) {
+                return '';
+            }
+            $res = $info['value'];
+        }
+
+        return $res;
+    }
+
+    public static function setConfigValue($code, $value = '')
+    {
+        if (is_array($code)) {
+            foreach ($code as $k => $v) {
+                self::setConfigValueSingle($k, $v);
+            }
+        } elseif (is_string($code)) {
+            self::setConfigValueSingle($code, $value);
+        }
+    }
+
+    public static function setConfigValueSingle($code, $value = '')
+    {
+        $info = self::where('code', $code)->find();
+        if (empty($info)) {
+            self::create(['code' => $code, 'value' => $value]);
+        } else {
+            $info->value = $value;
+            $info->save();
+        }
+    }
+}

+ 68 - 0
app/common/model/SinglePageModel.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace app\common\model;
+
+class SinglePageModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'single_page';
+
+    // 短信配置
+    const CODE = [
+        'privacy',
+        'service',
+        'about',
+    ];
+    const CODE_TITLE = [
+        'privacy' => '隐私政策',
+        'service' => '用户协议',
+        'about' => '关于我们',
+    ];
+
+    public static function getConfigValue($code)
+    {
+        $res = [];
+        if (is_array($code)) {
+            $list = self::where('code', 'in', $code)->select();
+            if ($list->isEmpty()) {
+                return [];
+            }
+            foreach ($list as $v) {
+                $res[$v['code']] = $v['value'];
+            }
+        } elseif (is_string($code)) {
+            $info = self::where('code', $code)->find();
+            if (empty($info)) {
+                return '';
+            }
+            $res = $info['value'];
+        }
+
+        return $res;
+    }
+
+    public static function setConfigValue($code, $value = '')
+    {
+        if (is_array($code)) {
+            foreach ($code as $k => $v) {
+                self::setConfigValueSingle($k, $v);
+            }
+        } elseif (is_string($code)) {
+            self::setConfigValueSingle($code, $value);
+        }
+    }
+
+    public static function setConfigValueSingle($code, $value = '')
+    {
+        if (in_array($code,self::CODE)) {
+            $info = self::where('code', $code)->find();
+            if (empty($info)) {
+                self::create(['code' => $code, 'value' => $value]);
+            } else {
+                $info->value = $value;
+                $info->save();
+            }
+        }
+
+    }
+}

+ 29 - 0
app/common/model/SlideModel.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace app\common\model;
+
+class SlideModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'slide';
+
+    // 常量
+    const TAB    = [1 => '首页轮播图'];
+    const STATUS = [1 => '显示', 2 => '隐藏'];
+
+    const TAB_INDEX   = 1;
+    const STATUS_SHOW = 1;
+    const STATUS_HIDE = 2;
+
+    public function getTabTextAttr($value, $data)
+    {
+        return self::TAB[$data['tab']];
+    }
+
+    public function getStatusTextAttr($value, $data)
+    {
+        return self::STATUS[$data['status']];
+    }
+
+
+}

+ 10 - 0
app/common/model/SmsTemplateModel.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace app\common\model;
+
+class SmsTemplateModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'sms_template';
+
+}

+ 30 - 0
app/common/model/UserFollowModel.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace app\common\model;
+
+class UserFollowModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'user_follow';
+
+    //自动完成
+    protected $autoWriteTimestamp = true;
+
+    // 常量
+    const TYPE = [1 => '电话', 2 => '微信/QQ', 3 => '其他'];
+
+    const TYPE_MOBILE = 1;
+    const TYPE_QQ     = 2;
+    const TYPE_OTHER  = 3;
+
+    public function getTypeTextAttr($value, $data)
+    {
+        return self::TYPE[$data['type']];
+    }
+
+    public function User()
+    {
+        return $this->hasMany(UserModel::class, "id", "user_id");
+    }
+
+}

+ 55 - 0
app/common/model/UserModel.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace app\common\model;
+
+use think\model\concern\SoftDelete;
+
+class UserModel extends BaseModel
+{
+    // 设置表名
+    protected $name = 'user';
+
+    // 设置字段自动转换类型
+    protected $type = [
+        'last_login_time' => 'timestamp:Y-m-d H:i:s',
+    ];
+
+    // 软删除
+    use SoftDelete;
+    protected $deleteTime = 'delete_time';
+    protected $defaultSoftDelete = 0;
+
+    // 常量
+    const STATUS = [1 => '待审核', 2 => '已通过', 3 => '未通过', 4 => '禁用'];
+    const GENDER = ['保密', '男', '女'];
+    const AUTH   = [1 => '待认证', 2 => '待审核', 3 => '审核拒绝', 4 => '审核通过'];
+
+    const STATUS_WAIT    = 1;
+    const STATUS_PASS    = 2;
+    const STATUS_FAIL    = 3;
+    const STATUS_DISABLE = 4;
+    const GENDER_MAN     = 1;
+    const GENDER_WOMAN   = 2;
+    const AUTH_UN        = 1;
+    const AUTH_WAIT      = 2;
+    const AUTH_REJECT    = 3;
+    const AUTH_PASS      = 4;
+
+    //允许修改
+    const MOBILE_EDIT_ALLOW = ['realname', 'idcard', 'idcard_front_pic', 'idcard_back_pic', 'is_auth']; //手机端实名认证
+
+    public function getStatusTextAttr($value, $data)
+    {
+        return self::STATUS[$data['status']];
+    }
+
+    public function getGenderTextAttr($value, $data)
+    {
+        return self::GENDER[$data['gender']];
+    }
+
+    public function getIsAuthTextAttr($value, $data)
+    {
+        return self::AUTH[$data['is_auth']];
+    }
+}

+ 42 - 0
app/common/service/QrcodeService.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace app\common\service;
+
+use Endroid\QrCode\Color\Color;
+use Endroid\QrCode\Encoding\Encoding;
+use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelLow;
+use Endroid\QrCode\QrCode;
+use Endroid\QrCode\RoundBlockSizeMode\RoundBlockSizeModeMargin;
+use Endroid\QrCode\Writer\PngWriter;
+
+class QrcodeService
+{
+    public static function getQrcode($file_name, $content, $size = 150, $margin = 20)
+    {
+        //创建文件夹
+        $path = public_path() . '/storage/qrcode';
+        if (!file_exists($path)) {
+            mkdir($path);
+        }
+
+        $file_path = $path . '/' . $file_name;
+        if (!file_exists($file_path)) {
+            $writer = new PngWriter();
+            $qrCode = QrCode::create($content)
+                ->setEncoding(new Encoding('UTF-8'))
+                ->setErrorCorrectionLevel(new ErrorCorrectionLevelLow())
+                ->setSize($size)//大小
+                ->setMargin($margin)//边距
+                ->setRoundBlockSizeMode(new RoundBlockSizeModeMargin())
+                ->setForegroundColor(new Color(0, 0, 0))
+                ->setBackgroundColor(new Color(255, 255, 255));
+            $result = $writer->write($qrCode);
+            $result->getString();
+
+            $result->saveToFile($file_path);
+        }
+
+        $file_url = url('/') . '/storage/qrcode/' . $file_name;
+        return $file_url;
+    }
+}

+ 29 - 0
app/common/service/SmsService.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace app\common\service;
+
+use app\common\model\SmsTemplateModel;
+use think\facade\Log;
+
+class SmsService
+{
+    public function send($mobile, $code, $content_param = [])
+    {
+        $message = SmsTemplateModel::where('code', $code)->find();
+        if (empty($message)) {
+            Log::error('短信模板不存在:' . $code);
+            return ['code' => 1, 'msg' => '模板不存在'];
+        }
+
+        $msg = $message['content'];
+        if (!empty($content_param)) {
+            foreach ($content_param as $k => $v) {
+                $msg = str_replace('{$' . ($k + 1) . '}', $v, $msg);
+            }
+        }
+
+        $sms_obj = Config('mobile.sms_type');
+        $sms = new $sms_obj();
+        return $sms->send($mobile, ['message' => $msg]);
+    }
+}

+ 17 - 0
app/event.php

@@ -0,0 +1,17 @@
+<?php
+// 事件定义文件
+return [
+    'bind'      => [
+    ],
+
+    'listen'    => [
+        'AppInit'  => [],
+        'HttpRun'  => [],
+        'HttpEnd'  => [],
+        'LogLevel' => [],
+        'LogWrite' => [],
+    ],
+
+    'subscribe' => [
+    ],
+];

+ 10 - 0
app/middleware.php

@@ -0,0 +1,10 @@
+<?php
+// 全局中间件定义文件
+return [
+    // 全局请求缓存
+    // \think\middleware\CheckRequestCache::class,
+    // 多语言加载
+    // \think\middleware\LoadLangPack::class,
+    // Session初始化
+     \think\middleware\SessionInit::class
+];

+ 1 - 0
app/mobile/.htaccess

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

+ 23 - 0
app/mobile/MobileBaseController.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace app\mobile;
+
+use app\BaseController;
+use app\common\model\SettingModel;
+
+/**
+ * 控制器基础类
+ */
+abstract class MobileBaseController extends BaseController
+{
+    // 初始化
+    protected function initialize()
+    {
+        $setting = SettingModel::select();
+        $set     = [];
+        foreach ($setting as $v) {
+            $set[$v['code']] = $v['value'];
+        }
+        config($set, 'mobile');
+    }
+}

+ 62 - 0
app/mobile/common.php

@@ -0,0 +1,62 @@
+<?php
+// 应用公共文件
+function jump($msg = '', $url = null, $wait = 3)
+{
+    if (is_null($url)) {
+        $url = 'javascript:history.back(-1);';
+    } else {
+        $url = "location.href = '" . url($url) . "'";
+    }
+
+    $result = [
+        'msg'  => $msg,
+        'url'  => $url,
+        'wait' => $wait,
+    ];
+
+    $html = view('/public/jump', $result);
+    throw new \think\exception\HttpResponseException($html);
+}
+
+function ajax_success($data)
+{
+    $res      = ['code' => 0, 'msg' => '成功', 'data' => $data];
+    $response = \think\Response::create($res, 'json');
+    throw new \think\exception\HttpResponseException($response);
+}
+
+function get_user()
+{
+    $sessionUserId = session('mobile.user.id');
+    if (empty($sessionUserId)) {
+        if (request()->isAjax()) {
+            $res      = ['code' => 401, 'msg' => '请登录'];
+            $response = \think\Response::create($res, 'json');
+            throw new \think\exception\HttpResponseException($response);
+        } else {
+            session('back_url',request()->url());
+            $response = redirect('/mobile/login/login');
+            throw new \think\exception\HttpResponseException($response);
+        }
+    }
+
+    $user = \app\common\model\UserModel::where('id',$sessionUserId)->hidden(['password','salt'])->find();
+    if (empty($user)) {
+        jump('该用户已删除');
+    }
+    if ($user['status'] != \app\common\model\UserModel::STATUS_PASS) {
+        jump('该账号暂时无法使用');
+    }
+
+    return $user;
+}
+
+function get_user_id()
+{
+    $sessionUserId = session('mobile.user.id');
+    if (empty($sessionUserId)) {
+        return 0;
+    }
+
+    return $sessionUserId;
+}

+ 18 - 0
app/mobile/config/view.php

@@ -0,0 +1,18 @@
+<?php
+// +----------------------------------------------------------------------
+// | 模板设置
+// +----------------------------------------------------------------------
+
+return [
+    // 模板常量
+    'tpl_replace_string' => [
+        '__STATIC__'        => '/static',
+        '__COMMON_IMAGES__' => '/static/common/images',
+        '__COMMON_CSS__'    => '/static/common/css',
+        '__COMMON_JS__'     => '/static/common/js',
+        '__MIMAGES__'       => '/static/mobile/images',
+        '__MCSS__'          => '/static/mobile/css',
+        '__MJS__'           => '/static/mobile/js',
+        '__COMPONENTS__'    => '/static/mobile/js/components',
+    ],
+];

+ 49 - 0
app/mobile/controller/Article.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace app\mobile\controller;
+
+use app\common\model\ArticleCateModel;
+use app\common\model\ArticleModel;
+use app\mobile\MobileBaseController;
+
+class Article extends MobileBaseController
+{
+    public function index()
+    {
+        $cate_list = ArticleCateModel::where('status', ArticleCateModel::STATUS_SHOW)
+            ->order(['priority' => 'desc', 'id' => 'desc'])
+            ->select();
+
+        return view('', [
+            'cate_list' => $cate_list,
+            'cate_id'   => input('cate_id/d', 0),
+        ]);
+    }
+
+    public function listArticle()
+    {
+        $map = $this->dealEqualInput(['cate_id']);
+
+        $list = ArticleModel::where($map)
+            ->order(['priority' => 'desc', 'id' => 'desc'])
+            ->limit(input('limit', 10))
+            ->page(input('page', 1))
+            ->append(['type_text', 'status_text'])
+            ->select();
+
+        ajax_success($list);
+    }
+
+    public function detail()
+    {
+        $id = input('id/d', 0);
+        empty($id) && jump('该文章不存在');
+
+        $info = ArticleModel::where('status', ArticleCateModel::STATUS_SHOW)->find($id);
+        empty($info) && jump('该文章不存在');
+
+        return view('', [
+            'info' => $info,
+        ]);
+    }
+}

+ 59 - 0
app/mobile/controller/Index.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace app\mobile\controller;
+
+use app\common\model\ArticleModel;
+use app\common\model\NavigationModel;
+use app\common\model\SinglePageModel;
+use app\common\model\SlideModel;
+use app\mobile\MobileBaseController;
+
+class Index extends MobileBaseController
+{
+    public function index()
+    {
+        //轮播图
+        $slide = SlideModel::where('tab', SlideModel::TAB_INDEX)
+            ->where('status', SlideModel::STATUS_SHOW)
+            ->order(['priority' => 'desc', 'id' => 'desc'])
+            ->select();
+
+        //导航图
+        $navigation = NavigationModel::where('tab', NavigationModel::TAB_INDEX)
+            ->where('status', SlideModel::STATUS_SHOW)
+            ->order(['priority' => 'desc', 'id' => 'desc'])
+            ->select();
+
+        //文章
+        $article = ArticleModel::where('status', ArticleModel::STATUS_PUBLISH)
+            ->order(['priority' => 'desc', 'update_time' => 'desc'])
+            ->limit(5)
+            ->select();
+
+        return view('', [
+            'slide'      => $slide,
+            'navigation' => $navigation,
+            'article'    => $article,
+        ]);
+    }
+
+    public function singlePage()
+    {
+        $field = input('get.field', 'about');
+        if (!in_array($field, SinglePageModel::CODE)) {
+            jump('文章不存在');
+        }
+
+        $value   = SinglePageModel::getConfigValue($field);
+        $value   = explode("\n", $value);
+        $content = '';
+        foreach ($value as $v) {
+            $content .= "<p>{$v}</p>";
+        }
+
+        return view('', [
+            'content' => $content,
+            'title'   => SinglePageModel::CODE_TITLE[$field],
+        ]);
+    }
+}

+ 159 - 0
app/mobile/controller/Login.php

@@ -0,0 +1,159 @@
+<?php
+
+namespace app\mobile\controller;
+
+use app\common\model\SinglePageModel;
+use app\common\model\UserModel;
+use app\common\service\SmsService;
+use app\mobile\MobileBaseController;
+
+class Login extends MobileBaseController
+{
+    public function login()
+    {
+        $service = SinglePageModel::getConfigValue(['service', 'privacy']);
+        foreach ($service as $k => $value) {
+            $value   = explode("\n", $value);
+            $content = '';
+            foreach ($value as $v) {
+                $content .= "<p>{$v}</p>";
+            }
+            $service[$k] = $content;
+        }
+
+        return view('', [
+            'service' => $service,
+        ]);
+    }
+
+    public function loginPost()
+    {
+        $param = input('post.');
+        empty($param['type']) && ajax_return(1, '请选择登录方式');
+
+        $user = [];
+        if ($param['type'] == 'mobile') {
+            empty($param['mobile']) && ajax_return(1, '请输入手机号');
+            empty($param['verify']) && ajax_return(1, '请输入验证码');
+            //验证码校验
+            if (config('mobile.sms_verify_expire') > 0) {
+                $verify_expire = session('mobile.login.verify_expire');
+                if ($verify_expire + config('mobile.sms_verify_expire') < time()) {
+                    session('mobile.login.verify', null);
+                    session('mobile.login.verify_expire', null);
+                    ajax_return(1, '验证码已过期');
+                }
+            }
+            $verify = session('mobile.login.verify');
+            if ($verify != $param['verify']) {
+                ajax_return(1, '验证码不正确');
+            }
+
+            //登录注册
+            $user = UserModel::where('mobile', $param['mobile'])->find();
+            if (empty($user)) {
+                $user = UserModel::create([
+                    'nickname' => '手机用户',
+                    'mobile'   => $param['mobile'],
+                    'status'   => UserModel::STATUS_PASS,
+                ]);
+            }
+        } elseif ($param['type'] == 'account') {
+            empty($param['account']) && ajax_return(1, '请输入账号');
+            empty($param['password']) && ajax_return(1, '请输入密码');
+            //帐号密码登录
+            $user = UserModel::where('account', $param['account'])->find();
+            empty($user) && ajax_return(1, '账号或密码错误');
+
+            $password = md5(md5($user['salt']) . $param['password']);
+            $password != $user['password'] && ajax_return(1, '账号或密码错误');
+        } else {
+            ajax_return(1, '请选择登录类型');
+        }
+
+        $user->last_login_time = time();
+        $user->last_login_ip   = request()->ip();
+        $user->save();
+        session('mobile.user.id', $user['id']);
+
+        $url = session('back_url') ?? url('/mobile/my/index');
+        session('back_url', null);
+        ajax_success(['url' => $url]);
+    }
+
+    public function sendSms()
+    {
+        $mobile = trim(input('post.mobile'));
+
+        if (empty($mobile)) {
+            ajax_return(1, '手机号为空');
+        } else {
+            $rand       = rand(100000, 999999);
+            $preg_phone = '/^1[34578]\d{9}$/ims';
+            if (preg_match($preg_phone, $mobile)) {
+                $sms = new SmsService();
+                $res = $sms->send($mobile, 'verification', [$rand]);
+
+                if ($res['code'] == 0) {
+                    session('mobile.login.verify', $rand);
+                    session('mobile.login.verify_expire', time());
+                } else {
+                    ajax_return(1, '发送失败,请联系管理员');
+                }
+            } else {
+                ajax_return(1, '手机号格式不正确');
+            }
+        }
+
+        ajax_return();
+    }
+
+    public function wechat()
+    {
+        return redirect('https://www.jucai.gov.cn/api/auth/wechat_auth?url=' . urlencode(url('/mobile/login/wechatBack')));
+    }
+
+    /**
+     * 微信回调
+     */
+    public function wechatBack()
+    {
+        $param   = input('param.');
+        $open_id = $param['openid'];
+
+        //登录
+        $user = UserModel::where(['openid' => $open_id])->find();
+        if (empty($user)) {
+            $user_id = get_user_id();
+            if (empty($user_id)) {
+                $user = UserModel::create([
+                    'nickname' => $param['nickname'],
+                    'avatar'   => $param['headimgurl'],
+                    'openid'   => $open_id,
+                    'unionid'  => $param['unionid'],
+                ]);
+            } else {
+                UserModel::update([
+                    'openid'  => $open_id,
+                    'unionid' => $param['unionid'],
+                ], ['id' => $user_id]);
+            }
+        }
+
+        $user->logintime = time();
+        $user->loginip   = request()->ip();
+        $user->save();
+
+        session('mobile.user.id', $user['id']);
+        $url = session('back_url') ?? url('/mobile/my/index');
+        session('back_url', null);
+
+        return redirect($url);
+    }
+
+    public function logout()
+    {
+        session('mobile.user.id', null);
+        return redirect('/');
+    }
+}

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