lip 3 mēneši atpakaļ
vecāks
revīzija
4cab47b8c0
79 mainītis faili ar 4551 papildinājumiem un 20 dzēšanām
  1. 1 0
      .gitignore
  2. 43 0
      app/BaseController.php
  3. 238 0
      app/admin/controller/Admin.php
  4. 119 0
      app/admin/controller/Category.php
  5. 81 0
      app/admin/controller/Complaint.php
  6. 93 0
      app/admin/controller/ComplaintItem.php
  7. 65 0
      app/admin/controller/Config.php
  8. 92 0
      app/admin/controller/DedicatedLine.php
  9. 143 0
      app/admin/controller/Department.php
  10. 143 0
      app/admin/controller/Expression.php
  11. 121 0
      app/admin/controller/ExpressionCategory.php
  12. 141 0
      app/admin/controller/GuessAsk.php
  13. 120 0
      app/admin/controller/Home.php
  14. 85 0
      app/admin/controller/IpConfig.php
  15. 119 0
      app/admin/controller/Kefu.php
  16. 118 0
      app/admin/controller/Keyword.php
  17. 137 0
      app/admin/controller/Menu.php
  18. 178 0
      app/admin/controller/Question.php
  19. 140 0
      app/admin/controller/Role.php
  20. 36 0
      app/admin/controller/Upload.php
  21. 61 0
      app/admin/controller/User.php
  22. 5 0
      app/admin/middleware.php
  23. 16 0
      app/admin/model/Admin.php
  24. 16 0
      app/admin/model/Category.php
  25. 14 0
      app/admin/model/CategoryLanguages.php
  26. 19 0
      app/admin/model/Complaint.php
  27. 27 0
      app/admin/model/ComplaintItem.php
  28. 58 0
      app/admin/model/Config.php
  29. 9 0
      app/admin/model/Country.php
  30. 17 0
      app/admin/model/CountryLanguages.php
  31. 9 0
      app/admin/model/DedicatedLine.php
  32. 10 0
      app/admin/model/Department.php
  33. 9 0
      app/admin/model/Expression.php
  34. 15 0
      app/admin/model/ExpressionCategory.php
  35. 16 0
      app/admin/model/ExpressionCategoryLanguages.php
  36. 20 0
      app/admin/model/ExpressionLanguages.php
  37. 11 0
      app/admin/model/GuessAsk.php
  38. 29 0
      app/admin/model/GuessAskLanguages.php
  39. 10 0
      app/admin/model/IpConfig.php
  40. 23 0
      app/admin/model/KefuWork.php
  41. 15 0
      app/admin/model/Keyword.php
  42. 16 0
      app/admin/model/KeywordLanguages.php
  43. 11 0
      app/admin/model/Menu.php
  44. 12 0
      app/admin/model/Operation.php
  45. 21 0
      app/admin/model/Question.php
  46. 10 0
      app/admin/model/QuestionLanguages.php
  47. 33 0
      app/admin/model/Role.php
  48. 11 0
      app/admin/model/RoleMenu.php
  49. 12 0
      app/admin/model/Sign.php
  50. 55 0
      app/admin/model/User.php
  51. 151 0
      app/admin/service/JwtService.php
  52. 82 0
      app/admin/validate/AdminValidate.php
  53. 68 0
      app/admin/validate/BaseValidate.php
  54. 59 0
      app/admin/validate/CategoryValidate.php
  55. 45 0
      app/admin/validate/ComplaintItemValidate.php
  56. 43 0
      app/admin/validate/ComplaintValidate.php
  57. 61 0
      app/admin/validate/ConfigValidate.php
  58. 47 0
      app/admin/validate/DedicatedLineValidate.php
  59. 49 0
      app/admin/validate/DepartmentValidate.php
  60. 47 0
      app/admin/validate/ExpressionCategoryValidate.php
  61. 49 0
      app/admin/validate/ExpressionValidate.php
  62. 60 0
      app/admin/validate/GuessAskValidate.php
  63. 51 0
      app/admin/validate/IpConfigValidate.php
  64. 46 0
      app/admin/validate/KeywordValidate.php
  65. 61 0
      app/admin/validate/MenuValidate.php
  66. 55 0
      app/admin/validate/QuestionValidate.php
  67. 45 0
      app/admin/validate/RoleValidate.php
  68. 24 0
      app/admin/validate/User.php
  69. 213 0
      app/common.php
  70. 1 1
      app/common/controller/Pub.php
  71. 2 1
      app/common/controller/Upload.php
  72. 5 5
      app/common/listener/UserRegister.php
  73. 15 1
      app/common/middleware/CheckAuth.php
  74. 1 1
      app/index/controller/Index.php
  75. 162 0
      app/lang/en.php
  76. 162 0
      app/lang/zh-tw.php
  77. 91 0
      app/lang/zh.php
  78. 7 7
      app/manage/model/Config.php
  79. 46 4
      config/lang.php

+ 1 - 0
.gitignore

@@ -4,3 +4,4 @@ public/unpackage
 public/.htaccess
 public/h5
 vender/
+runtime/

+ 43 - 0
app/BaseController.php

@@ -9,6 +9,7 @@ use think\Validate;
 use app\manage\model\{Config};
 use think\facade\Cache;
 use thans\jwt\facade\JWTAuth;
+use think\facade\Lang;
 /**
  * 控制器基础类
  */
@@ -44,6 +45,8 @@ abstract class BaseController
      */
     protected $userInfo = [];
 
+    protected $admin_id = 0;
+
         /**
      * 接收的post数据
      * @var bool
@@ -56,6 +59,8 @@ abstract class BaseController
 
     protected $chatSetting = [];
 
+    protected $lang = 'en';
+        
     /**
      * 构造方法
      * @access public
@@ -67,12 +72,17 @@ abstract class BaseController
         $this->request = $this->app->request;
         // 控制器初始化
         $this->initialize();
+
+        $lang = request()->header('Lang', 'en');
+        $this->lang = $lang;
+        Lang::setLangSet($lang);
     }
 
     // 初始化
     protected function initialize()
     {
         $this->userInfo=$this->request->userInfo;
+        $this->admin_id = $this->request->adminInfo ? $this->request->adminInfo->id : 0;
         $this->uid=$this->userInfo['user_id'] ?? 0;
         $config=Config::getSystemInfo();
         if($config){
@@ -138,4 +148,37 @@ abstract class BaseController
         return $model->paginate($limit);
     }
 
+    protected function success($data = [], $msg = 'ok')
+    {
+        return json([
+            'code' => 0,
+            'timestamp' => time(),
+            'msg' => Lang::get($msg),
+            'data' => $data
+        ]);
+    }
+
+    /**
+     * @apiError (错误) {String} msg 错误信息
+     * @apiError (错误) {Array} [data] 数据 若code!=0 则为错误数据,code=101009 该值为验证失败的详情
+     * @apiError (错误) {Int} code 错误代码
+     * @apiVersion 1.0.0
+     */
+    protected function error(string $msg = "请求错误", $data = [], int $code = -1)
+    {
+        $code = intval($code);
+        if ($code === 0) $code = -1;
+        $a = Lang::get("{$msg}", $data);
+        if ($a == $msg) {
+            $a = $msg;
+        }
+
+        return json([
+            'code' => $code,
+            'timestamp' => time(),
+            'msg' => $a,
+            'data' => $data
+        ]);
+    }
+
 }

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

@@ -0,0 +1,238 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\Admin as AdminModel;
+use app\admin\model\RoleMenu;
+use app\admin\model\Menu;
+use think\exception\Exception;
+use think\facade\Db;
+use app\admin\validate\AdminValidate;
+use app\admin\model\User;
+use think\facade\Session;
+
+class Admin extends BaseController
+{
+    protected $noNeedLogin = ['login'];
+   
+    /**
+     * @api {get} /list 查询管理员列表
+     */
+    public function list()
+    {
+        try {
+            $params = $this->request->param();
+            $query = new AdminModel();
+            if (!empty($params['username'])) {
+                $query->where('username', 'like', "%{$params['username']}%");
+            }
+            if (!empty($params['phone'])) {
+                $query->where('phone', 'like', "%{$params['phone']}%");
+            }
+            $page = isset($params['page']) ? intval($params['page']) : 1;
+            $limit = isset($params['limit']) ? intval($params['limit']) : 15;
+
+            $count = $query->count();
+            $list = $query->with(['role', 'department'])
+                ->order('id', 'desc')
+                ->limit($limit)
+                ->page($page)
+                ->select();
+
+        } catch (\Exception $e) {
+            return $this->error('查询失败:'.$e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    /**
+     * @api {post} /update 添加/修改管理员
+     */
+    public function update()
+    {
+
+        Db::startTrans();
+        try {
+            $params = (new AdminValidate())->post()->goCheck('add');
+            
+            // 只允许超级管理员配置
+            if ($this->admin_id != 1) {
+                return $this->error('只有超级管理员才能操作');
+            }
+
+            if (empty($params['id'])) {
+                // 新增校验
+                if (empty($params['password'])) {
+                    return $this->error('密码不能为空');
+                }
+                if (empty($params['role_id'])) {
+                    return $this->error('角色ID不能为空');
+                }
+                if (empty($params['department_id'])) {
+                    return $this->error('部门ID不能为空');
+                }
+            } elseif ($params['id'] != 1) {
+                if (empty($params['role_id'])) {
+                    return $this->error('角色ID不能为空');
+                }
+                if (empty($params['department_id'])) {
+                    return $this->error('部门ID不能为空');
+                }
+            }
+
+            if (!empty($params['password'])) {
+                $params['password'] = password_hash($params['password'], PASSWORD_DEFAULT);
+            } else {
+                unset($params['password']);
+            }
+            if (!empty($params['payment_password'])) {
+                $params['payment_password'] = password_hash($params['payment_password'], PASSWORD_DEFAULT);
+            } else {
+                unset($params['payment_password']);
+            }
+
+            $usernameCount = AdminModel::where('username', $params['username'])
+                ->where('id', '<>', $params['id'] ?? 0)
+                ->count();
+            if ($usernameCount > 0) {
+                return $this->error('用户名已存在');
+            }
+
+            if (!empty($params['id'])) {
+                AdminModel::where('id', $params['id'])->update($params);
+            } else {
+                AdminModel::create($params);
+            }
+
+            Db::commit(); 
+        } catch (\Exception $e) {
+            Db::rollback();
+            return $this->error($e->getMessage());
+        }
+        return $this->success([],'操作成功');
+    }
+
+    // 删除管理员
+    public function delete()
+    {
+        try {
+            
+            $params = (new AdminValidate())->goCheck('del');
+
+            // 只允许超级管理员配置
+            if ($this->admin_id != 1) {
+                return $this->error('只有超级管理员才能操作');
+            }
+
+            if ($params['id'] == 1) {
+                return $this->error('超级管理员不能删除');
+            }
+
+            // TP 删除语法
+            AdminModel::where('id', $params['id'])->delete();
+        } catch (\Exception $e) {
+            return $this->error('删除失败:'.$e->getMessage());
+        }
+        return $this->success([],'删除成功');
+    }
+
+    /**
+     * @api {post} /setPassword 修改登录密码
+     */
+    public function setPassword()
+    {
+        Db::startTrans();
+        try {
+            $params = (new AdminValidate())->post()->goCheck('password');
+
+            $user = AdminModel::find($this->admin_id);
+            if (!$user) {
+                throw new \Exception('用户不存在');
+            }
+
+            // 校验旧密码
+            if (!password_verify($params['old_password'], $user->password)) {
+                throw new \Exception('密码错误');
+            }
+
+            // 更新登录密码
+            $user->password = password_hash($params['password'], PASSWORD_DEFAULT);
+            $user->save();
+
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollback();
+            return $this->error($e->getMessage());
+        }
+    }
+
+    /**
+     * @api {post} /login 管理员登录
+     */
+    public function login()
+    {
+        // 登录无需事务,移除多余的 Db::startTrans()
+        try {
+            $params = (new AdminValidate())->post()->goCheck('login');
+
+            $admin = AdminModel::where('username', $params['username'])->find();
+            if (!$admin) {
+                throw new \Exception('账号不存在');
+            }
+            if (!password_verify($params['password'], $admin->password)) {
+                throw new \Exception('密码错误');
+            }
+           
+            // 获取角色权限(优化 TP 查询语法)
+            if ($admin->role_id && $admin->id > 1) {
+                $admin->role_menu = RoleMenu::alias('rm')
+                    ->join('menu m', 'rm.menu_id = m.id','left')
+                    ->where('rm.role_id', $admin->role_id)
+                    ->where('m.status', 1)
+                    ->field(['m.id', 'm.parent_id', 'm.type', 'm.name', 'm.perms', 'm.paths', 'm.component', 'm.params', 'm.is_cache', 'm.sort'])
+                    ->order('m.sort', 'asc')
+                    ->select()
+                    ->toArray();
+            } else {
+                $admin->role_menu = Menu::alias('m')
+                    ->where('m.status', 1)
+                    ->field(['m.id', 'm.parent_id', 'm.type', 'm.name', 'm.perms', 'm.paths', 'm.component', 'm.params', 'm.is_cache', 'm.sort'])
+                    ->order('m.sort', 'asc')
+                    ->select()
+                    ->toArray();
+            }
+
+            //如果登录信息中含有client——id则自动进行绑定
+            $userInfo = User::where('cs_uid', $admin->id)->find();
+            if(!$userInfo){
+                throw new \Exception('用户不存在');
+            }
+            if(!empty($params['client_id'])){
+                $cid = $this->request->header('cid','');
+                doBindUid($userInfo['user_id'],$params['client_id'],$cid,$this->request->isMobile());
+            }
+            $update=[
+                'last_login_time' => time(),
+                'last_login_ip' => $this->request->ip(),
+                'login_count' => Db::raw('login_count+1')
+            ];
+            User::where('user_id',$userInfo['user_id'])->update($update);
+            $userInfo['qrUrl']=getMainHost().'/scan/u/'.encryptIds($userInfo['user_id']);
+            unset($userInfo['password'],$userInfo['salt']);
+            $userInfo['displayName']=$userInfo['realname'];
+            $userInfo['id']=$userInfo['user_id'];
+            $authToken=User::refreshToken($userInfo,$param['terminal'] ?? 'web', ['id' => $admin->id]);
+            $data=[
+                'sessionId'=>Session::getId(),
+                'token' => $authToken,
+                'userInfo'=>$userInfo,
+                'adminInfo' => $admin,
+            ];
+
+        } catch (\Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success($data);
+    }
+}

+ 119 - 0
app/admin/controller/Category.php

@@ -0,0 +1,119 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use Exception;
+use app\admin\model\Category as CategoryModel;
+use app\admin\model\CategoryLanguages;
+use app\admin\validate\CategoryValidate;
+
+/**
+ * 问题分类管理
+ */
+class Category extends BaseController
+{
+
+    /**
+     * @api {get} /category/list 列表
+     */
+    function list()
+    {
+        try {
+            $params = $this->request->param();
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $query = CategoryLanguages::where('language_code', $language_code);            
+            $count = $query->count();
+            $list = $query->where('language_code', $language_code)
+                        ->order('weight','desc')
+                        ->paginate(['list_rows'=>$limit,'page'=>$page]);
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    //新增/编辑
+    public function update()
+    { 
+        try {
+            $params = (new CategoryValidate())->sceneAdd()->goCheck();
+
+            $id = $params['id'] ?? 0;
+            $status = $params['status'] ?? 1;
+            $category_id = $params['category_id'] ?? 0;
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $exists = CategoryLanguages::where('name', $params['name'])->where('language_code', $language_code)->find();
+            if ($exists ) {
+                if (!$id || $id != $exists->id) {
+                    return $this->error('分类名称已存在');
+                }
+            }
+            if (!$category_id) {
+                $category = CategoryModel::create([
+                    'category_id' => $category_id,
+                ]);
+                $category_id = $category->id;
+            }
+            if (empty($params['id'])) {
+                $categoryLanguage = new CategoryLanguages();
+            } else {
+                $categoryLanguage = CategoryLanguages::where('id', $id)->find();
+                if (!$categoryLanguage) {
+                    return $this->error('分类不存在');
+                }
+            }
+            $categoryLanguage->category_id = $category_id;
+            $categoryLanguage->name = $params['name'];
+            $categoryLanguage->weight = $params['weight'];
+            $categoryLanguage->status = $status;
+            $categoryLanguage->language_code = $language_code;
+            $categoryLanguage->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //设置状态
+    public function setStatus()
+    {
+        try {
+            $params = (new CategoryValidate())->sceneId()->goCheck();
+            $info = CategoryLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('分类不存在');
+            }
+            $info->status = $info->status == 0 ? 1 : 0;
+            $info->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //删除
+    public function delete()
+    {
+        try {
+            $params = (new CategoryValidate())->sceneId()->goCheck();
+            $info = CategoryLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('分类不存在');
+            }
+            $category_id = $info->category_id;
+            $info->delete();
+            if (CategoryLanguages::where('category_id', $category_id)->count() == 0) {
+                CategoryModel::where('id', $category_id)->delete();
+            }
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([],'删除成功');
+    }
+
+}

+ 81 - 0
app/admin/controller/Complaint.php

@@ -0,0 +1,81 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use Exception;
+use app\admin\model\Complaint as ComplaintModel;
+use app\admin\validate\ComplaintValidate;
+
+/**
+ * 客服投诉列表
+ */
+class Complaint extends BaseController
+{
+
+    /**
+     * @api {get} /complaint/list 列表
+     */
+    function list()
+    {
+        try {
+            $params = $this->request->param();
+
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $language_code = $params['language_code'] ?? $this->lang;
+            
+            $query = ComplaintModel::alias('complaint')->join('admin', 'admin.id=complaint.kefu_id','left')
+                                    ->where('complaint.language_code', $language_code); 
+            if (!empty($params['keyword'])) {
+                $query = $query->where('admin.nickname', 'like', '%'.$params['keyword'].'%')
+                    ->whereOr('admin.phone', 'like', '%'.$params['keyword'].'%');
+            }
+            if (!empty($params['complaint_item_id'])) {
+                $query->where('complaint.complaint_item_id', $params['complaint_item_id']);
+            }
+            if (isset($params['status'])) {
+                $query->where('complaint.status', $params['status']);
+            }
+            if (!empty($params['start_time'])) {
+                $query->where('complaint.created_at', '>=', $params['start_time'] . ' 00:00:00');
+            }
+            if (!empty($params['end_time'])) {
+                $query->where('complaint.created_at', '<=', $params['end_time'] . ' 23:59:59');
+            }
+            $count = $query->count();
+            $list = $query->with(['complaint_item', 'user'])
+                        ->field(['complaint.*', 'admin.nickname','admin.phone'])
+                        ->order('complaint.created_at','desc')
+                        ->limit($limit)
+                        ->page($page)
+                        ->select();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    //编辑
+    public function update()
+    { 
+        try {
+            $params = (new ComplaintValidate())->post()->goCheck('edit');
+            $id = $params['id'] ?? 0;
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $complaint = ComplaintModel::where('id', $id)->find();
+            if (!$complaint) {
+                return $this->error('投诉项不存在');
+            }
+            $complaint->name = $params['name'];
+            $complaint->weight = $params['weight'];
+            $complaint->language_code = $language_code;
+            $complaint->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+}

+ 93 - 0
app/admin/controller/ComplaintItem.php

@@ -0,0 +1,93 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use Exception;
+use app\admin\model\ComplaintItem as ComplaintItemModel;
+use app\admin\validate\ComplaintItemValidate;
+
+/**
+ * 投诉项
+ */
+class ComplaintItem extends BaseController
+{
+
+
+    /**
+     * @api {get} /complaintitem/list 列表
+     */
+    function list()
+    {
+        try {
+            
+            $params = $this->request->param();
+            $page = isset($params['page']) ? intval($params['page']) : 1;
+            $limit = isset($params['limit']) ? intval($params['limit']) : 15;
+
+            $language_code = $params['language_code'] ?? $this->lang;
+            $query = ComplaintItemModel::where('language_code', $language_code); 
+            if (!empty($params['name'])) {
+                $query = $query->where('name', 'like', '%'.$params['name'].'%');
+            }
+            $count = $query->count();
+            $list = $query->order('weight','desc')
+                        ->limit($limit)
+                        ->page($page)
+                        ->select();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['levelList' => ComplaintItemModel::levelList(true), 'count' => $count, 'list' => $list]);
+    }
+
+    //新增/编辑
+    public function update()
+    { 
+        try {
+            $params = (new ComplaintItemValidate)->post()->goCheck('edit');
+            $id = $params['id'] ?? 0;
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $exists = ComplaintItemModel::where('name', $params['name'])->where('language_code', $language_code)->find();
+            if ($exists ) {
+                if (!$id || $id != $exists->id) {
+                    return $this->error('投诉项已存在');
+                }
+            }
+            if (empty($params['id'])) {
+                $complaintItem = new ComplaintItemModel();
+            } else {
+                $complaintItem = ComplaintItemModel::where('id', $id)->find();
+                if (!$complaintItem) {
+                    return $this->error('投诉项不存在');
+                }
+            }
+            $complaintItem->name = $params['name'];
+            $complaintItem->level = $params['level'];
+            $complaintItem->weight = $params['weight'];
+            $complaintItem->language_code = $language_code;
+            $complaintItem->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //删除
+    public function delete()
+    {
+        try {
+            $params = $params = (new ComplaintItemValidate)->goCheck('id');
+            $info = ComplaintItemModel::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('投诉项不存在');
+            }
+            $info->delete();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([],'删除成功');
+    }
+
+}

+ 65 - 0
app/admin/controller/Config.php

@@ -0,0 +1,65 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\Config as ConfigModel;
+use app\admin\validate\ConfigValidate;
+use Exception;
+use think\facade\Db;
+
+class Config extends BaseController
+{
+    
+    /**
+     * @api {get} /config/list 系统参数列表
+     *
+     */
+    public function list()
+    {
+        $flag = $this->request->param('flag', 1);
+        $list = ConfigModel::where('flag', $flag)->select();
+        $select = ConfigModel::getSelect();
+        foreach ($list as &$item) {
+            if (isset($select[$item['field']])) {
+                $item['select'] = $select[$item['field']];
+            }
+        }
+        return $this->success(['count' => count($list), 'list' => $list]);
+    }
+
+    /**
+     * @api {post} /config/update 更新系统配置
+     */
+    function update()
+    {
+        DB::startTrans();
+        try {
+            $id = $this->request->post('id');
+            if ($id) {
+                $params = (new ConfigValidate())->post()->goCheck('edit');
+            } else {
+                $params = (new ConfigValidate())->post()->goCheck('add');
+            }
+            $params['language_code'] = $params['language_code'] ?? 'zh';
+            // $params['val'] = json_encode($params['val'], JSON_UNESCAPED_UNICODE);
+
+            if (!empty($id)) {
+                $exist = ConfigModel::where('id', $id)->find();
+                if (!$exist) {
+                    return $this->error('配置不存在');
+                }
+                ConfigModel::where('id', $id)->update($params);
+            } else {
+                ConfigModel::create($params);
+            }
+            DB::commit();
+        } catch (Exception $e) {
+            DB::rollBack();
+            return $this->error($e->getMessage());
+        }
+        return $this->success();
+
+    }
+
+}

+ 92 - 0
app/admin/controller/DedicatedLine.php

@@ -0,0 +1,92 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\DedicatedLine as DedicatedLineModel;
+use app\admin\validate\DedicatedLineValidate;
+use Exception;
+
+/**
+ * 专线设置
+ */
+class DedicatedLine extends BaseController
+{
+
+    /**
+     * @api {get} /dedicatedline/list 列表
+     */
+    function list()
+    {
+        try {
+            $params = $this->request->param();
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $language_code = $params['language_code'] ?? $this->lang;
+            
+            $query = DedicatedLineModel::where('language_code', $language_code); 
+            if (!empty($params['name'])) {
+                $query = $query->where('name', 'like', '%'.$params['name'].'%');
+            }
+            $count = $query->count();
+            $list = $query->order('weight','desc')
+                        ->limit($limit)
+                        ->page($page)
+                        ->select();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    //新增/编辑
+    public function update()
+    { 
+        try {
+            $params = (new DedicatedLineValidate)->post()->goCheck('edit');
+            $id = $params['id'] ?? 0;
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $exists = DedicatedLineModel::where('name', $params['name'])->where('language_code', $language_code)->find();
+            if ($exists ) {
+                if (!$id || $id != $exists->id) {
+                    return $this->error('专线已存在');
+                }
+            }
+            if (empty($params['id'])) {
+                $dedicatedLine = new DedicatedLineModel();
+            } else {
+                $dedicatedLine = DedicatedLineModel::where('id', $id)->find();
+                if (!$dedicatedLine) {
+                    return $this->error('专线不存在');
+                }
+            }
+            $dedicatedLine->name = $params['name'];
+            $dedicatedLine->keyword = $params['keyword'] ?? '';
+            $dedicatedLine->is_rec = $params['is_rec'] ?? 0;
+            $dedicatedLine->weight = $params['weight'];
+            $dedicatedLine->language_code = $language_code;
+            $dedicatedLine->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //删除
+    public function delete()
+    {
+        try {
+            $params = (new DedicatedLineValidate)->goCheck('id');
+            $info = DedicatedLineModel::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('专线不存在');
+            }
+            $info->delete();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([],'删除成功');
+    }
+
+}

+ 143 - 0
app/admin/controller/Department.php

@@ -0,0 +1,143 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\Department as DepartmentModel;
+use app\admin\validate\DepartmentValidate;
+use app\admin\model\Admin;
+use think\facade\Db;
+
+/**
+ * @apiDefine header
+ * @apiHeader {String} Authorization Bearer token
+ */
+class Department extends BaseController
+{
+
+    //获取部门列表
+    public function list()
+    {
+        $params = $this->request->param();
+        $page = $params['page'] ?? 1;
+        $limit = $params['limit'] ?? 15;
+        $where = [];
+        if (!empty($params['name'])) {
+            $where[] = ['name', 'like', "%{$params['name']}%"];
+        }
+        if (isset($params['status']) ) {
+            $where[] = ['status', '=',$params['status']];
+        }
+        $count = DepartmentModel::where($where)->count();
+        $list = DepartmentModel::where($where)
+            ->order('parent_id','asc')
+            ->order('weight','desc')
+            ->limit($limit)
+            ->page($page)
+            ->select();
+        return $this->success([
+            'list' => $list,
+            'count' => $count,
+        ]);
+    }
+
+    
+    //获取部门树形结构
+    public function tree()
+    {
+        $list = DepartmentModel::where('status', 1)
+            ->order('parent_id', 'asc')
+            ->order('weight', 'desc')
+            ->select();   
+        $list = linear_to_tree($list);
+        return $this->success($list);
+    }
+
+    //新增或编辑部门
+    public function update()
+    {
+        try { 
+            $params = (new DepartmentValidate)->post()->goCheck('edit');
+            $id = $params['id'] ?? 0;
+            $name = $params['name'];
+            $parent_id = $params['parent_id'] ?? 0;
+            $weight = $params['weight'] ?? 1;
+            $status = $params['status'] ?? 1;
+            if ($id) {
+                $department = DepartmentModel::where('id', $id)->find();
+                if (!$department) {
+                    return $this->error('部门不存在');
+                }
+            } else {
+                $department = new DepartmentModel();
+            }
+            $department->name = $name;
+            $department->parent_id = $parent_id;
+            $department->weight = $weight;
+            $department->status = $status;
+            $department->remark = $params['remark'] ?? '';
+            $department->save();
+        } catch (\Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success($department);
+    }
+
+    //设置部门状态
+    public function setStatus()
+    {
+        $params = (new DepartmentValidate)->goCheck('id');
+        $id = $params['id'];
+        $department = DepartmentModel::where('id', $id)->find();
+        if (!$department) {
+            return $this->error('部门不存在');
+        }
+        $department->status = $department->status == 0 ? 1 : 0;
+        $department->save();
+        return $this->success($department);
+    }
+
+    public function delete() { 
+        try {
+            
+            $params = (new DepartmentValidate)->goCheck('id');
+            $id = $params['id'];
+            $department = DepartmentModel::where('id', $id)->find();
+            if (!$department) {
+                return $this->error('部门不存在');
+            }
+            //查询所有下级部门
+            $list = DepartmentModel::order('parent_id', 'asc')
+                ->order('weight', 'desc')
+                ->select();   
+            $tree = linear_to_tree($list, 'children', 'id', 'parent_id', $id);
+            
+            DB::startTrans();
+            //获取所有下级的ID
+            $ids = $this->getChildrenIds($tree);
+            $ids[] = $id;
+            $exists = Admin::whereIn('department_id', $ids)->count();
+            if ($exists) {
+                return $this->error('该部门下有用户,不能删除');
+            }
+            DepartmentModel::whereIn('id', $ids)->delete();
+            $department->delete();
+            DB::commit();
+        } catch (\Exception $e) {
+            DB::rollBack();
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '删除成功');
+    }
+    //获取所有下级的ID
+    private function getChildrenIds($sub) {
+        $ids = [];
+        foreach ($sub as $key => $value) {
+            $ids[] = $value['id'];
+            if (!empty($value['children'])) {
+                $ids = array_merge($ids, $this->getChildrenIds($value['children']));
+            }
+        }
+        return $ids;
+    }
+}

+ 143 - 0
app/admin/controller/Expression.php

@@ -0,0 +1,143 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\Expression as ExpressionModel;
+use app\admin\model\ExpressionLanguages;
+use app\admin\validate\ExpressionValidate;
+use Exception;
+
+/**
+ * 常用语管理
+ */
+class Expression extends BaseController
+{
+
+    /**
+     * @api {get} /question/list 列表
+     */
+    function list()
+    {
+        try {
+            $params = $this->request->param();
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $query = ExpressionLanguages::join('admin', 'admin.id = expression_languages.operation_id', 'left');
+            $query->where('expression_languages.language_code', $language_code);
+
+            if (!empty($params['name'])) {
+                $query->where('expression_languages.name', 'like', "%{$params['name']}%");
+            }
+            if (!empty($params['category_id'])) {
+                $query->where('expression_languages.category_id', $params['category_id']);
+            }
+            if (!empty($params['operation_name'])) {
+                $query->where('admin.nickname', 'like', "%{$params['operation_name']}%");
+            }
+            
+
+            $count = $query->count();
+            $list = $query->join('expression_category_languages', 'expression_languages.category_id = expression_category_languages.category_id', 'left')
+                        ->field(['expression_languages.*', 'expression_category_languages.name as category_name','admin.nickname as operation_name'])
+                        ->order('expression_languages.weight','desc')
+                        ->paginate(['list_rows'=>$limit,'page'=>$page]);
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    //新增/编辑
+    public function update()
+    { 
+        try {
+            $params = (new ExpressionValidate())->post()->goCheck('edit');
+            $expression_id = $params['expression_id'] ?? 0;
+            $language_code = $params['language_code'] ?? $this->lang;
+            
+            if (empty($params['id'])) {
+                $expressionLanguage = new ExpressionLanguages();
+            } else {
+                $expressionLanguage = ExpressionLanguages::where('id', $params['id'])->find();
+                if (!$expressionLanguage) {
+                    return $this->error('常用语不存在');
+                }
+            }
+
+            if (!$expression_id) {
+                $expression = ExpressionModel::create([
+                    'category_id' => $params['category_id'],
+                ]);
+                $expression_id = $expression->id;
+            }
+            $expressionLanguage->expression_id = $expression_id;
+            $expressionLanguage->category_id = $params['category_id'];
+            $expressionLanguage->name = $params['name'];
+            $expressionLanguage->img = $params['img'];
+            $expressionLanguage->weight = $params['weight'];
+            $expressionLanguage->language_code = $language_code;
+            $expressionLanguage->operation_id = $this->admin_id;
+            $expressionLanguage->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([],'保存成功');
+    }
+
+    //设置状态
+    public function setStatus()
+    {
+        try {
+            $params = (new ExpressionValidate())->goCheck('id');
+            $info = ExpressionLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('常用语不存在');
+            }
+            $info->status = $info->status == 0 ? 1 : 0;
+            $info->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //批量修改权重
+    public function setWeight()
+    {
+        try {
+            $id = $this->request->post('id');
+            $weight = $this->request->post('weight');
+            if (empty($id) || empty($weight) || !is_array($id)) {
+                return $this->error('参数错误');
+            }
+            ExpressionLanguages::whereIn('id', $id)->update(['weight' => $weight]);
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //删除
+    public function delete()
+    {
+        try {
+            $params = (new ExpressionValidate())->goCheck('id');
+            $info = ExpressionLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('常用语不存在');
+            }
+            $expression_id = $info->expression_id;
+            $info->delete();
+            if (ExpressionLanguages::where('expression_id', $expression_id)->count() == 0) {
+                ExpressionModel::where('id', $expression_id)->delete();
+            }
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '删除成功');
+    }
+
+}

+ 121 - 0
app/admin/controller/ExpressionCategory.php

@@ -0,0 +1,121 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\ExpressionCategory as ExpressionCategoryModel;
+use app\admin\model\ExpressionCategoryLanguages;
+use app\admin\validate\ExpressionCategoryValidate;
+use Exception;
+
+/**
+ * 常用语分类管理
+ */
+class ExpressionCategory extends BaseController
+{
+    
+    /**
+     * @api {get} /expressioncategory/list 列表
+     */
+    function list()
+    {
+        try {
+            $params = $this->request->param();
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $query = ExpressionCategoryLanguages::where('language_code', $language_code);            
+            if (isset($params['status'])) {
+                $query->where('status', $params['status']);
+            }
+            $count = $query->count();
+            $list = $query->where('language_code', $language_code)
+                        ->order('weight','desc')
+                        ->paginate(['list_rows'=>$limit,'page'=>$page]);
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    //新增/编辑
+    public function update()
+    { 
+        try {
+            $params = (new ExpressionCategoryValidate())->post()->goCheck('edit');
+            $id = $params['id'] ?? 0;
+            $status = $params['status'] ?? 1;
+            $category_id = $params['category_id'] ?? 0;
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $exists = ExpressionCategoryLanguages::where('name', $params['name'])->where('language_code', $language_code)->find();
+            if ($exists ) {
+                if (!$id || $id != $exists->id) {
+                    return $this->error('分类名称已存在');
+                }
+            }
+            if (!$category_id) {
+                $category = ExpressionCategoryModel::create([
+                    'category_id' => $category_id,
+                ]);
+                $category_id = $category->id;
+            }
+            if (empty($params['id'])) {
+                $categoryLanguage = new ExpressionCategoryLanguages();
+            } else {
+                $categoryLanguage = ExpressionCategoryLanguages::where('id', $id)->find();
+                if (!$categoryLanguage) {
+                    return $this->error('分类不存在');
+                }
+            }
+            $categoryLanguage->category_id = $category_id;
+            $categoryLanguage->name = $params['name'];
+            $categoryLanguage->weight = $params['weight'];
+            $categoryLanguage->status = $status;
+            $categoryLanguage->language_code = $language_code;
+            $categoryLanguage->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //设置状态
+    public function setStatus()
+    {
+        try {
+            $params = (new ExpressionCategoryValidate())->goCheck('id');
+            $info = ExpressionCategoryLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('分类不存在');
+            }
+            $info->status = $info->status == 0 ? 1 : 0;
+            $info->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //删除
+    public function delete()
+    {
+        try {
+            $params = (new ExpressionCategoryValidate())->goCheck('id');
+            $info = ExpressionCategoryLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('分类不存在');
+            }
+            $category_id = $info->category_id;
+            $info->delete();
+            if (ExpressionCategoryLanguages::where('category_id', $category_id)->count() == 0) {
+                ExpressionCategoryModel::where('id', $category_id)->delete();
+            }
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([],'删除成功');
+    }
+
+}

+ 141 - 0
app/admin/controller/GuessAsk.php

@@ -0,0 +1,141 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\GuessAsk as GuessAskModel;
+use app\admin\model\GuessAskLanguages;
+use app\admin\validate\GuessAskValidate;
+use Exception;
+
+/**
+ * 猜你想问管理
+ */
+class GuessAsk extends BaseController
+{
+
+    /**
+     * @api {get} /guessask/list 列表
+     */
+    function list()
+    {
+        try {
+            $params = $this->request->param();
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $language_code = $params['language_code'] ?? $this->lang;
+            $query = GuessAskLanguages::where('language_code', $language_code); 
+            if (!empty($params['name'])) {
+                $query = $query->where('name', 'like', '%'.$params['name'].'%');
+            }
+            if (isset($params['type']) && $params['type'] != '') {
+                $query = $query->where('type', $params['type']);
+            }
+            if (isset($params['is_rec']) && $params['is_rec'] != '') {
+                $query = $query->where('is_rec', $params['is_rec']);
+            }
+            if (isset($params['is_top']) && $params['is_top'] != '') {
+                $query = $query->where('is_top', $params['is_top']);
+            }
+            if (isset($params['status']) && $params['status'] != '') {
+                $query = $query->where('status', $params['status']);
+            }
+            $count = $query->count();
+            $list = $query->order('is_top','desc')
+                        ->order('click_num','desc')
+                        ->limit($limit)
+                        ->page($page)
+                        ->select();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        $typeList = GuessAskLanguages::typeList();
+        return $this->success(['typeList' => $typeList, 'count' => $count, 'list' => $list]);
+    }
+
+    //新增/编辑
+    public function update()
+    { 
+        try {
+            $params = $this->request->param();
+            $id = $params['id'] ?? 0;
+            $status = $params['status'] ?? 1;
+            $guess_ask_id = $params['guess_ask_id'] ?? 0;
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $exists = GuessAskLanguages::where('name', $params['name'])->where('language_code', $language_code)->find();
+            if ($exists ) {
+                if (!$id || $id != $exists->id) {
+                    return $this->error('关键词已存在');
+                }
+            }
+            if (!$guess_ask_id) {
+                $guess_ask = GuessAskModel::create([]);
+                $guess_ask_id = $guess_ask->id;
+            }
+            if (empty($params['id'])) {
+                $guessAskLanguages = new GuessAskLanguages();
+            } else {
+                $guessAskLanguages = GuessAskLanguages::where('id', $id)->find();
+                if (!$guessAskLanguages) {
+                    return $this->error('关键词不存在');
+                }
+            }
+            $guessAskLanguages->guess_ask_id = $guess_ask_id;
+            $guessAskLanguages->name = $params['name'];
+            $guessAskLanguages->type = $params['type'];
+            $guessAskLanguages->weight = $params['weight'];
+            $guessAskLanguages->status = $status;
+            $guessAskLanguages->language_code = $language_code;
+            $guessAskLanguages->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //删除
+    public function delete()
+    {
+        try {
+            $params = (new GuessAskValidate())->goCheck('id');
+            $info = GuessAskLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('猜你想问不存在');
+            }
+            $guess_ask_id = $info->guess_ask_id;
+            $info->delete();
+            if (GuessAskLanguages::where('guess_ask_id', $guess_ask_id)->count() == 0) {
+                GuessAskModel::where('id', $guess_ask_id)->delete();    
+            }
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([],'删除成功');
+    }
+    
+    //设置状态、是否推荐、是否置顶
+    public function setStatus()
+    {
+        try {
+            
+            $params = (new GuessAskValidate())->goCheck('status');
+            $info = GuessAskLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('猜你想问不存在');
+            }
+            $field = $params['field'];
+            $value = $info->$field == 0 ? 1 : 0;
+            if ($field == 'is_top' && $value == 1) {
+                GuessAskLanguages::where('is_top', 1)->update(['is_top' => 0]);
+            }
+
+            $info->$field = $value;
+            $info->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+}

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

@@ -0,0 +1,120 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\Config;
+use app\admin\model\CountryLanguages;
+use think\facade\Lang;
+
+class Home extends BaseController
+{
+
+    
+    /**
+     * @api {get} /country/list 国家|地区 列表
+     * @apiGroup 公共
+     * @apiVersion 1.0.0
+     * @apiUse lang
+     * @apiSuccess {int} id 国家ID
+     * @apiSuccess {String} country_name 国家名称
+     */
+    public function countryList()
+    {
+        $list = CountryLanguages::where('language_code', $this->lang)
+            ->order('id')
+            ->select();
+        if (count($list) < 1) {
+            $list = CountryLanguages::where('language_code', config("app.fallback_locale"))
+                ->order('id')
+                ->select(); 
+        }
+        return $this->success($list);
+    }
+    /**
+     * @api {get} /home/config 系统配置
+     */
+    function config()
+    {
+        $params = $this->request->param();
+        $params['flag'] = $params['flag'] ?? '';
+        $fields = !empty($params['fields']) ? $params['fields'] : [];
+        $list = Config::getConfigData($fields, $params['flag']);
+        return $this->success($list);
+    }
+
+    /**
+     * @api {get} /home/getLanguageCode 语言列表
+     * @apiGroup 首页
+     * @apiVersion 1.0.0
+     * @apiUse header
+     *
+     */
+    function getLanguageCode()
+    {
+        $list = [
+            [
+                'code' => 'zh',
+                'name' => '中文简体',
+                'icon' => '',
+            ], [
+                'code' => 'en',
+                'name' => '英语',
+                'icon' => '',
+            ], [
+                'code' => 'zh-tw',
+                'name' => '中文繁体',
+                'icon' => '',
+            ], [
+                'code' => 'pt',
+                'name' => '葡萄牙语',
+                'icon' => '',
+            ], [
+                'code' => 'jp',
+                'name' => '日语',
+                'icon' => '',
+            ], [
+                'code' => 'ko',
+                'name' => '韩语',
+                'icon' => '',
+            ], [
+                'code' => 'th',
+                'name' => '泰语',
+                'icon' => '',
+            ], [
+                'code' => 'id',
+                'name' => '印度尼西亚',
+                'icon' => '',
+            ], [
+                'code' => 'vi',
+                'name' => '越南语',
+                'icon' => '',
+            ], [
+                'code' => 'pt-br',
+                'name' => '巴西葡萄牙语',
+                'icon' => '',
+            ], [
+                'code' => 'hi',
+                'name' => '印地语',
+                'icon' => '',
+            ],[
+                'code' => 'en-ph',
+                'name' => '菲律宾语',
+                'icon' => '',
+            ],  [
+                'code' => 'en-in',
+                'name' => '印度英语',
+                'icon' => '',
+            ],[
+                'code' => 'tl',
+                'name' => '他加禄语',
+                'icon' => '',
+            ], 
+        ];
+        foreach ($list as &$item ) {
+            $item['name'] = Lang::get($item['name']);
+        }
+        return $this->success($list);
+    }
+
+}

+ 85 - 0
app/admin/controller/IpConfig.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\IpConfig as IpConfigModel;
+use app\admin\validate\IpConfigValidate;
+use Exception;
+use think\facade\DB;
+
+class IpConfig extends BaseController
+{
+    /**
+     * @api {post} /ip/delete IP黑名单 删除
+     *
+     */
+    function delete()
+    {
+
+        DB::startTrans();
+        try {
+            $params = (new IpConfigValidate())->post()->goCheck('id');
+            $count = IpConfigModel::where('id', $params['id'])->delete();
+            if ($count < 1) throw new Exception('操作失败');
+            DB::commit();
+        } catch (Exception $e) {
+            DB::rollBack();
+            return $this->error($e->getMessage());
+        }
+        return $this->success();
+    }
+
+
+    /**
+     * @api {post} /ip/update IP 更新
+     */
+    function update()
+    {
+        DB::startTrans();
+        try {
+
+            $params = (new IpConfigValidate())->post()->goCheck('edit');
+            $params['remark'] = request()->input('remark', '');
+            if (empty($params['remark'])) $params['remark'] = '';
+            $params['operator_id'] = $this->admin_id;
+            
+            IpConfigModel::updateOrCreate(['ip' => $params['ip']], $params);
+            DB::commit();
+        } catch (Exception $e) {
+            DB::rollBack();
+            return $this->error($e->getMessage());
+        }
+        return $this->success();
+    }
+
+    /**
+     * @api {get} /ip/index IP查询
+     */
+    function index()
+    {
+        try {
+            $params = $this->request->param();
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $query = IpConfigModel::join('kefu', 'kefu.id = ip_config.operator_id', 'left');
+            if (!empty($params['type'])) {
+                $query->where('ip_config.type', $params['type']);
+            }
+            if (!empty($params['status'])) {
+                $query->where('ip_config.status', $params['status']);
+            }
+            if (!empty($params['operator'])) {
+                $query->where('kefu.name', 'like', '%'.$params['operator'].'%');
+            }
+            $count = $query->count();
+            $list = $query
+                ->field(['ip_config.*', 'kefu.name as operator_name'])
+                ->order('updated_at','desc')
+                ->paginate(['list_rows'=>$limit,'page'=>$page]);
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+}

+ 119 - 0
app/admin/controller/Kefu.php

@@ -0,0 +1,119 @@
+<?php
+
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\Admin;
+use app\admin\model\Sign;
+use app\admin\model\KefuWork;
+use Exception;
+
+
+class Kefu extends BaseController
+{
+
+    public function statistics()
+    {
+        // 统计
+        $data['visit_count'] = 0; //当前客服页访问量
+        $data['online_count'] = 0; //当前客服在线人数
+        $data['handling_count'] = 0; //当前客服接线中的总数
+        $data['today_handling_count'] = 0; //今日客服接线总数
+
+        return $this->success($data);
+    }
+
+    /**
+     * @api {get} /today 今日在线客服列表
+     */
+    public function today()
+    {
+        try {
+            $params = $this->request->param();
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $query = Admin::alias('admin')->join('kefu_work', 'kefu_work.admin_id = admin.id', 'left');
+            if (isset($params['is_online'])) {
+                $query->where('is_online', $params['is_online']);
+            }
+
+            $count = $query->count();
+            $list = $query->field(['admin.*', 'kefu_work.chat_num','kefu_work.transfer_num','kefu_work.intervention_num','kefu_work.completed_num'])
+                        ->order('admin.id', 'asc')            
+                        ->limit($limit)
+                        ->page($page)
+                        ->select();
+            foreach ($list as &$value) {
+                $value['chat_num'] = intval($value['chat_num']);
+                $value['transfer_num'] = intval($value['transfer_num']);
+                $value['intervention_num'] = intval($value['intervention_num']);
+                $value['completed_num'] = intval($value['completed_num']);
+                $value['inprocess'] = 0;//进行中
+                $value['unprocessed'] = 0;//待处理
+            }
+            
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    /**
+     * @api {get} /list 客服数据展板列表
+     */
+    public function list()
+    {
+        try {
+            $params = $this->request->param();
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+
+            $query = KefuWork::alias('kefu_work')->join('admin', 'kefu_work.admin_id = admin.id', 'left');
+            if (isset($params['is_online'])) {
+                $query->where('is_online', $params['is_online']);
+            }
+            if (!empty($params['start_time'])) {
+                $query->where('kefu_work.created_at', '>=', $params['start_time'].'00:00:00');
+            }
+            if (!empty($params['end_time'])) {
+                $query->where('kefu_work.created_at', '<=', $params['end_time'].'23:59:59');
+            }
+
+            $count = $query->count();
+            $list = $query->field(['admin.username','admin.nickname','admin.is_online', 'kefu_work.*'])
+                        ->order('kefu_work.id', 'desc')           
+                        ->limit($limit)
+                        ->page($page)
+                        ->select();
+            foreach ($list as &$value) {
+                // $value['chat_num'] = intval($value['chat_num']);
+                // $value['transfer_num'] = intval($value['transfer_num']);
+                // $value['intervention_num'] = intval($value['intervention_num']);
+                // $value['completed_num'] = intval($value['completed_num']);
+                // $value['inprocess'] = 0;//进行中
+                // $value['unprocessed'] = 0;//待处理
+            }
+            
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    //客服签到
+    public function sign()
+    {
+        try {
+            $admin_id = $this->admin_id;
+            KefuWork::addNum($admin_id, 'sign_num');//客服签到次数更新
+            //签到记录
+            Sign::create([          
+                'admin_id' => $admin_id,
+            ]);
+        } catch (\Exception $e) {
+            return $this->error($e->getMessage());
+        }
+    }
+
+}

+ 118 - 0
app/admin/controller/Keyword.php

@@ -0,0 +1,118 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\Keyword as KeywordModel;
+use app\admin\model\KeywordLanguages;
+use app\admin\validate\KeywordValidate;
+use Exception;
+
+/**
+ * 关键词管理
+ */
+class Keyword extends BaseController
+{
+
+    /**
+     * @api {get} /category/list 列表
+     */
+    function list()
+    {
+        try {
+            $params = $this->request->param();
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $query = KeywordLanguages::where('language_code', $language_code);            
+            $count = $query->count();
+            $list = $query->where('language_code', $language_code)
+                        ->order('weight','desc')
+                        ->paginate(['list_rows'=>$limit,'page'=>$page]);
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    //新增/编辑
+    public function update()
+    { 
+        try {
+            $params = (new KeywordValidate)->post()->goCheck('edit');
+            $id = $params['id'] ?? 0;
+            $status = $params['status'] ?? 1;
+            $keyword_id = $params['keyword_id'] ?? 0;
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $exists = KeywordLanguages::where('name', $params['name'])->where('language_code', $language_code)->find();
+            if ($exists ) {
+                if (!$id || $id != $exists->id) {
+                    return $this->error('关键词已存在');
+                }
+            }
+            if (!$keyword_id) {
+                $keyword = KeywordModel::create([
+                    'keyword_id' => $keyword_id,
+                ]);
+                $keyword_id = $keyword->id;
+            }
+            if (empty($params['id'])) {
+                $keywordLanguages = new KeywordLanguages();
+            } else {
+                $keywordLanguages = KeywordLanguages::where('id', $id)->find();
+                if (!$keywordLanguages) {
+                    return $this->error('关键词不存在');
+                }
+            }
+            $keywordLanguages->keyword_id = $keyword_id;
+            $keywordLanguages->name = $params['name'];
+            $keywordLanguages->weight = $params['weight'];
+            $keywordLanguages->status = $status;
+            $keywordLanguages->language_code = $language_code;
+            $keywordLanguages->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //设置状态
+    public function setStatus()
+    {
+        try {
+            $params = (new KeywordValidate)->goCheck('id');
+            $info = KeywordLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('关键词不存在');
+            }
+            $info->status = $info->status == 0 ? 1 : 0;
+            $info->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //删除
+    public function delete()
+    {
+        try {
+            $params = (new KeywordValidate)->goCheck('id');
+            $info = KeywordLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('关键词不存在');
+            }
+            $keyword_id = $info->keyword_id;
+            $info->delete();
+            if (KeywordLanguages::where('keyword_id', $keyword_id)->count() == 0) {
+                KeywordModel::where('id', $keyword_id)->delete();
+            }
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([],'删除成功');
+    }
+
+}

+ 137 - 0
app/admin/controller/Menu.php

@@ -0,0 +1,137 @@
+<?php
+
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\Menu as MenuModel;
+use app\admin\model\RoleMenu;
+use app\admin\model\Admin;
+use app\admin\validate\MenuValidate;
+use think\facade\Db;
+
+class Menu extends BaseController
+{
+
+    /**
+     * @api {get} /menu/list 查询菜单列表
+     */
+    public function list()
+    {
+        try {
+            $count = MenuModel::count();
+            $list = MenuModel::order('sort', 'asc')
+                ->order('id', 'asc')
+                ->select();
+            
+            $list = linear_to_tree($list, 'children');
+        } catch (\Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    /**
+     * @api {get} /menu/route 获取菜单路由
+     */
+    public function route()
+    {
+        try {
+            $adminId = $this->admin_id;
+            // 缓存优化
+            $list = cache('MenuLogic:getMenuByAdminId:'.$adminId);
+            if(empty($list)){
+                $admin = Admin::where('id',$adminId)->find();
+                $where = [];
+                $where[] = ['type', 'in', [1,2]];
+                $where[] = ['is_disable', '=', 0];
+                if ($adminId != 1) {
+                    $roleMenu = RoleMenu::whereIn('role_id', $admin['role_id'])->column('menu_id');
+                    $where[] = ['id', 'in', $roleMenu];
+                }
+                $menu = MenuModel::where($where)
+                    ->order(['sort' => 'desc', 'id' => 'asc'])
+                    ->select();
+                $list = linear_to_tree($menu, 'children');
+                cache('MenuLogic:getMenuByAdminId:'.$adminId,$list);
+            }
+            
+        } catch (\Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success($list);
+    }
+
+    /**
+     * @api {get} /menu/info 菜单详情
+     */
+    public function info()
+    {
+        try {
+            $params = (new MenuValidate())->goCheck('id');
+            $detail = MenuModel::where('id', $params['id'])->find();
+            if(empty($detail)){
+                return $this->error('菜单不存在');
+            }
+        } catch (\Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success($detail);
+    }
+
+    /**
+     * @api {post} /menu/update 添加/修改
+     * @apiGroup 菜单
+     * @apiVersion 1.0.0
+     * @apiUse header
+     * @apiUse lang
+     *
+     * @apiParam {Integer} parent_id 父级ID
+     * @apiParam {String} type 类型 M:菜单 C:按钮
+     * @apiParam {String} name 名称
+     * @apiParam {String} icon 图标
+     * @apiParam {Integer} sort 排序
+     * @apiParam {String} perms 权限
+     * @apiParam {String} paths 路径
+     * @apiParam {String} component 组件
+     * @apiParam {String} params 参数
+     * @apiParam {Integer} is_cache 是否缓存:1是 0否,默认0
+     * @apiParam {Integer} status 状态: 1正常 0停用,默认1
+     */
+    public function update()
+    {
+        Db::startTrans();
+        try {
+            $params = $this->request->param();
+            $params['parent_id'] = $params['parent_id'] ?? 0;
+            $params['is_cache'] = $params['is_cache'] ?? 0;
+            $params['status'] = $params['status'] ?? 1;
+            $params['sort'] = $params['sort'] ?? 0;
+
+            if (!empty($params['id'])) {
+                MenuModel::where('id', $params['id'])->update($params);
+            } else {
+                MenuModel::create($params);
+            }
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollBack();
+            return $this->error($e->getMessage());
+        }
+        return $this->success();
+
+    }
+
+    //删除
+    public function delete()
+    {
+        try {
+            $params = (new MenuValidate())->goCheck('id');
+            MenuModel::where('id', $params['id'])->delete();
+        } catch (\Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success();
+    }
+
+}

+ 178 - 0
app/admin/controller/Question.php

@@ -0,0 +1,178 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\Question as QuestionModel;
+use app\admin\model\QuestionLanguages;
+use app\admin\validate\QuestionValidate;
+use Exception;
+
+/**
+ * 问题管理
+ */
+class Question extends BaseController
+{
+
+    /**
+     * @api {get} /question/list 列表
+     */
+    function list()
+    {
+        try {
+            $params = $this->request->param();
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $question = $params['question'] ?? '';
+            $language_code = $params['language_code'] ?? $this->lang;
+
+            $query = QuestionLanguages::alias('question_languages')->join('question', 'question.id = question_languages.question_id', 'left')
+                        ->join('keyword_languages', 'keyword_languages.id = question_languages.keyword_id', 'left');
+                        
+            if (!empty($language_code)) {
+                $query->where('question_languages.language_code', $language_code);
+            }
+            if (!empty($question)) {
+                $query->where(function ($query) use ($question) {
+                    $query->where('question_languages.question', 'like', "%{$question}%")
+                        ->whereOr('keyword_languages.name', 'like', "%{$question}%");
+                });
+            }
+            if (!empty($params['category_id'])) {
+                $query->where('question.category_id', $params['category_id']);
+            }
+            if (!empty($params['question_type'])) {
+                $query->where('question.question_type', $params['question_type']);
+            }
+            if (!empty($params['start_time'])) {
+                $query->where('question_languages.created_at', '>=', $params['start_time'].'00:00:00');
+            }
+            if (!empty($params['end_time'])) {
+                $query->where('question_languages.created_at', '<=', $params['end_time'].'23:59:59');
+            }
+
+            $count = $query->count();
+            $list = $query->join('category_languages', 'question.category_id = category_languages.category_id', 'left')
+                        ->field(['question_languages.*', 'question.question_type', 'question.category_id', 'category_languages.name as category_name', 'keyword_languages.name as keyword_name'])
+                        ->where('category_languages.language_code', $language_code)
+                        ->order('weight','desc')
+                        ->limit($limit)
+                        ->page($page)
+                        ->select();
+            $questionTypeList = QuestionModel::questionTypeList(false);
+            foreach($list as &$item) {
+                $item['question_type_text'] = $questionTypeList[$item['question_type']] ?? '';
+            }
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['questionTypeList' => QuestionModel::questionTypeList(), 'count' => $count, 'list' => $list]);
+    }
+
+    //新增/编辑
+    public function update()
+    { 
+        try {
+            $params = (new QuestionValidate)->post()->goCheck('edit');
+            $question_id = $params['question_id'] ?? 0;
+            $language_code = $params['language_code'] ?? $this->lang;
+            
+            if (empty($params['id'])) {
+                $questionLanguage = new QuestionLanguages();
+            } else {
+                $questionLanguage = QuestionLanguages::where('id', $params['id'])->find();
+                if (!$questionLanguage) {
+                    return $this->error('问题不存在');
+                }
+            }
+
+            if (!$question_id) {
+                $question = QuestionModel::create([
+                    'category_id' => $params['category_id'],
+                    'question_type' => $params['question_type'],
+                ]);
+                $question_id = $question->id;
+            }
+            $questionLanguage->question_id = $question_id;
+            $questionLanguage->question = $params['question'];
+            $questionLanguage->answer = $params['answer'];
+            $questionLanguage->keyword_id = $params['keyword_id']??0;
+            $questionLanguage->weight = $params['weight'];
+            $questionLanguage->language_code = $language_code;
+            $questionLanguage->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([],'保存成功');
+    }
+
+    //设置状态
+    public function setStatus()
+    {
+        try {
+            $params = (new QuestionValidate)->goCheck('id');
+            $info = QuestionLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('问题不存在');
+            }
+            $info->status = $info->status == 0 ? 1 : 0;
+            $info->save();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //批量修改权重
+    public function setWeight()
+    {
+        try {
+            $id = request()->post('id');
+            $weight = request()->post('weight');
+            if (empty($id) || empty($weight) || !is_array($id)) {
+                return $this->error('参数错误');
+            }
+            QuestionLanguages::whereIn('id', $id)->update(['weight' => $weight]);
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //批量修改问题类别
+    public function setQuestionType()
+    {
+        try {
+            $id = request()->post('id');
+            $question_type = request()->post('question_type');
+            if (empty($id) || empty($question_type) || !is_array($id)) {
+                return $this->error('参数错误');
+            }
+            QuestionModel::whereIn('id', $id)->update(['question_type' => $question_type]);
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '操作成功');
+    }
+
+    //删除
+    public function delete()
+    {
+        try {
+            $params = (new QuestionValidate)->goCheck('id');
+            $info = QuestionLanguages::where('id', $params['id'])->find();
+            if (!$info) {
+                return $this->error('问题不存在');
+            }
+            $question_id = $info->question_id;
+            $info->delete();
+            if (QuestionLanguages::where('question_id', $question_id)->count() == 0) {
+                QuestionModel::where('id', $question_id)->delete();
+            }
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success([], '删除成功');
+    }
+
+}

+ 140 - 0
app/admin/controller/Role.php

@@ -0,0 +1,140 @@
+<?php
+
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\Role as RoleModel;
+use app\admin\model\Admin;
+use app\admin\model\RoleMenu;
+use app\admin\validate\RoleValidate;
+use think\facade\Db;
+use think\facade\Cache;
+use Exception;
+
+class Role extends BaseController
+{
+
+    /**
+     * @api {get} /role/list 查看角色列表
+     */
+    public function list()
+    {
+        try {
+            $params = $this->request->param();
+            $query = new RoleModel();
+            if (!empty($params['name'])) {
+                $query->where('name', 'like', '%'.$params['name'].'%');
+            }
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $count = $query->count();
+            $list = $query->order('id', 'desc')
+                ->limit($limit)
+                ->page($page)
+                ->select();
+            
+        } catch (\Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    /**
+     * @api {post} /role/update 添加/修改
+     * @apiGroup 角色
+     * @apiVersion 1.0.0
+     * @apiUse header
+     * @apiUse lang
+     *
+     * 'id' => $params['id'],
+     * @apiParam {Integer} id ID
+     * @apiParam {String} name 名称
+     * @apiParam {String} desc 描述
+     */
+    public function update()
+    {
+        DB::startTrans();
+        try {
+            $params = (new RoleValidate())->post()->goCheck('edit');
+            $menuId = $params['menu_id'] ?? [];
+            $is_exists = RoleModel::where('name', $params['name'])->where('id', '<>', $params['id'] ?? 0)->find();
+            if ($is_exists) {
+                return $this->error('角色名称不可重复');
+            }
+
+            unset($params['menu_id']);
+            if (!empty($params['id'])) {    
+                //删除当前角色的菜单
+                RoleMenu::where(['role_id' => $params['id']])->delete();
+        
+                RoleModel::where('id', $params['id'])->update($params);
+                $role_id = $params['id'];
+
+                //删除角色权限的缓存
+                Cache::delete('role_menu_'.$role_id);
+            } else {
+                $role = RoleModel::create($params);
+                $role_id = $role->id;
+            }
+
+            //添加角色的权限
+            $data = [];
+            foreach ($menuId as $item) {
+                if (empty($item)) {
+                    continue;
+                }
+                $data[] = [
+                    'role_id' => $role_id,
+                    'menu_id' => $item,
+                ];
+            }
+            RoleMenu::insertAll($data);
+            DB::commit();
+        } catch (Exception $e) {
+            DB::rollBack();
+            return $this->error($e->getMessage());
+        }
+        return $this->success();
+
+    }
+
+    //删除
+    public function delete()
+    {
+        try {
+            $params = (new RoleValidate())->goCheck('id');
+
+            //校验角色是否绑定管理员
+            $count = Admin::where('role_id', $params['id'])->count();
+            if($count > 0){
+                return $this->error('该角色下有管理员,不能删除');
+            }
+            RoleModel::where('id', $params['id'])->delete();
+            
+            //删除角色权限的缓存
+            Cache::delete('role_menu_'.$params['id']);
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success();
+    }
+
+    //查看详情
+    public function info()
+    {
+        try {
+            $params = (new RoleValidate())->goCheck('id');
+            $role = RoleModel::where('id', $params['id'])->find();
+            if(empty($role)){
+                return $this->error('角色不存在');
+            }
+            //获取角色的菜单
+            $role->menu = RoleMenu::where('role_id', $params['id'])->column('menu_id');
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success($role);
+    }
+
+}

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

@@ -0,0 +1,36 @@
+<?php
+namespace app\admin\controller;
+
+
+class Upload extends \app\common\controller\Upload
+{
+    /**
+     * @api {post} /upload/image 上传图片
+     * @apiGroup Upload
+     * @apiVersion 1.0.0
+     * @apiUse header
+     * @apiUse lang
+     *
+     * @apiParam {File} file 图像文件的路径(本地路径)
+     * - 文件大小限制:最大 20MB。
+     * - 支持图像格式:`jpg`, `jpeg`, `png`,`webp`。
+     */
+    public function uploadFile()
+    {
+        $type = request()->input('type');
+        //商品分类上传图片要求尺寸是750*750
+        if ($type && $type == 'category') {
+            $image = request()->file('file');
+            if ($image && $image->isValid()) {
+                $imageSize = getimagesize($image->getRealPath());
+                $width = $imageSize[0];
+                $height = $imageSize[1];
+                if ($width != 750 || $height != 750) {
+                    return $this->error("上传文件的图片大小不合符标准,标准尺寸为750×750。");
+                }
+            }
+        }
+
+        return parent::uploadFile();
+    }
+}

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

@@ -0,0 +1,61 @@
+<?php
+
+namespace app\admin\controller;
+
+use app\BaseController;
+use app\admin\model\User as UserModel;
+use Exception;
+
+class User extends BaseController
+{
+
+    /**
+     * @api {get} /user/list 用户列表
+     */
+    function list()
+    {
+        try {
+            $params = $this->request->param();
+            $page = $params['page'] ?? 1;
+            $limit = $params['limit'] ?? 15;
+            $user_id = $params['user_id'] ?? '';
+            $name = $params['name'] ?? '';
+            
+            $query = new UserModel();
+            if (!empty($user_id)) {
+                $query = $query->where('user_id', $user_id);
+            }
+            if (!empty($name)) {
+                $query = $query->where(function ($query) use ($name) {
+                    $query->where('account', 'like', "%{$name}%")
+                        ->whereOr('phone', 'like', "%{$name}%")
+                        ->whereOr('realname', 'like', "%{$name}%");
+                });
+            }
+
+            $count = $query->count();
+            $list = $query->order('last_login_time','desc')
+                        ->limit($limit)
+                        ->page($page)
+                        ->select();
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+        return $this->success(['count' => $count, 'list' => $list]);
+    }
+
+    //设置用户状态
+    public function setStatus()
+    {
+        
+        $user_id = (int)$this->request->param('user_id');
+        $user = UserModel::where('user_id', $user_id)->find();
+        if (!$user) {
+            return $this->error('用户不存在');
+        }
+        $user->status = $user->status == 0 ? 1 : 0;
+        $user->save();
+        return $this->success($user);
+    }
+
+}

+ 5 - 0
app/admin/middleware.php

@@ -0,0 +1,5 @@
+<?php
+return [
+    // "locale",
+    // "checkAuth"
+];

+ 16 - 0
app/admin/model/Admin.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+class Admin extends BaseModel
+{
+    public function role()
+{
+    return $this->hasOne(Role::class, 'id', 'role_id')->field(['id', 'name']);
+}
+    public function department()
+    {
+        return $this->hasOne(Department::class, 'id', 'department_id')->field(['id', 'name']);
+    }
+}

+ 16 - 0
app/admin/model/Category.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+class Category extends BaseModel
+{
+    protected $autoWriteTimestamp = false;
+
+    public function languages()
+    {
+        return $this->hasMany(CategoryLanguages::class, 'category_id')
+            ->order('language_code', 'asc')
+            ->field(['category_id','language_code','name','weight','status']);
+    }
+}

+ 14 - 0
app/admin/model/CategoryLanguages.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+class CategoryLanguages  extends BaseModel
+{
+    
+    // 语言表对应分类
+    public function category()
+    {
+        return $this->belongsTo(Category::class, 'category_id');
+    }
+}

+ 19 - 0
app/admin/model/Complaint.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+class Complaint extends BaseModel
+{
+    
+    public function user()
+    {
+        return $this->hasOne(User::class, 'user_id', 'user_id')->field(['user_id','realname','account','avatar']);
+    }
+
+    public function complaintItem()
+    {
+        return $this->hasOne(ComplaintItem::class, 'id', 'complaint_item_id')->field(['id','level','name']);
+    }
+
+}

+ 27 - 0
app/admin/model/ComplaintItem.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+class ComplaintItem extends BaseModel
+{
+    
+    protected $appends = ['level_name'];
+    public function getLevelNameAttribute()
+    {
+        $levelList = self::levelList();
+        return isset($levelList[$this->level]) ? $levelList[$this->level] : '';
+    }
+    public static function levelList($select = false)
+    {
+        $levelList = [
+            1 => '一级',
+            2 => '二级',
+            3 => '三级',
+        ];
+        if ($select) {
+            return getSelectData($levelList);
+        }
+        return $levelList;
+    }
+}

+ 58 - 0
app/admin/model/Config.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+class Config extends BaseModel
+{
+
+    protected $json = ['val'];
+    protected $jsonAssoc = true;
+    
+    public static function getSelect($select = true) {
+        $data = [
+            'kefu_chat_type' => [
+                1 => '顺序分配'
+            ],
+            'user_vip_level' => [
+                1 => 1,
+                2 => 2,
+                3 => 3,
+                4 => 4,
+                5 => 5,
+                6 => 6,
+                7 => 7,
+                8 => 8,
+                9 => 9,
+            ]
+        ];
+        if ($select) {
+            foreach ($data as &$item) {
+                $item = getSelectData($item);
+            }
+        }
+        return $data;
+    }
+
+    //字段val如果是json格式,转换为数组
+    public function getValAttribute($value)
+    {
+        return $value ? json_decode($value, true) : '';
+    }
+
+    //获取配置数据
+    public static function getConfigData($fields, $flag = 1) 
+    {
+        if (!empty($fields)) {
+            $list = Config::whereIn('field',$fields)->select();
+        } else {
+            $list = Config::where('flag',$flag)->whereIn('field',$fields)->select();
+        }
+        $data = [];
+        foreach ($list as $item) {
+            $data[$item['field']] = $item['val'];
+        }
+        return $data;
+    }
+}

+ 9 - 0
app/admin/model/Country.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+class Country extends BaseModel
+{
+}

+ 17 - 0
app/admin/model/CountryLanguages.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+class CountryLanguages extends BaseModel
+{
+    public static function getAreaCode($language_code='en')
+    {
+        $country_codes = CountryLanguages::where('language_code', $language_code)
+                ->order('sort', 'desc')
+                ->field(['area_code as code','country_name as name'])
+                ->select();
+        return $country_codes;
+    }
+}

+ 9 - 0
app/admin/model/DedicatedLine.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+class DedicatedLine extends BaseModel
+{
+}

+ 10 - 0
app/admin/model/Department.php

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

+ 9 - 0
app/admin/model/Expression.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+class Expression extends BaseModel
+{
+}

+ 15 - 0
app/admin/model/ExpressionCategory.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+class ExpressionCategory extends BaseModel
+{
+    public function languages()
+    {
+        return $this->hasMany(ExpressionCategoryLanguages::class, 'category_id')
+            ->order('language_code', 'asc')
+            ->field(['category_id','language_code','name','weight','status']);
+    }
+}

+ 16 - 0
app/admin/model/ExpressionCategoryLanguages.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+
+class ExpressionCategoryLanguages  extends BaseModel
+{
+    
+    // 语言表对应分类
+    public function category()
+    {
+        return $this->belongsTo(ExpressionCategory::class, 'category_id');
+    }
+}

+ 20 - 0
app/admin/model/ExpressionLanguages.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+class ExpressionLanguages extends BaseModel
+{
+    // 表达式对应分类
+    public function category()
+    {
+        return $this->belongsTo(ExpressionCategory::class, 'category_id');
+    }
+
+    public function getImgAttribute($value)
+    {
+        return ensureUrl($value);
+    }
+
+}

+ 11 - 0
app/admin/model/GuessAsk.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+
+class GuessAsk extends BaseModel
+{
+
+}

+ 29 - 0
app/admin/model/GuessAskLanguages.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+
+class GuessAskLanguages extends BaseModel
+{
+    
+    protected $appends = ['type_text'];
+
+    public function getTypeTextAttribute()
+    {
+        $list = self::typeList(false);
+        return $list[$this->type] ?? '';
+    }
+    
+    public static function typeList($select = true)
+    {
+        $list = [
+            1 => '问题',
+        ];
+        if ($select) {
+            $list = getSelectData($list);
+        }
+        return $list;
+    }
+}

+ 10 - 0
app/admin/model/IpConfig.php

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

+ 23 - 0
app/admin/model/KefuWork.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+class KefuWork extends BaseModel
+{
+    
+    public static function addNum($admin_id, $field) {
+        $info = self::where('admin_id', $admin_id)->where("created_at", '>=', date("Y-m-d"))->find();
+        if (!$info) {
+            $info = self::create([
+                'admin_id' => $admin_id,
+                $field => 1,
+            ]);
+        } else {
+            $info->$field += 1;
+            $info->save();
+        }
+        return true;
+    }
+}

+ 15 - 0
app/admin/model/Keyword.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+class Keyword extends BaseModel
+{
+    public function languages()
+    {
+        return $this->hasMany(KeywordLanguages::class, 'keyword_id')
+            ->order('language_code', 'asc')
+            ->field(['keyword_id','language_code','name','weight','status']);
+    }
+}

+ 16 - 0
app/admin/model/KeywordLanguages.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+
+class KeywordLanguages  extends BaseModel
+{
+    
+    // 语言表对应关键词
+    public function keyword()
+    {
+        return $this->belongsTo(Keyword::class, 'keyword_id');
+    }
+}

+ 11 - 0
app/admin/model/Menu.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+
+class Menu extends BaseModel
+{
+    
+}

+ 12 - 0
app/admin/model/Operation.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+
+class Operation extends BaseModel
+{
+    
+
+}

+ 21 - 0
app/admin/model/Question.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+use think\facade\Lang;
+
+
+class Question extends BaseModel
+{
+    public static function questionTypeList($select = true)
+    {
+        $list = [
+            1 => Lang::get('通用问题'),
+        ];
+        if ($select) {
+            return getSelectData($list);
+        }
+        return $list;
+    }
+}

+ 10 - 0
app/admin/model/QuestionLanguages.php

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

+ 33 - 0
app/admin/model/Role.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+use think\facade\Cache;
+use app\admin\model\Menu; 
+
+class Role extends BaseModel
+{
+    /**
+     * 获取角色对应的权限列表(带30分钟缓存)
+     * @param int $roleId 角色ID
+     * @return array 权限标识列表
+     */
+    public static function getRoleMenu(int $roleId): array
+    {
+        // 缓存key(规范命名,避免冲突)
+        $cacheKey = "admin:role_menu:{$roleId}";
+        // 缓存有效期(30分钟,单位:秒)
+        $expire = 30 * 60;
+
+        return Cache::remember( $cacheKey,  function () use ($roleId) { 
+                return Menu::alias('m') 
+                    ->join('role_menu rm', 'm.id = rm.menu_id', 'join') 
+                    ->where('rm.role_id', $roleId)
+                    ->whereNotNull('m.perms') 
+                    ->pluck('m.perms') 
+                    ->toArray(); 
+            },$expire 
+        );
+    }
+}

+ 11 - 0
app/admin/model/RoleMenu.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+
+class RoleMenu extends BaseModel
+{
+    
+}

+ 12 - 0
app/admin/model/Sign.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+
+
+class Sign extends BaseModel
+{
+    
+
+}

+ 55 - 0
app/admin/model/User.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace app\admin\model;
+
+use app\BaseModel;
+use think\model\concern\SoftDelete;
+use thans\jwt\facade\JWTAuth;
+
+class User extends BaseModel
+{
+   use SoftDelete;
+
+   protected $pk = "user_id";
+   
+   public static $defaultField = 'user_id,realname,realname as displayName,account,avatar,name_py,email,last_login_ip';
+
+   protected $json = ['setting'];
+   protected $jsonAssoc = true;
+
+   public function getAvatarAttr($value,$data)
+    {
+        return avatarUrl($data['avatar'],$data['realname'],$data['user_id']);
+    }
+
+    public function getSettingAttr($value)
+    {
+        if (!$value) return null;
+        $setting = $value;
+        $setting['hideMessageName']= $setting['hideMessageName']=='true' ? true : false;
+        $setting['hideMessageTime']= $setting['hideMessageTime']=='true' ? true : false;
+        $setting['avatarCricle']= $setting['avatarCricle']=='true' ? true : false;
+        $setting['isVoice']= $setting['isVoice']=='true' ? true : false;
+        $setting['sendKey']=(int)$setting['sendKey'];
+        return $setting;
+    }
+
+   /**
+     * 刷新用户token 之前token将被拉黑
+     * 修改用户数据后 调用该方法 并返回前台更新token
+     * @param array $info 用户信息
+     * @param string $terminal 客户端标识
+     * @return string
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public static function refreshToken($info,$terminal, $admin = [])
+    {
+        $info      = str_encipher(json_encode($info),true, config('app.aes_token_key'));
+        $authToken = 'bearer '.JWTAuth::builder(['info' => $info, 'terminal' => $terminal]);
+        return $authToken;
+    }
+
+
+}

+ 151 - 0
app/admin/service/JwtService.php

@@ -0,0 +1,151 @@
+<?php
+
+namespace app\admin\service;
+
+use app\admin\model\User;
+use think\facade\Cache;
+use think\facade\Config;
+use think\exception\RuntimeException;
+use thans\jwt\exception\JWTException;
+use thans\jwt\facade\JWT;
+
+class JwtService
+{
+    /**
+     * Token 过期时间(秒),优先读取 jwt 配置文件
+     * @var int
+     */
+    private $exp;
+
+    public function __construct()
+    {
+        // 从 thans/jwt 配置文件读取过期时间(config/jwt.php)
+        $this->exp = Config::get('jwt.ttl', 7200);
+    }
+
+    /**
+     * 生成 JWT Token(适配 thans/jwt)
+     * @param User $user 用户模型实例
+     * @return string
+     * @throws RuntimeException
+     */
+    public function generateToken(User $user): string
+    {
+        // 严格校验参数类型
+        if (!$user instanceof User) {
+            throw new RuntimeException('生成Token失败:必须传入 User 模型实例');
+        }
+
+        try {
+            // 构建 JWT 载荷(thans/jwt 支持数组格式)
+            $payload = [
+                'sub'      => $user->id,       // 主题(用户ID)
+                'user_id'  => $user->id,       // 自定义字段:用户ID
+                'iat'      => time(),          // 签发时间
+                'exp'      => time() + $this->exp, // 过期时间
+                'iss'      => Config::get('app.app_name', 'admin_system'), // 签发者
+            ];
+
+            // 生成 Token(thans/jwt 核心方法)
+            $token = JWT::builder($payload);
+
+            // 缓存 Token(区分普通用户/商家)
+            $cacheKey = $user->is_store == 0
+                ? "user_{$user->id}_jwt"
+                : "store_{$user->id}_jwt";
+            // TP 缓存:set 方法存储,过期时间与 Token 一致
+            Cache::set($cacheKey, $token, $this->exp);
+
+            return $token;
+        } catch (JWTException $e) {
+            throw new RuntimeException('生成JWT Token失败:'.$e->getMessage());
+        }
+    }
+
+    /**
+     * 验证 JWT Token 有效性(适配 thans/jwt)
+     * @param string $token JWT Token 字符串(支持带/不带 Bearer 前缀)
+     * @return array|null 解码后的载荷数组(无效返回null)
+     */
+    public function validateToken(string $token): ?array
+    {
+        // 预处理 Token:移除 Bearer 前缀
+        $token = trim(str_replace('Bearer ', '', $token));
+
+        if (empty($token)) {
+            return null;
+        }
+
+        try {
+            // 验证并解码 Token(thans/jwt 核心方法)
+            $payload = JWT::verify($token);
+
+            // 额外校验:缓存中的 Token 是否一致(防止注销/伪造)
+            if (isset($payload['user_id'])) {
+                $user = User::find($payload['user_id']);
+                if ($user) {
+                    $cacheKey = $user->is_store == 0
+                        ? "user_{$user->id}_jwt"
+                        : "store_{$user->id}_jwt";
+                    $cacheToken = Cache::get($cacheKey);
+                    // 缓存无 Token 或不一致,视为无效
+                    if ($cacheToken !== $token) {
+                        return null;
+                    }
+                }
+            }
+
+            return (array)$payload;
+        } catch (JWTException $e) {
+            // 捕获 thans/jwt 专属异常(过期、签名错误、格式错误等)
+            return null;
+        }
+    }
+
+    /**
+     * 注销 Token(清除缓存)
+     * @param User $user 用户模型实例
+     * @return bool
+     */
+    public function invalidateToken(User $user): bool
+    {
+        $cacheKey = $user->is_store == 0
+            ? "user_{$user->id}_jwt"
+            : "store_{$user->id}_jwt";
+        return Cache::delete($cacheKey);
+    }
+
+    /**
+     * 刷新 Token(续期,thans/jwt 内置支持)
+     * @param string $oldToken 旧 Token
+     * @return string|null 新 Token(无效返回null)
+     */
+    public function refreshToken(string $oldToken): ?string
+    {
+        $oldToken = trim(str_replace('Bearer ', '', $oldToken));
+        if (empty($oldToken)) {
+            return null;
+        }
+
+        try {
+            // 验证旧 Token 并生成新 Token(自动续期)
+            $newToken = JWT::refresh($oldToken);
+
+            // 更新缓存中的 Token
+            $payload = JWT::verify($oldToken);
+            if (isset($payload['user_id'])) {
+                $user = User::find($payload['user_id']);
+                if ($user) {
+                    $cacheKey = $user->is_store == 0
+                        ? "user_{$user->id}_jwt"
+                        : "store_{$user->id}_jwt";
+                    Cache::set($cacheKey, $newToken, $this->exp);
+                }
+            }
+
+            return $newToken;
+        } catch (JWTException $e) {
+            return null;
+        }
+    }
+}

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

@@ -0,0 +1,82 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class AdminValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'username' => 'require|min:1',
+        'nickname' => 'require|min:1',
+        'password' => 'require|min:6',
+        'phone' => 'nullable|min:11',
+        'email' => 'nullable|email',
+        'sex' => 'require|in:0,1',
+        'role_id' => 'integer',
+        'department_id' => 'integer',
+        'remark' => 'length:0,100',
+        'old_password' => 'require|min:6',
+        'password_confirmation' => 'require|min:6|confirm:password',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'username' => '账号',
+        'nickname' => '昵称',
+        'password' => '密码',
+        'phone' => '手机号',
+        'email' => '邮箱',
+        'sex' => '性别',
+        'role_id' => '角色ID',
+        'department_id' => '部门ID',
+        'remark' => '备注',
+        'old_password' => '旧密码',
+        'password' => '新密码',
+        'password_confirmation' => '确认密码',
+    ];
+
+
+    /**
+     * @notes 添加场景
+     */
+    public function sceneAdd()
+    {
+        return $this->only(['username', 'nickname', 'password', 'phone', 'email', 'sex', 'role_id', 'department_id', 'remark']);
+    }
+
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['id','username', 'nickname', 'password', 'phone', 'email', 'sex', 'role_id', 'department_id', 'remark']);
+    }
+
+    public function sceneDel()
+    {
+        return $this->only(['id']);
+    }
+
+    public function scenePassword()
+    {
+        return $this->only(['old_password','password','password_confirmation']);
+    }
+
+    public function sceneLogin()
+    {
+        return $this->only(['username','password']);
+    }
+
+}

+ 68 - 0
app/admin/validate/BaseValidate.php

@@ -0,0 +1,68 @@
+<?php
+
+declare(strict_types=1);
+
+namespace app\admin\validate;
+
+use think\Validate;
+
+class BaseValidate extends Validate
+{
+    public $method = 'GET';
+
+    /**
+     * @notes 设置请求方式
+     */
+    public function post()
+    {
+        if (!$this->request->isPost()) {
+            throw new \think\exception\ValidateException('请求方式错误,请使用post请求方式');
+        }
+        $this->method = 'POST';
+        return $this;
+    }
+
+    /**
+     * @notes 设置请求方式
+     */
+    public function get()
+    {
+        if (!$this->request->isGet()) {
+            throw new \think\exception\ValidateException('请求方式错误,请使用get请求方式');
+        }
+        return $this;
+    }
+
+
+    /**
+     * @notes 切面验证接收到的参数
+     * @param null $scene 场景验证
+     * @param array $validateData 验证参数,可追加和覆盖掉接收的参数
+     * @return array
+     */
+    public function goCheck($scene = null, array $validateData = []): array
+    {
+        //接收参数
+        if ($this->method == 'GET') {
+            $params = request()->get();
+        } else {
+            $params = request()->post();
+        }
+        //合并验证参数
+        $params = array_merge($params, $validateData);
+
+        //场景
+        if ($scene) {
+            $result = $this->scene($scene)->check($params);
+        } else {
+            $result = $this->check($params);
+        }
+
+        if (!$result) {
+            $exception = is_array($this->error) ? implode(';', $this->error) : $this->error;
+            throw new \think\exception\ValidateException($exception);
+        }
+        // 3.成功返回数据
+        return $params;
+    }
+}

+ 59 - 0
app/admin/validate/CategoryValidate.php

@@ -0,0 +1,59 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class CategoryValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'category_id' => 'nullable|integer',
+        'name' => 'require|min:1',
+        'weight' => 'require|integer|min:0',
+        'status' => 'nullable|min:0',
+        'language_code' => 'nullable',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'category_id' => '分类id',
+        'name' => '分类名称',
+        'weight' => '权重',
+        'status' => '状态',
+        'language_code' => '语言',
+    ];
+
+
+    /**
+     * @notes 添加场景
+     */
+    public function sceneAdd()
+    {
+        return $this->only(['category_id', 'name', 'weight', 'status', 'language_code']);
+    }
+
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['category_id', 'name', 'weight', 'status', 'language_code']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 45 - 0
app/admin/validate/ComplaintItemValidate.php

@@ -0,0 +1,45 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class ComplaintItemValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'name' => 'require|min:1',
+        'level' => 'require|integer|min:0',
+        'weight' => 'require|integer|min:0',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'name' => '投诉项',
+        'level' => '等级',
+        'weight' => '权重',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['name', 'level', 'weight', 'language_code']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 43 - 0
app/admin/validate/ComplaintValidate.php

@@ -0,0 +1,43 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class ComplaintValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'name' => 'require|min:1',
+        'weight' => 'require|integer|min:0',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'name' => '投诉项',
+        'weight' => '权重',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['name', 'weight', 'language_code']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 61 - 0
app/admin/validate/ConfigValidate.php

@@ -0,0 +1,61 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class ConfigValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'field' => 'require|length:1,50',
+        'val' => 'require|length:0,2000',
+        'remark' => 'length:0,100',
+        'weight' => 'integer',
+        'flag' => 'require|in:0,1,2,3,4',
+        'type' => 'require',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'field' => '参数名',
+        'val' => '参数值',
+        'remark' => '备注',
+        'weight' => '权重',
+        'type' => '类型',
+        'flag' => '标志',
+        'unit' => '单位',
+        'language_code' => '语言代码',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneAdd()
+    {
+        return $this->only(['field', 'val', 'remark', 'weight', 'type', 'flag', 'unit', 'language_code']);
+    }
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['id', 'val', 'remark', 'language_code']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 47 - 0
app/admin/validate/DedicatedLineValidate.php

@@ -0,0 +1,47 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class DedicatedLineValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'name' => 'require|min:1',
+        'weight' => 'require|integer|min:0',
+        'is_rec' => 'integer|in:0,1',
+        'keyword' => 'length:0,200',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'name' => '专线名称',
+        'weight' => '权重',
+        'is_rec' => '是否推荐',
+        'keyword' => '关键词',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['name', 'weight', 'language_code','is_rec','keyword']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 49 - 0
app/admin/validate/DepartmentValidate.php

@@ -0,0 +1,49 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class DepartmentValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'name' => 'require|min:1',
+        'parent_id' => 'integer|min:0',
+        'weight' => 'require|integer|min:0',
+        'status' => 'integer|in:0,1',
+        'remark' => 'length:0,200',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'name' => '部门名称',
+        'parent_id' => '父部门ID',
+        'weight' => '权重',
+        'status' => '状态',
+        'remark' => '备注',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['name', 'parent_id', 'weight', 'status', 'remark']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 47 - 0
app/admin/validate/ExpressionCategoryValidate.php

@@ -0,0 +1,47 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class ExpressionCategoryValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'category_id' => 'require|integer|min:0',
+        'name' => 'require|min:1',
+        'weight' => 'require|integer|min:0',
+        'status' => 'integer|min:0',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'category_id' => '分类ID',
+        'name' => '常用语名称',
+        'weight' => '权重',
+        'status' => '状态',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['category_id', 'name', 'weight','status','language_code']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 49 - 0
app/admin/validate/ExpressionValidate.php

@@ -0,0 +1,49 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class ExpressionValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'expression_id' => 'integer|min:0',
+        'category_id' => 'require|integer|min:0',
+        'name' => 'require|min:1',
+        'img' => 'url',
+        'weight' => 'require|integer|min:0',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'expression_id' => '常用语ID',
+        'category_id' => '分类ID',
+        'name' => '常用语名称',
+        'img' => '图片',
+        'weight' => '权重',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['expression_id', 'category_id', 'name', 'img', 'weight','language_code']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 60 - 0
app/admin/validate/GuessAskValidate.php

@@ -0,0 +1,60 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class GuessAskValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'guess_ask_id' => 'integer|min:0',
+        'name' => 'require|min:1',
+        'type' => 'require|integer|min:0',
+        'is_rec' => 'integer|in:0,1',
+        'is_top' => 'integer|in:0,1',
+        'status' => 'integer|in:0,1',
+        'weight' => 'require|integer|min:0',
+        'field' => 'require|in:is_rec,is_top,status',
+    ];
+    
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'guess_ask_id' => 'guess_ask_id',
+        'type' => '问题类别',
+        'is_rec' => '是否推荐',
+        'is_top' => '是否置顶',
+        'status' => '状态',
+        'weight' => '权重',
+        'field' => '字段',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['guess_ask_id', 'type', 'is_rec', 'is_top', 'status', 'weight', 'language_code']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+    public function sceneStatus()
+    {
+        return $this->only(['id', 'field']);
+    }
+
+}

+ 51 - 0
app/admin/validate/IpConfigValidate.php

@@ -0,0 +1,51 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class IpConfigValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'ip' => 'require|ip',
+        'status' => 'integer|in:0,1',
+        'remark' => 'length:0,100',
+    ];
+    
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'ip' => 'IP地址',
+        'status' => '状态',
+        'remark' => '备注',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['ip', 'status', 'remark']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+    public function sceneStatus()
+    {
+        return $this->only(['id', 'field']);
+    }
+
+}

+ 46 - 0
app/admin/validate/KeywordValidate.php

@@ -0,0 +1,46 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class KeywordValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'keyword_id' => 'integer|min:0',
+        'name' => 'require|length:1,200',
+        'status' => 'integer|min:0',
+        'weight' => 'integer|min:0',
+    ];
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'keyword_id' => '关键词ID',
+        'name' => '名称',
+        'status' => '状态',
+        'weight' => '权重',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['keyword_id', 'name', 'status', 'weight','language_code']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 61 - 0
app/admin/validate/MenuValidate.php

@@ -0,0 +1,61 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class MenuValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'name' => 'require|length:1,50',
+        'parent_id' => 'integer|min:0',
+        'type' => 'require|integer|in:1,2',
+        'icon' => 'length:0,100',
+        'perms' => 'length:0,100',
+        'paths' => 'length:0,100',
+        'component' => 'length:0,100',
+        'params' => 'length:0,100',
+        'sort' => 'nteger|min:0',
+        'is_cache' => 'integer|in:0,1',
+        'status' => 'integer|in:0,1',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'name' => '菜单名称',
+        'parent_id' => '父菜单ID',
+        'type' => '菜单类型',
+        'icon' => '图标',
+        'perms' => '权限',
+        'paths' => '路径',
+        'component' => '组件',
+        'params' => '参数',
+        'sort' => '排序',
+        'is_cache' => '是否缓存',
+        'status' => '状态',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['name', 'parent_id', 'type', 'icon', 'perms', 'paths', 'component', 'params', 'sort', 'is_cache', 'status']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 55 - 0
app/admin/validate/QuestionValidate.php

@@ -0,0 +1,55 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class QuestionValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'question_id' => 'integer|min:0',
+        'category_id' => 'integer|min:0',
+        'question' => 'require|length:1,200',
+        'answer' => 'require|length:1,200',
+        'question_type' => 'require|integer',
+        'keyword_id' => 'integer|min:0',
+        'status' => 'integer|min:0',
+        'weight' => 'integer|min:0',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'question_id' => 'question_id',
+        'category_id' => '分类ID',
+        'question_type' => '问题类别',
+        'question' => '问题',
+        'answer' => '回答',
+        'keyword_id' => '关键词ID',
+        'status' => '状态',
+        'weight' => '权重',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['question_id', 'category_id', 'question_type', 'question', 'answer', 'keyword_id', 'status', 'weight','language_code']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 45 - 0
app/admin/validate/RoleValidate.php

@@ -0,0 +1,45 @@
+<?php
+
+
+namespace app\admin\validate;
+
+
+class RoleValidate extends BaseValidate
+{
+
+     /**
+      * 设置校验规则
+      * @var string[]
+      */
+    protected $rule = [
+        'id' => 'require',
+        'name' => 'require|length:1,50',
+        'desc' => 'length:0,200',
+        'menu_id' => 'require|array',
+    ];
+
+    /**
+     * 参数描述
+     * @var string[]
+     */
+    protected $field = [
+        'id' => 'id',
+        'name' => '角色名称',
+        'desc' => '角色描述',
+        'menu_id' => '菜单ID',
+    ];
+
+    /**
+     * @notes 编辑场景
+     */
+    public function sceneEdit()
+    {
+        return $this->only(['name', 'desc', 'menu_id']);
+    }
+
+    public function sceneId()
+    {
+        return $this->only(['id']);
+    }
+
+}

+ 24 - 0
app/admin/validate/User.php

@@ -0,0 +1,24 @@
+<?php
+/**
+ * lvzhe [a web admin based ThinkPHP5]
+ */
+
+namespace app\enterprise\validate;
+
+use think\Validate;
+
+class User extends Validate
+{
+    protected $rule = [
+        'account|帐号'      => 'require',
+        'password|密码'     => 'require',
+        'captcha|验证码'     => 'require|captcha',
+        'oldpassword|旧密码' => 'require',
+        'repassword|重复密码' => 'require',
+    ];
+
+    protected $scene = [
+        'password' => ['password', 'oldpassword', 'repassword'],
+        'login'    => ['account', 'password'],
+    ];
+}

+ 213 - 0
app/common.php

@@ -59,6 +59,219 @@ function ret($code, $msg = "",$data = [],$count=0, $page=0)
     return json($ret);
 }
 
+// 执行绑定
+function doBindUid($user_id,$client_id,$cid='',$isMobile = false){
+    // 如果当前ID在线,将其他地方登陆挤兑下线
+    if(Gateway::isUidOnline($user_id)){
+        wsSendMsg($user_id,'offline',['id'=>$user_id,'client_id'=>$client_id,'isMobile'=>$isMobile]);
+    }
+    Gateway::bindUid($client_id, $user_id);
+    // 查询团队,如果有团队则加入团队
+    $group=Group::getMyGroup(['gu.user_id'=>$user_id,'gu.status'=>1]);
+    if($group){
+        $group=$group->toArray();
+        $group_ids=arrayToString($group,'group_id',false);
+        foreach($group_ids as $v){
+            Gateway::joinGroup($client_id, $v); 
+        }
+    }
+    if($cid){
+        bindCid($user_id,$cid);
+    }
+    wsSendMsg(0,'isOnline',['id'=>$user_id,'is_online'=>1]);
+}
+
+function ensureUrl($url)
+    {
+        if (!filter_var($url, FILTER_VALIDATE_URL)) {
+            if (empty($url)) return $url;
+            $newUrl = config('app.url') . $url;
+            return filter_var($newUrl, FILTER_VALIDATE_URL) ? $newUrl : $url;
+        }
+        return $url;
+    }
+
+function replacePartInUrl($url)
+{
+    if (filter_var($url, FILTER_VALIDATE_URL)) {
+        $target = config('app.url');
+        return str_replace($target, '', $url);
+    }
+    return $url;
+}
+
+function getSelectData($data, $key_name = 'value', $value_name = 'label')
+{
+    $selectData = [];
+    foreach ($data as $key => $value) {
+        $selectData[] = [
+            $value_name => $value,
+            $key_name => $key,
+        ];
+    }
+    return $selectData;
+}
+
+
+if (!function_exists('linear_to_tree')) {
+    function linear_to_tree($data, $sub_key_name = 'children', $id_name = 'id', $parent_id_name = 'parent_id', $parent_id = 0)
+    {
+        $tree = [];
+        foreach ($data as $row) {
+            if ($row[$parent_id_name] == $parent_id) {
+                $temp = $row;
+                $child = linear_to_tree($data, $sub_key_name, $id_name, $parent_id_name, $row[$id_name]);
+                if ($child) {
+                    $temp[$sub_key_name] = $child;
+                }
+                $tree[] = $temp;
+            }
+        }
+        return $tree;
+    }
+}
+
+
+if (!function_exists('is_valid_date')) {
+    function is_valid_date($date)
+    {
+        // 使用正则表达式匹配 yyyy-mm-dd 格式的日期
+        return preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) === 1;
+    }
+}
+
+
+if (!function_exists('getUuid')) {
+    function getUuid()
+    {
+        // Generate 16 bytes (128 bits) of random data or use the data passed into the function.
+        $data = random_bytes(16);
+
+        // Set version to 0100
+        $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
+        // Set bits 6-7 to 10
+        $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
+
+        // Output the 36 character UUID.
+        return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
+    }
+}
+
+
+if (!function_exists('generate_random_string')) {
+    function generate_random_string(int $length = 6): string
+    {
+        $characters = '0123456789abcdefghijklmnopqrstuvwxyz';
+        $randomString = '';
+        for ($i = 0; $i < $length; $i++) {
+            $randomString .= $characters[rand(0, strlen($characters) - 1)];
+        }
+        return $randomString;
+    }
+}
+
+
+/**
+ * 辅助函数:十进制转十六进制(支持大数)
+ */
+function bcdechex($dec)
+{
+    $hex = '';
+    while (bccomp($dec, 0) > 0) {
+        $last = bcmod($dec, 16);
+        $hex = dechex($last) . $hex;
+        $dec = bcdiv($dec, 16, 0);
+    }
+    return $hex ?: '0';
+}
+
+
+function removeZero($str)
+{
+    if (empty($str)) {
+        return 0;
+    }
+    if (!is_numeric($str)) {
+        return $str;
+    }
+
+    $number = number_format($str, 10, '.', '');
+
+    // 使用 rtrim 移除末尾的零和小数点
+    return rtrim(rtrim($number, '0'), '.');
+}
+
+/**
+ * 唯一订单号
+ * @return string
+ */
+function createOrderNo(): string
+{
+    $str = microtime(true);
+    $arr = explode('.', $str);
+    $decimal = $arr[1];
+
+    return date('YmdHis') . $decimal;
+}
+
+/**
+ * 获取精度
+ * @param $number
+ * @return int
+ */
+function getScale($number): int
+{
+    if (!is_numeric($number)) {
+        return 1;
+    }
+
+    $sub = strrchr($number, ".");
+    if (empty($sub)) {
+        return 1;
+    }
+
+    $scale = strlen(substr($sub, 1));
+    if ($scale == 0) {
+        return 1;
+    }
+
+    return $scale;
+}
+
+/**
+ * 将用户名中间部分字符替换为*号
+ * @param string $username 原始用户名
+ * @param int $keepLength 前后保留的字符数量(默认1)
+ * @return string 处理后的用户名
+ */
+function maskUsername($username, $keepLength = 1) {
+    // 获取用户名长度
+    $length = mb_strlen($username, 'UTF-8');
+    
+    // 短于等于2个字符的不处理
+    if ($length <= $keepLength) {
+        return $username;
+    }
+    if ($length > 8) {
+        $keepLength = 3;
+    }
+    // 计算需要替换的字符数量
+    $replaceLength = $length - 2 * $keepLength;
+    
+    // 获取前后保留的字符
+    $prefix = mb_substr($username, 0, $keepLength, 'UTF-8');
+    $suffix = mb_substr($username, -$keepLength, $keepLength, 'UTF-8');
+    
+    // 生成替换的*号
+    $stars = str_repeat('*', 3);
+    
+    // 组合结果
+    return $prefix . $stars . $suffix;
+}
+
+
+
+
 
 /* @param string $string 原文或者密文
 * @param string $operation 操作(ENCODE | DECODE), 默认为 DECODE

+ 1 - 1
app/common/controller/Pub.php

@@ -340,7 +340,7 @@ class Pub
         Cache::set($account,$code,300);
         Cache::set($account.'_time',$code,60);
         if($acType==2){
-            $conf=Config::where(['name'=>'smtp'])->value('value');
+            $conf=Config::where(['field'=>'smtp'])->value('val');
             $conf['temp']='code';
             $mail=new \mail\Mail($conf);
             $mail->sendEmail([$account],$text,$code);

+ 2 - 1
app/common/controller/Upload.php

@@ -29,6 +29,7 @@ class Upload extends BaseController
         
     }
 
+
     /**
      * 文件上传
      */
@@ -50,7 +51,7 @@ class Upload extends BaseController
             $info['ext']     = $pathInfo['extension'];
             $info['name']    =$message['fileName'] ?? '';
         }
-        $conf=Config::where(['name'=>'fileUpload'])->value('value');
+        $conf=Config::where(['field'=>'fileUpload'])->value('val');
         if($conf['size']*1024*1024 < $info['size']){
             return shutdown(lang('file.uploadLimit',['size'=>$conf['size']]));
         }

+ 5 - 5
app/common/listener/UserRegister.php

@@ -11,12 +11,12 @@ class UserRegister
     public function handle(User $user,$data){
         try{
             // 查询相关配置信息
-            $sysInfo=Config::where(['name'=>'sysInfo'])->value('value');
+            $sysInfo=Config::where(['field'=>'sysInfo'])->value('val');
             if($sysInfo['runMode']!=2){
                 return true;
             }
             // 获取聊天设置
-            $chatInfo=Config::where(['name'=>'chatInfo'])->value('value');
+            $chatInfo=Config::where(['field'=>'chatInfo'])->value('val');
             $autoAdduser=$chatInfo['autoAddUser'] ?? [];
             $autoTask=$this->createConf();
             // 是否开启自动客服
@@ -85,7 +85,7 @@ class UserRegister
                     $autoTask['group_id']=$groupInfo['group_id'];
                 }
             }
-            Config::update(['value'=>$autoTask],['name'=>'autoTask']);
+            Config::update(['val'=>$autoTask],['field'=>'autoTask']);
             return true;
         }catch(\Exception $e){
             return shutdown($e->getMessage().$e->getLine());
@@ -95,7 +95,7 @@ class UserRegister
 
     // 创建配置文件
     public function createConf(){
-        $autoTask=Config::where(['name'=>'autoTask'])->value('value');
+        $autoTask=Config::where(['field'=>'autoTask'])->value('val');
         if($autoTask){
             return $autoTask;
         }else{
@@ -104,7 +104,7 @@ class UserRegister
                 'group_num'=>1, //群聊序号
                 'user_id'=>0,  //上一次的客服ID
             ];
-            Config::create(['name'=>'autoTask','value'=>$autoTask]);
+            Config::create(['field'=>'autoTask','val'=>$autoTask]);
             return $autoTask;
         }
     }

+ 15 - 1
app/common/middleware/CheckAuth.php

@@ -5,12 +5,21 @@ use Exception;
 use thans\jwt\exception\TokenInvalidException;
 use thans\jwt\facade\JWTAuth;
 use think\facade\Cache;
+use think\facade\Request;
 //验证权限
 class CheckAuth
 {
     public function handle($request, \Closure $next)
     {
         try {
+
+            //判断,如果当前控制的noNeedLogin 属性包含当前接口的名称,则不需要验证权限
+            // $controller = $request->controller();
+            // $action = $request->action();
+            // $noNeedLogin = $controller->noNeedLogin;
+            // if(in_array($action, $noNeedLogin)){
+            //     return $next($request);
+            // }
             $jwtData = JWTAuth::auth();
         } catch (Exception $exception) {
 
@@ -27,8 +36,12 @@ class CheckAuth
             ];
             return shutdown($errorMsgArr[$exception->getMessage()] ?? $exception->getMessage(), -1);
         }
-
+        $adminInfo = [];
+        if (!empty($jwtData['admin'])) {
+            $adminInfo = $jwtData['admin']->getValue();
+        }
         $userInfo = $jwtData['info']->getValue();
+
         //解密token中的用户信息
         $userInfo = str_encipher($userInfo,false, config('app.aes_token_key'));
 
@@ -44,6 +57,7 @@ class CheckAuth
             return shutdown(lang('user.forbid'), -1);
         }
         //已经登陆,将用户信息存入请求头
+        $request->adminInfo  = $adminInfo;
         $request->userInfo  = $userInfo;
         $request->uid       = $userInfo['id'];
         $request->userToken = JWTAuth::token()->get();

+ 1 - 1
app/index/controller/Index.php

@@ -155,7 +155,7 @@ class Index
         if($downAppUrl){
             return redirect($downAppUrl);
         }
-        $config=Config::where('name','sysInfo')->value('value');
+        $config=Config::where('field','sysInfo')->value('val');
         $android=getAppDowmUrl('android');
         $winUrl=getAppDowmUrl('windows');
         $macUrl=getAppDowmUrl('mac');

+ 162 - 0
app/lang/en.php

@@ -0,0 +1,162 @@
+<?php
+return [
+    "" => "",
+    "ok" => 'Success',
+    "OK" => "Success",
+    "请求错误" => "Request Error",
+    "用户名重复" => "Username Already Exists",
+    "路由不存在" => "Route Does Not Exist",
+    "用户不存在" => "User Does Not Exist",
+    "密码错误" => "Incorrect Password",
+    "请登录" => "Please Log In",
+    "已存在同名店铺" => 'Store with the Same Name Already Exists',
+    "请选择国家" => "Please Select a Country",
+    "邀请码无效" => "Invalid Invitation Code",
+    "商家待审核" => "Merchant Pending Review",
+    "至少提交一个参数" => "At Least One Parameter Must Be Submitted",
+    "店铺审核中,禁止此操作" => 'Store Under Review, This Operation Is Prohibited',
+    "没有找到" => "Not Found",
+    "保存失败" => "Save Failed",
+    "文件上传错误" => "File Upload Error",
+    "充值地址错误" => "Recharge Address Error",
+    "用户名已存在" => "Username Already Exists",
+    "资金密码错误" => "Fund Password Error",
+    "添加失败" => "Add Failed",
+    "余额不足" => "Insufficient Balance",
+    "上传文件的图片大小不合符标准,标准尺寸为1920×300。" => "The Uploaded Image Size Does Not Meet the Standard. Standard Size: 1920×300.",
+    "上传文件的图片大小不合符标准,标准尺寸为750×750。" => "The Uploaded Image Size Does Not Meet the Standard. Standard Size: 750×750.",
+    "上传文件的图片大小不合符标准,标准尺寸为w*h" => "The Uploaded Image Size Does Not Meet the Standard. Standard Size: :width × :height ",
+    "上传的文件无效或不存在" => "The Uploaded File Is Invalid or Does Not Exist",
+    "地址最多可设置5条" => "A Maximum of 5 Addresses Can Be Set",
+    "删除失败" => "Delete Failed",
+    "地址不存在" => "Address Does Not Exist",
+    "下单失败" => "Order Placement Failed",
+    "不支持的提现方式" => "Unsupported Withdrawal Method",
+    "您有1笔提现正在处理中" => "You Have :count Withdrawal(s) Being Processed",
+    "订单不存在" => "Order Does Not Exist",
+    "该订单状态无法操作" => "This Operation Cannot Be Performed for Order :id Due to Its Status",
+    "订单" => "Order",
+    "下单成功,等待付款" => "Order Placed Successfully, Waiting for Payment",
+    "下单成功,付款成功" => "Order Placed Successfully, Payment Completed",
+    "商家已确认,已进入备货状态" => "Merchant Confirmed, Now in Stock Preparation Status",
+    "已发货,正在运输中" => "Shipped, In Transit",
+    "发起退款申请" => "Refund Request Initiated",
+    "无法购买本店商品" => "Unable to Purchase Products from This Store",
+    "已取消" => "Cancelled",
+    "只能传递一个排序参数" => "Only One Sorting Parameter Can Be Passed",
+    "商品不存在或已下架" => "Product Does Not Exist or Has Been Removed from Shelf",
+    "店铺不存在" => "Store Does Not Exist",
+    "暂时不支持银行卡" => "Bank Card Not Supported Temporarily",
+    "参数错误" => "Parameter Error",
+    "指定参数错误" => "Parameter Error: :param",
+    "所选规格已失效" => "Selected Specification Has Expired",
+    "分类不存在" => "Category Does Not Exist",
+    "二级分类不可设置" => "Secondary Categories Cannot Be Set",
+    "登录失败" => "Login Failed",
+    "提现失败" => "Withdrawal Failed",
+    "充值失败" => "Recharge Failed",
+    "付款失败" => "Payment Failed",
+    "操作失败" => "Operation Failed",
+    "商品不可编辑" => "Product Cannot Be Edited",
+    "属性不存在" => "Attribute Does Not Exist",
+    "sku配置错误" => "SKU Configuration Error",
+    "店铺不在审核中" => "Store Not Under Review",
+    "店铺审核已通过,不可修改" => "Store Review Approved, Cannot Be Modified",
+    "区块链地址已存在"=>" :currency :network_type Already Exists",
+    "未知文件格式" => "Unknown File Format",
+    "当前订单无商品数据" => "Current Order Has No Product Data",
+    "当前订单未支付" => "Current Order Unpaid",
+    "当前订单未采购" => "Current Order Not Purchased",
+    "当前订单未到待发货状态" => "Current Order Not in Pending Shipment Status",
+    "当前订单已申请退款"    => "Refund Requested for Current Order",
+    "该商品已评价"    => "This Product Has Been Reviewed",
+    "收藏成功"  => "Collected Successfully",
+    "取消成功"  => "Cancelled Successfully",
+    "所选商品已下架,请刷新购物车" => "Selected Products Have Been Removed from Shelf, Please Refresh Cart!",
+    "账号已存在" => "Account Already Exists",
+    "部分商品已失效"    => "Some Products Have Expired",
+    "登录成功" => "Login Successful",
+    "保存成功" => "Saved Successfully",
+    "加入成功" => "Added Successfully",
+    "删除成功" => "Deleted Successfully",
+    "取消成功" => "Cancelled Successfully",
+    "申请成功" => "Applied Successfully",
+    "评价成功" => "Reviewed Successfully",
+    "确认成功" => "Confirmed Successfully",
+    "支付成功" => "Payment Successful",
+    "修改成功" => "Modified Successfully",
+    "设置成功" => "Settings Successful",
+    "提交成功" => "Submitted Successfully",
+    "添加成功" => "Added Successfully",
+    "下单成功,付款成功" => "Order Placed Successfully, Payment Completed",
+    "商家已确认,已进入备货状态" => "Merchant Confirmed, Now in Stock Preparation Status",
+    "已发货,正在运输中" => "Shipped, In Transit",
+    "快件已从仓库装出,正被送往下一站" => "Package Has Been Dispatched from Warehouse and Is Being Sent to the Next Station",
+    "货物已到达中转中心" => "Goods Have Arrived at Transit Center",
+    "货件已装载并正在发送到配送中心" => "Package Has Been Loaded and Is Being Sent to Distribution Center",
+    "货物已到达配送中心,正在分拣" => "Goods Have Arrived at Distribution Center and Are Being Sorted",
+    "快递员正在递送包裹" => "Courier Is Delivering the Package",
+    "用户签收,配送完成。" => "User Signed for Delivery, Delivery Completed.",
+    "充值订单" => "Recharge Order",
+    "提现订单" => "Withdrawal Order",
+    "商品采购" => "Product Purchase",
+    "订单购买" => "Order Purchase",
+    "商品退款" => "Product Refund",
+    "店铺直通车购买" => "Store Direct Train Purchase",
+    "直通车套餐不存在" => "Direct Train Package Does Not Exist",
+    "发放订单利润" => "Distribute Order Profits",
+    "该角色下有管理员,不能删除" => "This Role Contains Administrators and Cannot Be Deleted",
+    "角色名称不可重复" => "Role Name Cannot Be Duplicated",
+    "角色ID不能为空" => "Role ID Cannot Be Empty",
+    "角色不存在" => "Role Does Not Exist",
+    "您暂无权限" => "You Do Not Have Permission",
+    "已下架商品,不可推荐" => "Products Removed from Shelf Cannot Be Recommended",
+    "您可推荐的商品数量不足" => "Insufficient Number of Products Available for Recommendation",
+    "商品库商品已下架,店铺无法上架" => "Products in the Product Library Have Been Removed from Shelf, Stores Cannot List Them",
+    "输入的利润比或者折扣比,不符合规范,请重新填写" => "The Entered Profit Ratio or Discount Ratio Does Not Meet Specifications, Please Re-enter",
+    "邮箱格式错误" => "Incorrect Email Format",
+    "套餐不存在" => "Package Does Not Exist",
+    "套餐已下架" => "Package Has Been Removed from Shelf",
+    "只有超级管理员才能操作" => "Only Super Administrators Can Perform This Operation",
+    "超级管理员不能删除" => "Super Administrators Cannot Be Deleted",
+    "资金冻结" => "Funds Frozen",
+    "平台客服" => "Platform Customer Service",
+    "返还订单成本" => "Refund Order Cost",
+    "注册成功,请等待审核" => "Registration Successful, Please Wait for Approval",
+    "定时开始时间须小于结束时间" => "Scheduled Start Time Must Be Earlier Than End Time",
+    "定时开始时间不能小于当前时间" => "Scheduled Start Time Cannot Be Earlier Than Current Time",
+    "请先添加收货地址" => "Please Add Shipping Address First",
+    "商家审核通过天后才可下架商品" => "Merchants Can Only Take Down Products :num Days After Approval",
+    "商家审核通过天后才可删除商品" => "Merchants Can Only Delete Products :num Days After Approval",
+    "用户已审核通过,不可修改" => "User Has Been Approved and Cannot Be Modified",
+    "英语" => "English",
+    "中文简体" => "Simplified Chinese",
+    "中文繁体" => "Traditional Chinese",
+    "日语" => "Japanese",
+    "德语" => "German",
+    "越南语" => "Vietnamese",
+    "印度语" => "Hindi",
+    "印度尼西亚" => "Indonesian",
+    "菲律宾语" => "Filipino",
+    "法语" => "French",
+    "俄语" => "Russian",
+    "西班牙语" => "Spanish",
+    "葡萄牙语" => "Portuguese",
+    "意大利语" => "Italian",
+    "马来西亚语" => "Malay",
+    "南非荷兰语" => "Afrikaans",
+    "希腊语" => "Greek",
+    "土耳其语" => "Turkish",
+    "韩语" => "Korean",
+    "泰语" => "Thai",
+    "阿拉伯语" => "Arabic",
+    "商家充值自动升级" => "Merchant Recharge Automatic Upgrade",
+    "返佣时间 单位(小时),提交订单后,自动返佣所需时间" => "Commission Rebate Time Unit (Hours) - Required Time for Automatic Commission Rebate After Order Submission",
+    "商城虚拟订单自动发货时间,单位小时" => "Automatic Delivery Time for Mall Virtual Orders, Unit: Hours",
+    "商城虚拟订单自动确认,单位小时" => "Automatic Confirmation for Mall Virtual Orders, Unit: Hours",
+    "平台发货后,自动完成收货,单位天" => "Automatic Confirmation of Receipt After Platform Shipping, Unit: Days",
+    "商城订单完成收货后,自动释放冻结资金,单位小时" => "Automatic Release of Frozen Funds After Completing Receipt of Mall Orders, Unit: Hours",
+    "商城订单完成收货后,自动评论,单位天" => "Automatic Comment After Completing Receipt of Mall Orders, Unit: Days",
+    "商城订单超时未付款,自动关闭,单位小时" => "Automatic Closure of Mall Orders for Overdue Unpayment, Unit: Hours",
+    "商城订单超时未采购,自动退款,单位天" => "Automatic Refund for Mall Orders for Overdue Unpurchase, Unit: Days",
+];

+ 162 - 0
app/lang/zh-tw.php

@@ -0,0 +1,162 @@
+<?php
+return [
+    "" => "",
+    "ok" => '成功',
+    "OK" => "成功",
+    "请求错误" => "請求錯誤",
+    "用户名重复" => "用戶名重複",
+    "路由不存在" => "路由不存在",
+    "用户不存在" => "用戶不存在",
+    "密码错误" => "密碼錯誤",
+    "请登录" => "請登錄",
+    "已存在同名店铺" => '已存在同名店舖',
+    "请选择国家" => "請選擇國家",
+    "邀请码无效" => "邀請碼無效",
+    "商家待审核" => "商家待審核",
+    "至少提交一个参数" => "至少提交一個參數",
+    "店铺审核中,禁止此操作" => '店舖審核中,禁止此操作',
+    "没有找到" => "沒有找到",
+    "保存失败" => "保存失敗",
+    "文件上传错误" => "文件上傳錯誤",
+    "充值地址错误" => "充值地址錯誤",
+    "用户名已存在" => "用戶名已存在",
+    "资金密码错误" => "資金密碼錯誤",
+    "添加失败" => "添加失敗",
+    "余额不足" => "餘額不足",
+    "上传文件的图片大小不合符标准,标准尺寸为1920×300。" => "上傳文件的圖片大小不符合標準,標準尺寸為1920×300。",
+    "上传文件的图片大小不合符标准,标准尺寸为750×750。" => "上傳文件的圖片大小不符合標準,標準尺寸為750×750。",
+    "上传文件的图片大小不合符标准,标准尺寸为w*h" => "上傳文件的圖片大小不符合標準,標準尺寸為 :width × :height ",
+    "上传的文件无效或不存在" => "上傳的文件無效或不存在",
+    "地址最多可设置5条" => "地址最多可設置5條",
+    "删除失败" => "刪除失敗",
+    "地址不存在" => "地址不存在",
+    "下单失败" => "下單失敗",
+    "不支持的提现方式" => "不支持的提現方式",
+    "您有1笔提现正在处理中" => "您有 :count 筆提現正在處理中",
+    "订单不存在" => "訂單不存在",
+    "该订单状态无法操作" => " :id 該訂單狀態無法操作",
+    "订单" => "訂單",
+    "下单成功,等待付款" => "下單成功,等待付款",
+    "下单成功,付款成功" => "下單成功,付款成功",
+    "商家已确认,已进入备货状态" => "商家已確認,已進入備貨狀態",
+    "已发货,正在运输中" => "已發貨,正在運輸中",
+    "发起退款申请" => "發起退款申請",
+    "无法购买本店商品" => "無法購買本店商品",
+    "已取消" => "已取消",
+    "只能传递一个排序参数" => "只能傳遞一個排序參數",
+    "商品不存在或已下架" => "商品不存在或已下架",
+    "店铺不存在" => "店舖不存在",
+    "暂时不支持银行卡" => "暫時不支持銀行卡",
+    "参数错误" => "參數錯誤",
+    "指定参数错误" => " :param 參數錯誤",
+    "所选规格已失效" => "所選規格已失效",
+    "分类不存在" => "分類不存在",
+    "二级分类不可设置" => "二級分類不可設置",
+    "登录失败" => "登錄失敗",
+    "提现失败" => "提現失敗",
+    "充值失败" => "充值失敗",
+    "付款失败" => "付款失敗",
+    "操作失败" => "操作失敗",
+    "商品不可编辑" => "商品不可編輯",
+    "属性不存在" => "屬性不存在",
+    "sku配置错误" => "sku配置錯誤",
+    "店铺不在审核中" => "店舖不在審核中",
+    "店铺审核已通过,不可修改" => "店舖審核已通過,不可修改",
+    "区块链地址已存在"=>" :currency :network_type 已存在",
+    "未知文件格式" => "未知文件格式",
+    "当前订单无商品数据" => "當前訂單無商品數據",
+    "当前订单未支付" => "當前訂單未支付",
+    "当前订单未采购" => "當前訂單未採購",
+    "当前订单未到待发货状态" => "當前訂單未到待發貨狀態",
+    "当前订单已申请退款"    => "當前訂單已申請退款",
+    "该商品已评价"    => "該商品已評價",
+    "收藏成功"  => "收藏成功",
+    "取消成功"  => "取消成功",
+    "所选商品已下架,请刷新购物车" => "所選商品已下架,請刷新購物車!",
+    "账号已存在" => "賬號已存在",
+    "部分商品已失效"    => "部分商品已失效",
+    "登录成功" => "登錄成功",
+    "保存成功" => "保存成功",
+    "加入成功" => "加入成功",
+    "删除成功" => "刪除成功",
+    "取消成功" => "取消成功",
+    "申请成功" => "申請成功",
+    "评价成功" => "評價成功",
+    "确认成功" => "確認成功",
+    "支付成功" => "支付成功",
+    "修改成功" => "修改成功",
+    "设置成功" => "設置成功",
+    "提交成功" => "提交成功",
+    "添加成功" => "添加成功",
+    "下单成功,付款成功" => "下單成功,付款成功",
+    "商家已确认,已进入备货状态" => "商家已確認,已進入備貨狀態",
+    "已发货,正在运输中" => "已發貨,正在運輸中",
+    "快件已从仓库装出,正被送往下一站" => "快件已從倉庫裝出,正被送往下一站",
+    "货物已到达中转中心" => "貨物已到達中轉中心",
+    "货件已装载并正在发送到配送中心" => "貨件已裝載並正在發送到配送中心",
+    "货物已到达配送中心,正在分拣" => "貨物已到達配送中心,正在分揀",
+    "快递员正在递送包裹" => "快遞員正在遞送包裹",
+    "用户签收,配送完成。" => "用戶簽收,配送完成。",
+    "充值订单" => "充值訂單",
+    "提现订单" => "提現訂單",
+    "商品采购" => "商品採購",
+    "订单购买" => "訂單購買",
+    "商品退款" => "商品退款",
+    "店铺直通车购买" => "店舖直通車購買",
+    "直通车套餐不存在" => "直通車套餐不存在",
+    "发放订单利润" => "發放訂單利潤",
+    "该角色下有管理员,不能删除" => "該角色下有管理員,不能刪除",
+    "角色名称不可重复" => "角色名稱不可重複",
+    "角色ID不能为空" => "角色ID不能為空",
+    "角色不存在" => "角色不存在",
+    "您暂无权限" => "您暫無權限",
+    "已下架商品,不可推荐" => "已下架商品,不可推薦",
+    "您可推荐的商品数量不足" => "您可推薦的商品數量不足",
+    "商品库商品已下架,店铺无法上架" => "商品庫商品已下架,店舖無法上架",
+    "输入的利润比或者折扣比,不符合规范,请重新填写" => "輸入的利潤比或者折扣比,不符合規範,請重新填寫",
+    "邮箱格式错误" => "郵箱格式錯誤",
+    "套餐不存在" => "套餐不存在",
+    "套餐已下架" => "套餐已下架",
+    "只有超级管理员才能操作" => "只有超級管理員才能操作",
+    "超级管理员不能删除" => "超級管理員不能刪除",
+    "资金冻结" => "資金凍結",
+    "平台客服" => "平台客服",
+    "返还订单成本" => "返還訂單成本",
+    "注册成功,请等待审核" => "註冊成功,請等待審核",
+    "定时开始时间须小于结束时间" => "定時開始時間須小於結束時間",
+    "定时开始时间不能小于当前时间" => "定時開始時間不能小於當前時間",
+    "请先添加收货地址" => "請先添加收貨地址",
+    "商家审核通过天后才可下架商品" => "商家審核通過 :num天後才可下架商品",
+    "商家审核通过天后才可删除商品" => "商家審核通過 :num天後才可刪除商品",
+    "用户已审核通过,不可修改" => "用戶已審核通過,不可修改",
+    "英语" => "英語",
+    "中文简体" => "中文簡體",
+    "中文繁体" => "中文繁體",
+    "日语" => "日語",
+    "德语" => "德語",
+    "越南语" => "越南語",
+    "印度语" => "印度語",
+    "印度尼西亚" => "印度尼西亞",
+    "菲律宾语" => "菲律賓語",
+    "法语" => "法語",
+    "俄语" => "俄語",
+    "西班牙语" => "西班牙語",
+    "葡萄牙语" => "葡萄牙語",
+    "意大利语" => "意大利語",
+    "马来西亚语" => "馬來西亞語",
+    "南非荷兰语" => "南非荷蘭語",
+    "希腊语" => "希臘語",
+    "土耳其语" => "土耳其語",
+    "韩语" => "韓語",
+    "泰语" => "泰語",
+    "阿拉伯语" => "阿拉伯語",
+    "商家充值自动升级" => "商家充值自動升級",
+    "返佣时间 单位(小时),提交订单后,自动返佣所需时间" => "返佣時間 單位(小時),提交訂單後,自動返佣所需時間",
+    "商城虚拟订单自动发货时间,单位小时" => "商城虛擬訂單自動發貨時間,單位小時",
+    "商城虚拟订单自动确认,单位小时" => "商城虛擬訂單自動確認,單位小時",
+    "平台发货后,自动完成收货,单位天" => "平台發貨後,自動完成收貨,單位天",
+    "商城订单完成收货后,自动释放冻结资金,单位小时" => "商城訂單完成收貨後,自動釋放凍結資金,單位小時",
+    "商城虚拟订单完成收货后,自动评论,单位天" => "商城訂單完成收貨後,自動評論,單位天",
+    "商城订单超时未付款,自动关闭,单位小时" => "商城訂單超時未付款,自動關閉,單位小時",
+    "商城订单超时未采购,自动退款,单位天" => "商城訂單超時未採購,自動退款,單位天",
+];

+ 91 - 0
app/lang/zh.php

@@ -0,0 +1,91 @@
+<?php
+return [
+    "" => "",
+    "ok" => '成功',
+    "OK" => "成功",
+    "请求错误" => "请求错误",
+    "用户名重复" => "用户名重复",
+    "路由不存在" => "路由不存在",
+    "用户不存在" => "用户不存在",
+    "密码错误" => "密码错误",
+    "请登录" => "请登录3",
+    "请选择国家" => "请选择国家",
+    "没有找到" => "没有找到",
+    "保存失败" => "保存失败",
+    "文件上传错误" => "文件上传错误",
+    "用户名已存在" => "用户名已存在",
+    "添加失败" => "添加失败",
+    "删除失败" => "删除失败",
+    "已取消" => "已取消",
+    "参数错误" => "参数错误",
+    "分类不存在" => "分类不存在",
+    "二级分类不可设置" => "二级分类不可设置",
+    "登录失败" => "登录失败",
+    "操作失败" => "操作失败",
+    "未知文件格式" => "未知文件格式",
+    "取消成功"  => "取消成功",
+    "账号已存在" => "账号已存在",
+    "登录成功" => "登录成功",
+    "保存成功" => "保存成功",
+    "加入成功" => "加入成功",
+    "删除成功" => "删除成功",
+    "取消成功" => "取消成功",
+    "申请成功" => "申请成功",
+    "修改成功" => "修改成功",
+    "设置成功" => "设置成功",
+    "提交成功" => "提交成功",
+    "添加成功" => "添加成功",
+    "操作成功" => "操作成功",
+    "该角色下有管理员,不能删除" => "该角色下有管理员,不能删除",
+    "角色名称不可重复" => "角色名称不可重复",
+    "角色ID不能为空" => "角色ID不能为空",
+    "角色不存在" => "角色不存在",
+    "您暂无权限" => "您暂无权限",
+    "邮箱格式错误" => "邮箱格式错误",
+    "只有超级管理员才能操作" => "只有超级管理员才能操作",
+    "超级管理员不能删除" => "超级管理员不能删除",
+    "平台客服" => "平台客服",
+    "英语" => "英语",
+    "中文简体" => "中文简体",
+    "中文繁体" => "中文繁体",
+    "日语" => "日语",
+    "德语" => "德语",
+    "越南语" => "越南语",
+    "印度语" => "印度语",
+    "印度尼西亚" => "印度尼西亚",
+    "菲律宾语" => "菲律宾语",
+    "法语" => "法语",
+    "俄语" => "俄语",
+    "西班牙语" => "西班牙语",
+    "葡萄牙语" => "葡萄牙语",
+    "意大利语" => "意大利语",
+    "马来西亚语" => "马来西亚语",
+    "南非荷兰语" => "南非荷兰语",
+    "希腊语" => "希腊语",
+    "土耳其语" => "土耳其语",
+    "韩语" => "韩语",
+    "泰语" => "泰语",
+    "阿拉伯语" => "阿拉伯语",
+    '配置不存在' => '配置不存在',
+    '部门不存在' => '部门不存在',
+    '问题不存在' => '问题不存在',
+    '分类不存在' => '分类不存在',
+    '分类名称已存在' => '分类名称已存在',
+    '关键词已存在' => '关键词已存在',
+    '关键词不存在' => '关键词不存在',
+    '该部门下有用户,不能删除' => '该部门下有用户,不能删除',
+    '部门名称已存在' => '部门名称已存在',
+    '角色ID不能为空' => '角色ID不能为空',
+    '部门ID不能为空' => '部门ID不能为空',
+    '密码不能为空' => '密码不能为空',
+    '资金密码错误' => '资金密码错误',
+    '通用问题' => '通用问题',
+    '常用语不存在' => '常用语不存在',
+    '猜你想问不存在' => '猜你想问不存在',
+    '投诉项不存在' => '投诉项不存在',
+    '投诉项已存在' => '投诉项已存在',
+    '专线不存在' => '专线不存在',
+    '专线已存在' => '专线已存在',
+    '账号不存在' => '账号不存在',
+    '登录密码修改成功' => '登录密码修改成功',
+];

+ 7 - 7
app/manage/model/Config.php

@@ -26,17 +26,17 @@ class Config extends BaseModel
             $systemInfo=Cache::get($name);
         }else{
             $systemInfo=[];
-            $conf=Config::where([['name','in',$nameFields]])->select()->toArray();
+            $conf=Config::where([['field','in',$nameFields]])->select()->toArray();
             foreach($conf as $v){
                 $value=[];
-                if($v['name']=='fileUpload'){
-                    $value['size'] = $v['value']['size'];
-                    $value['preview'] = $v['value']['preview'];
-                    $value['fileExt'] = $v['value']['fileExt'];
+                if($v['field']=='fileUpload'){
+                    $value['size'] = $v['val']['size'];
+                    $value['preview'] = $v['val']['preview'];
+                    $value['fileExt'] = $v['val']['fileExt'];
                 }else{
-                    $value=$v['value'];
+                    $value=$v['val'];
                 }
-                $systemInfo[$v['name']]=$value;
+                $systemInfo[$v['field']]=$value;
             }
             Cache::set($name,$systemInfo,7*86400);
         }

+ 46 - 4
config/lang.php

@@ -5,9 +5,9 @@
 
 return [
     // 默认语言
-    'default_lang'    => env('lang.default_lang', 'zh-cn'),
+    'default_lang'    => env('lang.default_lang', 'en'),
     // 允许的语言列表
-    'allow_lang_list' => [],
+    'allow_lang_list' => ['zh','zh-tw','en','pt','ja','ko','th','id','vi','pt-br','hi','en-ph','en-in','tl'],
     // 多语言自动侦测变量名
     'detect_var'      => 'lang',
     // 是否使用Cookie记录
@@ -16,6 +16,48 @@ return [
     'cookie_var'      => 'think_lang',
     // 扩展语言包
     'extend_list'     => [
+        'zh'    => [
+            app()->getBasePath() . 'lang/zh.php',
+        ],
+        'zh-tw'    => [
+            app()->getBasePath() . 'lang/zh-tw.php',
+        ],
+        'en'    => [
+            app()->getBasePath() . 'lang/en.php',
+        ],
+        'pt'    => [
+            app()->getBasePath() . 'lang/pt.php',
+        ],
+        'ja'    => [
+            app()->getBasePath() . 'lang/ja.php',
+        ],
+        'ko'    => [
+            app()->getBasePath() . 'lang/ko.php',
+        ],
+        'th'    => [
+            app()->getBasePath() . 'lang/th.php',
+        ],
+        'id'    => [
+            app()->getBasePath() . 'lang/id.php',
+        ],
+        'vi'    => [
+            app()->getBasePath() . 'lang/vi.php',
+        ],
+        'pt-br'    => [
+            app()->getBasePath() . 'lang/pt-br.php',
+        ],
+        'hi'    => [
+            app()->getBasePath() . 'lang/hi.php',
+        ],
+        'en-ph'    => [
+            app()->getBasePath() . 'lang/en-ph.php',
+        ],
+        'en-in'    => [
+            app()->getBasePath() . 'lang/en-in.php',
+        ],
+        'tl'    => [
+            app()->getBasePath() . 'lang/tl.php',
+        ],
         'zh-cn'    => [
             app()->getBasePath() . 'lang/zh_cn.php',
         ],
@@ -25,8 +67,8 @@ return [
     ],
     // Accept-Language转义为对应语言包名称
     'accept_language' => [
-        'zh-Hans' => 'zh-cn',
-        'en' => 'en-us',
+        // 'zh-Hans' => 'zh-cn',
+        // 'en' => 'en-us',
     ],
     // 是否支持语言分组
     'allow_group'     => true,