Ver código fonte

帧工场更新

zxg 2 meses atrás
pai
commit
6279114bf7
76 arquivos alterados com 3051 adições e 69 exclusões
  1. 1 1
      app/controller/adminapi/admin/Login.php
  2. 1 1
      app/controller/adminapi/admin/Menu.php
  3. 140 0
      app/controller/adminapi/admin/Role.php
  4. 11 3
      app/controller/adminapi/admin/Upload.php
  5. 6 3
      app/controller/adminapi/admin/User.php
  6. 95 0
      app/controller/adminapi/attachment/Attachment.php
  7. 99 0
      app/controller/adminapi/attachment/AttachmentCategory.php
  8. 1 0
      app/controller/adminapi/cutter/CutterApply.php
  9. 91 0
      app/controller/adminapi/cutter/CutterLabel.php
  10. 1 1
      app/controller/adminapi/cutter/CutterOrder.php
  11. 13 1
      app/controller/adminapi/cutter/CutterTask.php
  12. 1 1
      app/controller/adminapi/kefu/Kefu.php
  13. 1 1
      app/controller/adminapi/user/User.php
  14. 106 0
      app/controller/adminapi/user/UserLevel.php
  15. 66 0
      app/controller/api/PublicController.php
  16. 14 2
      app/controller/api/cutter/CutterController.php
  17. 39 0
      app/controller/api/cutter/CutterLabelController.php
  18. 18 0
      app/controller/api/cutter/CutterOrderController.php
  19. 13 1
      app/controller/api/cutter/CutterTaskController.php
  20. 1 0
      app/controller/api/user/LoginController.php
  21. 18 0
      app/controller/api/user/UserController.php
  22. 19 0
      app/controller/api/user/UserExtractController.php
  23. 43 0
      app/controller/api/user/UserLevelController.php
  24. 47 4
      app/extra/basic/Dao.php
  25. 137 0
      app/extra/basic/Http.php
  26. 17 0
      app/extra/basic/Service.php
  27. 25 0
      app/extra/dao/cutter/CutterLabelDao.php
  28. 10 1
      app/extra/dao/cutter/CutterOrderDao.php
  29. 17 2
      app/extra/dao/cutter/CutterTaskDao.php
  30. 27 0
      app/extra/dao/system/SystemAttachmentCategoryDao.php
  31. 34 0
      app/extra/dao/system/SystemAttachmentDao.php
  32. 43 0
      app/extra/dao/system/SystemMenuDao.php
  33. 37 0
      app/extra/dao/system/SystemRoleDao.php
  34. 25 0
      app/extra/dao/system/SystemUserDao.php
  35. 26 0
      app/extra/dao/user/UserBillDao.php
  36. 52 0
      app/extra/dao/user/UserDao.php
  37. 26 0
      app/extra/dao/user/UserLevelDao.php
  38. 26 0
      app/extra/dao/user/UserLevelLogDao.php
  39. 1 0
      app/extra/service/basic/UploadService.php
  40. 68 0
      app/extra/service/cutter/CutterLabelService.php
  41. 16 4
      app/extra/service/cutter/CutterOrderService.php
  42. 6 0
      app/extra/service/cutter/CutterService.php
  43. 22 2
      app/extra/service/cutter/CutterTaskService.php
  44. 14 5
      app/extra/service/service/KefuService.php
  45. 18 2
      app/extra/service/system/MenuService.php
  46. 108 0
      app/extra/service/system/SystemAttachmentCategoryService.php
  47. 155 0
      app/extra/service/system/SystemAttachmentService.php
  48. 82 0
      app/extra/service/system/SystemRoleService.php
  49. 30 7
      app/extra/service/system/UserService.php
  50. 76 0
      app/extra/service/user/UserBillService.php
  51. 4 1
      app/extra/service/user/UserExtractService.php
  52. 39 0
      app/extra/service/user/UserLevelLogService.php
  53. 181 0
      app/extra/service/user/UserLevelService.php
  54. 32 4
      app/extra/service/user/UserService.php
  55. 330 0
      app/extra/tools/JingLinExtend.php
  56. 25 0
      app/extra/tools/UploadExtend.php
  57. 32 0
      app/functions.php
  58. 46 0
      app/model/cutter/CutterLabel.php
  59. 28 4
      app/model/cutter/CutterTask.php
  60. 42 0
      app/model/system/SystemAttachment.php
  61. 42 0
      app/model/system/SystemAttachmentCategory.php
  62. 42 0
      app/model/system/SystemRole.php
  63. 2 2
      app/model/system/SystemUser.php
  64. 16 0
      app/model/user/User.php
  65. 51 0
      app/model/user/UserBill.php
  66. 60 0
      app/model/user/UserLevel.php
  67. 60 0
      app/model/user/UserLevelLog.php
  68. 18 5
      app/validate/adminapi/cutter/CutterTaskValidate.php
  69. 1 0
      app/validate/adminapi/kefu/KefuValidate.php
  70. 36 0
      app/validate/adminapi/user/UserLevelValidate.php
  71. 4 4
      app/validate/api/user/CutterApplyValidate.php
  72. 12 2
      app/validate/api/user/UserExtractValidate.php
  73. 2 2
      app/validate/system/UserValidate.php
  74. 1 1
      config/plugin/shopwwi/auth/app.php
  75. 1 1
      config/plugin/webman/redis-queue/redis.php
  76. 1 1
      windows.bat

+ 1 - 1
app/controller/adminapi/admin/Login.php

@@ -59,7 +59,7 @@ class Login extends Base
         if ($user->isEmpty()) return [0,trans("error.user-empty"),[]];
         if ($user['status'] <> 1) return [0,trans("error.user-status"),[]];
         if ($type == 2) {
-//            if (md5($param['password'].$user['salt']) <> $user['password']) return [0,trans("error.passwd"),[]];
+            if (md5($param['password'].$user['salt']) <> $user['password']) return [0,trans("error.passwd"),[]];
         }
         $user->login_at = getDateFull();
         $user->login_ip = request()->getRealIp();

+ 1 - 1
app/controller/adminapi/admin/Menu.php

@@ -34,7 +34,7 @@ class Menu extends Base
                 "type.default"  => 1
             ]);
             $hide = 0;
-            $menu = $this->service->getMenuList($request->user['is_super'],$hide,$param['form']);
+            $menu = $this->service->getMenuList($request->user['id']>1?$request->user['roles']:-1,$hide,$param['form']);
             $permissionsData = [];
             foreach ($menu as $val) {
                 if ($val['type'] == 'button') {

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

@@ -0,0 +1,140 @@
+<?php
+
+namespace app\controller\adminapi\admin;
+
+use app\extra\basic\Base;
+use app\extra\service\system\SystemRoleService;
+use app\extra\tools\DataExtend;
+use app\middleware\AuthMiddleware;
+use app\model\system\SystemMenu;
+use crmeb\services\CacheService;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+
+
+#[Controller(prefix: "/adminapi/role/"),Middleware(AuthMiddleware::class)]
+class Role extends Base
+{
+
+    #[Inject]
+    protected SystemRoleService $service;
+
+    /**
+     * 获取菜单
+     */
+    #[Route(path: "",methods: "get")]
+    public function index(Request $request): Response
+    {
+        try {
+            $param = $request->get();
+            $role = $this->service->getList($param);
+            return successTrans("success.data",$role);
+        } catch (\Throwable $throwable) {
+            echo $throwable->getFile()."\n";
+            echo $throwable->getLine()."\n";
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 显示创建资源表单页.
+     */
+    #[Route(path: "create",methods: "get")]
+    public function create(Request $request): Response
+    {
+        try {
+            $menus = $this->service->getmenus([]);
+            return successTrans("success.data",$menus);
+        } catch (\Throwable $throwable) {
+            echo $throwable->getFile()."\n";
+            echo $throwable->getLine()."\n";
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 更新/保存
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "save[/{id}]",methods: "post")]
+    public function save(Request $request,$id = 0): Response
+    {
+        try {
+            $data = $this->_valid([
+                "role_name.require"  => '请输入身份名称',
+                "status.default"  => '1',
+                "rules.default"  => '1',
+            ],"post");
+            if (!is_array($data)) return error($data);
+            if (!is_array($data['rules']) || !count($data['rules']))
+                return errorTrans('请选择最少一个权限');
+            $data['rules'] = implode(',', $data['rules']);
+            if ($id) {
+                if (!$this->service->update($id, $data))
+                    return errorTrans('修改失败!');
+            } else {
+                if (!$this->service->save($data))
+                    return errorTrans('添加身份失败!');
+            }
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 编辑.
+     */
+    #[Route(path: "edit/{id}",methods: "get")]
+    public function edit(Request $request,$id): Response
+    {
+        try {
+            $role = $this->service->getOne(['id'=>$id]);
+            if (!$role) {
+                return $this->fail('修改的角色不存在');
+            }
+            $menus = $this->service->getmenus([]);
+            return successTrans("success.data",['role' => $role->toArray(), 'menus' => $menus]);
+        } catch (\Throwable $throwable) {
+            echo $throwable->getFile()."\n";
+            echo $throwable->getLine()."\n";
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 删除.
+     */
+    #[Route(path: "del/{id}",methods: "delete")]
+    public function del(Request $request,$id): Response
+    {
+        try {
+            if (!$this->service->delete($id))
+                return errorTrans('删除失败,请稍候再试!');
+            else {
+                return successTrans('删除成功!');
+            }
+        } catch (\Throwable $throwable) {
+            echo $throwable->getFile()."\n";
+            echo $throwable->getLine()."\n";
+            return error($throwable->getMessage());
+        }
+    }
+
+    #[Route(path: "set_status/{id}/{status}",methods: "get")]
+    public function set_status($id,$status): Response
+    {
+        try {
+            $state = $this->service->update($id,['status'=>$status]);
+            if (!$state) return errorTrans("empty.error");
+            return successTrans($status?'显示成功':'关闭成功');
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+}

+ 11 - 3
app/controller/adminapi/admin/Upload.php

@@ -3,6 +3,7 @@
 namespace app\controller\adminapi\admin;
 
 use app\extra\basic\Base;
+use app\extra\service\system\SystemAttachmentService;
 use app\extra\tools\UploadExtend;
 use app\middleware\AuthMiddleware;
 use LinFly\Annotation\Route\Controller;
@@ -12,7 +13,7 @@ use support\Request;
 use support\Response;
 
 
-#[Controller(prefix: "/upload"),Middleware(AuthMiddleware::class)]
+#[Controller(prefix: "adminapi/upload"),Middleware(AuthMiddleware::class)]
 class Upload extends Base
 {
 
@@ -22,12 +23,19 @@ class Upload extends Base
      * @param Request $request
      * @return Response
      */
-    #[Route(path: "data",methods: "post")]
-    public function upload2image(Request $request): Response
+    #[Route(path: "data[/{file_type}]",methods: "post")]
+    public function upload2image(Request $request,$file_type): Response
     {
         try {
+            $param = $request->post();
             $resp = UploadExtend::uploadFile();
             if (!isset($resp[0]['url'])) return errorTrans(40010);
+            $systemAttachmentService = new SystemAttachmentService();
+            $fileInfo = UploadExtend::getUploadInfo($resp);
+//            //保存附件记录
+            foreach ($fileInfo as $k => $v) {
+                $systemAttachmentService->saveAttachment($v,$param['pid']??0, $file_type, 1);
+            }
             return successTrans("success.data",[
                 "fileName"  => $resp[0]['origin_name'],
                 "src"       => $resp[0]['url'],

+ 6 - 3
app/controller/adminapi/admin/User.php

@@ -37,7 +37,7 @@ class User extends Base
         try {
             $param = $request->get();
             $list = $this->service->getList($param);
-            return successTrans("success.data",pageFormat($list),200);
+            return successTrans("success.data",$list);
         } catch (\Throwable $throwable) {
             return error($throwable->getMessage());
         }
@@ -56,12 +56,14 @@ class User extends Base
         try {
             $param = $this->_valid([
                 "id.require"        => trans(20010),
-                "password.require"  => trans(20010)
+                "password.default"  => trans(20010),
+                "roles.default"  => 2
             ],"post");
             if (!is_array($param)) return error($param);
             $user = $this->model->where("id",$param['id'])->findOrEmpty();
             if ($user->isEmpty()) return errorTrans("empty.error");
             $user->password = md5($param['password'].$user['salt']);
+            $user->roles = $param['roles'];
             $state = $user->save();
             if (!$state) return errorTrans("error.data");
             return successTrans("success.data");
@@ -69,6 +71,7 @@ class User extends Base
             return error($throwable->getMessage());
         }
     }
+
     /**
      * 新增/编辑代理
      * @param Request $request
@@ -80,7 +83,7 @@ class User extends Base
         try {
             $param = $request->post();
             $param['salt'] = strtoupper(CodeExtend::random(10,3));
-            $param['password'] = md5($param['password'].$param['salt']);
+            $param['password'] = md5(md5($param['password']).$param['salt']);
             if (!$this->validate->check($param)) return error($this->validate->getError());
             $user = $this->model->where("username",$param['username'])->findOrEmpty();
             if (!$user->isEmpty()) return errorTrans("error.user-exist");

+ 95 - 0
app/controller/adminapi/attachment/Attachment.php

@@ -0,0 +1,95 @@
+<?php
+// +----------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +----------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +----------------------------------------------------------------------
+namespace app\controller\adminapi\attachment;
+
+use app\extra\basic\Base;
+use app\extra\service\system\SystemAttachmentService;
+use app\middleware\AuthMiddleware;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+
+/**
+ * 图片管理类
+ * Class SystemAttachment
+ */
+#[Controller(prefix: "/adminapi/file/"),Middleware(AuthMiddleware::class)]
+class Attachment extends Base
+{
+    /**
+     * @var SystemAttachmentService
+     */
+    #[Inject]
+    protected SystemAttachmentService $service;
+
+    /**
+     * 显示列表
+     * @return mixed
+     */
+    #[Route(path: "",methods: "get")]
+    public function index(Request $request)
+    {
+        $param = $request->get();
+        return $this->success($this->service->getImageList($param));
+    }
+
+    /**
+     * 删除指定资源
+     *
+     * @param string $ids
+     */
+    #[Route(path: "delete",methods: "delete")]
+    public function delete(Request $request)
+    {
+        $ids = $request->post('ids');
+        $this->service->del($ids);
+        return $this->success('删除成功');
+    }
+
+    /**
+     * 移动图片
+     * @return mixed
+     */
+    #[Route(path: "do_move",methods: "put")]
+    public function moveImageCate(Request $request)
+    {
+        $data = $request->get();
+        $this->service->move($data);
+        return $this->success('移动成功');
+    }
+
+//    /**
+//     * 修改文件名
+//     * @param $id
+//     * @return mixed
+//     */
+//    public function update($id)
+//    {
+//        $realName = $this->request->post('real_name', '');
+//        if (!$realName) {
+//            return $this->fail('文件名称不能为空');
+//        }
+//        $this->service->update($id, ['real_name' => $realName]);
+//        return $this->success('修改成功');
+//    }
+//
+//    /**
+//     * 获取上传类型
+//     * @return mixed
+//     */
+//    public function uploadType()
+//    {
+//        $data['upload_type'] = (string)sys_config('upload_type', 1);
+//        return app('json')->success($data);
+//    }
+}

+ 99 - 0
app/controller/adminapi/attachment/AttachmentCategory.php

@@ -0,0 +1,99 @@
+<?php
+// +----------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +----------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +----------------------------------------------------------------------
+namespace app\controller\adminapi\attachment;
+
+use app\extra\basic\Base;
+use app\extra\service\system\SystemAttachmentCategoryService;
+use app\extra\service\system\SystemAttachmentService;
+use app\middleware\AuthMiddleware;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+
+/**
+ * 图片管理类
+ * Class SystemAttachment
+ */
+#[Controller(prefix: "/adminapi/file/category/"),Middleware(AuthMiddleware::class)]
+class AttachmentCategory extends Base
+{
+    /**
+     * @var SystemAttachmentCategoryService
+     */
+    #[Inject]
+    protected SystemAttachmentCategoryService $service;
+
+    /**
+     * 显示列表
+     * @return mixed
+     */
+    #[Route(path: "",methods: "get")]
+    public function index(Request $request)
+    {
+        $param = $request->get();
+        return $this->success($this->service->getAll($param));
+    }
+
+    /**
+     * 获取分类列表
+     * @return mixed
+     * @throws \FormBuilder\Exception\FormBuilderException
+     */
+    #[Route(path: "cate_list",methods: "get")]
+    public function cate_list(Request $request)
+    {
+        $param = $request->get();
+        return $this->success($this->service->getCateList($param));
+    }
+
+    #[Route(path: "save[/{id}]",methods: "post")]
+    public function save(Request $request,$id): Response
+    {
+        try {
+            $param = $this->_valid([
+                "pid.number"  => '上级分类错误',
+                "name.require"  => '请输入分类名称',
+                "file_type.require" => '文件类型参数错误',
+            ],"post");
+            if (!is_array($param)) return error($param);
+            if($id){
+                $info = $this->service->getOne(['id'=>$id]);
+                $count = $this->service->count(['pid' => $id]);
+                if ($count && $info['pid'] != $param['pid']) return errorTrans('该分类有下级分类,无法修改上级');
+                $state = $this->service->update($id, $param);
+            }else{
+                $state = $this->service->save($param);
+            }
+            if (!$state) return errorTrans("empty.error");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 删除指定资源
+     *
+     * @param int $id
+     * @return \think\Response
+     */
+    #[Route(path: "delete/{id}",methods: "delete")]
+    public function delete($id)
+    {
+        $this->service->del($id);
+        return $this->success('删除成功!');
+    }
+
+
+}

+ 1 - 0
app/controller/adminapi/cutter/CutterApply.php

@@ -56,6 +56,7 @@ class CutterApply extends Base
             $apply = $this->service->getOne(["id"=>$id]);
             if ($apply->isEmpty()) return errorTrans("empty.error");
             $state = $this->service->update($id,['status'=>1]) && $this->userService->update($apply['uid'],['is_cutter'=>1]);
+
             if (!$state) return errorTrans("error.data");
             return successTrans("success.data");
         } catch (\Throwable $throwable) {

+ 91 - 0
app/controller/adminapi/cutter/CutterLabel.php

@@ -0,0 +1,91 @@
+<?php
+
+namespace app\controller\adminapi\cutter;
+
+use app\extra\basic\Base;
+use app\extra\service\cutter\CutterLabelService;
+use app\middleware\AuthMiddleware;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+
+
+#[Controller(prefix: "/adminapi/cutter/label"),Middleware(AuthMiddleware::class)]
+class CutterLabel extends Base
+{
+
+    #[Inject]
+    protected CutterLabelService $service;
+
+    #[Route(path: "list/{type}",methods: "get")]
+    public function getList(Request $request,$type): Response
+    {
+        try {
+            $param = $request->get();
+            $param['type'] = $type;
+            $list = $this->service->getList($param,'*',$param['page']??0,$param['limit']??0);
+            return successTrans("success.data",$list);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    #[Route(path: "save",methods: "post")]
+    public function save(Request $request): Response
+    {
+        try {
+            $param = $this->_valid([
+                "label_name.require"=> '标签名字不能为空',
+                "type.require"  => '类型错误1',
+                "type.int"  => '类型错误2',
+                "type.gt:0"  => '类型错误3',
+                "id.int"  => '类型错误3',
+            ],"post");
+            if (!is_array($param)) return error($param);
+            $label = $this->service->getOne(['label_name'=>$param['label_name']]);
+            if(!$label->isEmpty() && (empty($param['id']) || $param['id'] != $label->id)){
+                return errorTrans("该标签已经存在");
+            }
+
+            if(!empty($param['id'])){
+                $id = $param['id'];
+                unset($param['id']);
+                $state = $this->service->update($id,['label_name'=>$param['label_name']]);
+            }else{
+                $state = $this->service->save($param);
+            }
+            if (!$state) return errorTrans("empty.error");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    #[Route(path: "info/{id}",methods: "get")]
+    public function info($id): Response
+    {
+        try {
+            $take = $this->service->getOne(["id"=>$id,'is_del'=>0]);
+            if ($take->isEmpty()) return errorTrans("empty.error");
+            return successTrans("success.data",$take->toArray());
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    #[Route(path: "del/{id}",methods: "delete")]
+    public function delete($id): Response
+    {
+        try {
+            $state = $this->service->update($id,['is_del'=>1]);
+            if (!$state) return errorTrans("empty.error");
+            return successTrans('删除成功');
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 1 - 1
app/controller/adminapi/cutter/CutterOrder.php

@@ -73,7 +73,7 @@ class CutterOrder extends Base
         }
     }
 
-    #[Route(path: "reject/{id}",methods: "post")]
+    #[Route(path: "settle/{id}",methods: "post")]
     public function settle(Request $request,$id): Response
     {
         try {

+ 13 - 1
app/controller/adminapi/cutter/CutterTask.php

@@ -29,6 +29,7 @@ class CutterTask extends Base
     {
         try {
             $param = $request->get();
+            $param['is_del'] = 0;
             $list = $this->service->getList($param,'*',$param['page']??0,$param['limit']??0);
             return successTrans("success.data",$list);
         } catch (\Throwable $throwable) {
@@ -36,12 +37,23 @@ class CutterTask extends Base
         }
     }
 
+    #[Route(path: "info/{id}",methods: "get")]
+    public function info($id): Response
+    {
+        try {
+            $info = $this->service->getOne(['id'=>$id]);
+            if ($info->isEmpty()) return errorTrans("empty.error");
+            return successTrans("success.data",$info->toArray());
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
     #[Route(path: "save",methods: "post")]
     public function save(Request $request): Response
     {
         try {
             $param = $request->post();
-            $param['material'] = [];
             if (!$this->validate->check($param)) return error($this->validate->getError());
             $param = $this->validate->checked($param);
             if(!empty($param['id'])){

+ 1 - 1
app/controller/adminapi/kefu/Kefu.php

@@ -44,7 +44,7 @@ class Kefu extends Base
             if (!$this->validate->check($param)) return error($this->validate->getError());
             $param = $this->validate->checked($param);
             $state = $this->service->save($param);
-            if ($state->isEmpty()) return errorTrans("empty.error");
+            if (!$state) return errorTrans("empty.error");
             return successTrans("success.data");
         } catch (\Throwable $throwable) {
             return error($throwable->getMessage());

+ 1 - 1
app/controller/adminapi/user/User.php

@@ -26,7 +26,7 @@ class User extends Base
     {
         try {
             $param = $request->get();
-            $list = $this->service->getList($param,'*',$param['page']??0,$param['limit']??0);
+            $list = $this->service->getList($param,'*');
             return successTrans("success.data",$list);
         } catch (\Throwable $throwable) {
             return error($throwable->getMessage());

+ 106 - 0
app/controller/adminapi/user/UserLevel.php

@@ -0,0 +1,106 @@
+<?php
+
+namespace app\controller\adminapi\user;
+
+use app\extra\basic\Base;
+use app\extra\service\user\UserLevelService;
+use app\middleware\AuthMiddleware;
+use app\validate\adminapi\user\UserLevelValidate;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use support\Request;
+use support\Response;
+
+
+#[Controller(prefix: "/adminapi/user/level"),Middleware(AuthMiddleware::class)]
+class UserLevel extends Base
+{
+
+    #[Inject]
+    protected UserLevelService $service;
+
+    #[Inject]
+    protected UserLevelValidate $validate;
+
+    #[Route(path: "list",methods: "get")]
+    public function getList(Request $request): Response
+    {
+        try {
+            $param = $request->get();
+            $list = $this->service->getList($param,'*',$param['page']??0,$param['limit']??0);
+            return successTrans("success.data",$list);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    #[Route(path: "save[/{id}]",methods: "post")]
+    public function save(Request $request,$id = 0): Response
+    {
+        try {
+            $param = $request->post();
+            if (!$this->validate->check($param)) return error($this->validate->getError());
+            $param = $this->validate->checked($param);
+            $level = $this->service->getOne(['grade'=>$param['grade'],'is_del'=>0]);
+            if(!$level->isEmpty() && (!$id || $level->id != $id)){
+                return errorTrans("该等级已存在");
+            }
+            $level = $this->service->getOne([['grade','<',$param['grade']],['is_del','=',0]],'*','grade desc');
+            if(!$level->isEmpty() && $level['exp_num'] >= $param['exp_num']){
+                return errorTrans("经验值必须大于上一级别,上级经验值为:{$level['exp_num']}");
+            }
+            $level = $this->service->getOne([['grade','>',$param['grade']],['is_del','=',0]],'*','exp_num asc');
+            if(!$level->isEmpty() && $level['exp_num'] <= $param['exp_num']){
+                return errorTrans("经验值必须小于下一级别,下级经验值为:{$level['exp_num']}");
+            }
+            if($id){
+                $state = $this->service->update($id,$param);
+            }else{
+                $state = $this->service->save($param);
+            }
+            if (!$state) return errorTrans("empty.error");
+            return successTrans("success.data");
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    #[Route(path: "info/{id}",methods: "get")]
+    public function info($id): Response
+    {
+        try {
+            $take = $this->service->getOne(["id"=>$id,'is_del'=>0]);
+            if ($take->isEmpty()) return errorTrans("empty.error");
+            return successTrans("success.data",$take->toArray());
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    #[Route(path: "set_show/{id}/{show}",methods: "get")]
+    public function set_show($id,$show): Response
+    {
+        try {
+            $state = $this->service->update($id,['is_show'=>$show]);
+            if (!$state) return errorTrans("empty.error");
+            return successTrans($show?'显示成功':'禁用成功');
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    #[Route(path: "del/{id}",methods: "delete")]
+    public function delete($id): Response
+    {
+        try {
+            $state = $this->service->update($id,['is_del'=>1]);
+            if (!$state) return errorTrans("empty.error");
+            return successTrans('删除成功');
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+}

+ 66 - 0
app/controller/api/PublicController.php

@@ -3,6 +3,10 @@
 namespace app\controller\api;
 
 use app\extra\basic\Base;
+use app\extra\service\system\SystemAttachmentService;
+use app\extra\service\user\UserBillService;
+use app\extra\service\user\UserLevelService;
+use app\extra\tools\UploadExtend;
 use app\middleware\AuthMiddleware;
 use app\model\system\SystemUser;
 use app\model\user\User;
@@ -46,4 +50,66 @@ class PublicController extends Base
             return error($throwable->getMessage());
         }
     }
+
+    /**
+     * 获取协议
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "config",methods: "get")]
+    public function config(Request $request): Response
+    {
+        try {
+
+            $config['title'] = sConf('service.title');
+            $config['logo'] = sConf('service.logo');
+
+            return successTrans("success.login",$config);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+    /**
+     * 上传文件
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "upload[/{file_type}]",methods: "post"),Middleware(AuthMiddleware::class)]
+    public function upload_file(Request $request,$file_type): Response
+    {
+        try {
+            $param = $request->post();
+            $resp = UploadExtend::uploadFile();
+            if (!isset($resp[0]['url'])) return errorTrans(40010);
+            $systemAttachmentService = new SystemAttachmentService();
+            $fileInfo = UploadExtend::getUploadInfo($resp);
+//            //保存附件记录
+            foreach ($fileInfo as $k => $v) {
+                $systemAttachmentService->saveAttachment($v,$param['pid']??0, $file_type, 2);
+            }
+            return successTrans("success.data",[
+                "fileName"  => $resp[0]['origin_name'],
+                "src"       => $resp[0]['url'],
+            ],200);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+    /**
+     * 获取协议
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "test",methods: "get")]
+    public function test(Request $request): Response
+    {
+//        $userBillService = new UserBillService();
+//        $userBillService->incomeExp(3,1,'订单结算成功','订单结算成功,增加经验值1',1);
+        $userLevelService = new UserLevelService();
+        $userLevelService->detection(3);
+        var_dump(121);
+    }
 }

+ 14 - 2
app/controller/api/cutter/CutterController.php

@@ -4,16 +4,18 @@ namespace app\controller\api\cutter;
 
 use app\extra\basic\Base;
 use app\extra\service\cutter\CutterApplyService;
+use app\middleware\AuthMiddleware;
 use app\validate\api\user\CutterApplyValidate;
 use DI\Attribute\Inject;
 use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
 use LinFly\Annotation\Route\Route;
 use Shopwwi\WebmanAuth\Auth;
 use support\Request;
 use support\Response;
 
 
-#[Controller(prefix: "/api/user/")]
+#[Controller(prefix: "/api/user/"),Middleware(AuthMiddleware::class)]
 class CutterController extends Base
 {
 
@@ -37,7 +39,17 @@ class CutterController extends Base
             $param = $request->post();
             if (!$this->validate->check($param)) return error($this->validate->getError());
             $param['uid'] = $user['uid'];
-            $state = $this->cutterApplyService->save($param);
+
+            if($user['is_cutter'])
+                return errorTrans("您已成为剪辑师,请勿重复操作");
+            $apply = $this->cutterApplyService->getOne(['uid'=>$param['uid']]);
+            if(!$apply->isEmpty()){
+                $param['status'] = 0;
+                $state = $this->cutterApplyService->update($apply['id'],$param);
+            }else{
+                $state = $this->cutterApplyService->save($param);
+            }
+
             if (!$state) return errorTrans("error.data");
             return successTrans("success.data");
         } catch (\Throwable $throwable) {

+ 39 - 0
app/controller/api/cutter/CutterLabelController.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace app\controller\api\cutter;
+
+use app\extra\basic\Base;
+use app\extra\service\cutter\CutterLabelService;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Route;
+use Shopwwi\WebmanAuth\Auth;
+use support\Request;
+use support\Response;
+
+
+#[Controller(prefix: "/api/cutter/label")]
+class CutterLabelController extends Base
+{
+
+    #[Inject]
+    protected CutterLabelService $service;
+
+    /**
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "lst/{type}",methods: "get")]
+    public function cutter_apply(Request $request,$type): Response
+    {
+        try {
+            $label = $this->service->selectWhere(['is_del'=>0,'type'=>$type],'id,label_name');
+            return successTrans("success.data",$label?$label->toArray():[]);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
+
+}

+ 18 - 0
app/controller/api/cutter/CutterOrderController.php

@@ -36,12 +36,30 @@ class CutterOrderController extends Base
         }
     }
 
+    #[Route(path: "details/{id}",methods: "get")]
+    public function details(Request $request,$id): Response
+    {
+        try {
+            $param = $request->get();
+            $user = (new Auth)->guard("user")->user()->toArray();
+//            $param['uid'] = $user['uid'];
+            $param['id'] = $id;
+            $details = $this->service->getDetails($param,'id,task_id,uid,status,remark,created_at');
+            return successTrans("success.data",$details?$details->toArray():[],200);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
     #[Route(path: "create",methods: "post")]
     public function create(Request $request): Response
     {
         try {
             $id = $request->post('id',0);
             $user = (new Auth)->guard("user")->user()->toArray();
+            if(!$user['is_cutter']){
+                return errorTrans("请申请成为剪辑师后再领取任务");
+            }
             $state = $this->service->createOrder($id,$user);
             if (!$state) return errorTrans("error.data");
             return successTrans("任务领取成功",['id'=>$state->id]);

+ 13 - 1
app/controller/api/cutter/CutterTaskController.php

@@ -7,6 +7,7 @@ use app\extra\service\cutter\CutterTaskService;
 use DI\Attribute\Inject;
 use LinFly\Annotation\Route\Controller;
 use LinFly\Annotation\Route\Route;
+use Shopwwi\WebmanAuth\Auth;
 use support\Request;
 use support\Response;
 
@@ -25,6 +26,16 @@ class CutterTaskController extends Base
             $param = $request->get();
             $param['status'] = 1;
             $param['is_del'] = 0;
+            $param['type'] = $param['type']??0;
+            $user = (new Auth)->guard("user")->user();
+            if($user){
+//                $param['grade'] = $user['level'];
+                $param['uid'] = $user['uid'];
+            }else{
+//                $param['grade'] = 1;
+                $param['uid'] = 0;
+            }
+
             $list = $this->service->getList($param,'*',$param['page']??0,$param['limit']??0);
             return successTrans("success.data",$list);
         } catch (\Throwable $throwable) {
@@ -36,8 +47,9 @@ class CutterTaskController extends Base
     public function info($id): Response
     {
         try {
-            $take = $this->service->getOne(["id"=>$id]);
+            $take = $this->service->getInfo(["id"=>$id]);
             if ($take->isEmpty()) return errorTrans("empty.error");
+            $this->service->incField(["id"=>$id],'hot',1);
             return successTrans("success.data",$take->toArray(),200);
         } catch (\Throwable $throwable) {
             return error($throwable->getMessage());

+ 1 - 0
app/controller/api/user/LoginController.php

@@ -39,6 +39,7 @@ class LoginController extends Base
         try {
             $code = $request->get('code','');
             $wechatUser = $this->service->getUserInfo($code);
+
             $wechatUser['login_at'] = getDateFull();
             $wechatUser['login_ip']= $request->getRealIp();
 //            $wechatUser = [

+ 18 - 0
app/controller/api/user/UserController.php

@@ -66,5 +66,23 @@ class UserController extends Base
         }
     }
 
+    /**
+     * 修改用户数据
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "rank/{type}",methods: "get")]
+    public function rank(Request $request,$type): Response
+    {
+        try {
+            $user = (new Auth)->guard("user")->user()->toArray();
+            $rank = $this->service->rank($type,$user);
+            return successTrans("success.data",$rank);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
+
 
 }

+ 19 - 0
app/controller/api/user/UserExtractController.php

@@ -46,6 +46,25 @@ class UserExtractController extends Base
         }
     }
 
+    /**
+     * 提现配置
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "config",methods: "get")]
+    public function config(Request $request): Response
+    {
+        try {
+            $config['extract_min_price'] = sConf('extract.extract_min_price');
+            $config['extract_bank'] = sConf('extract.extract_bank');
+            $config['extract_charge'] = sConf('extract.extract_charge');
+
+            return successTrans("success.login",$config);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+
 
 
 }

+ 43 - 0
app/controller/api/user/UserLevelController.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace app\controller\api\user;
+
+use app\extra\basic\Base;
+use app\extra\service\user\UserLevelService;
+use app\middleware\AuthMiddleware;
+use app\validate\api\user\UserValidate;
+use DI\Attribute\Inject;
+use LinFly\Annotation\Route\Controller;
+use LinFly\Annotation\Route\Middleware;
+use LinFly\Annotation\Route\Route;
+use Shopwwi\WebmanAuth\Auth;
+use support\Request;
+use support\Response;
+
+
+#[Controller(prefix: "/api/user/level/"),Middleware(AuthMiddleware::class)]
+class UserLevelController extends Base
+{
+
+    #[Inject]
+    protected UserLevelService $service;
+
+//    #[Inject]
+//    protected UserValidate $validate;
+
+    /**
+     * 等级列表
+     * @param Request $request
+     * @return Response
+     */
+    #[Route(path: "list",methods: "get")]
+    public function list(Request $request): Response
+    {
+        try {
+            $level = $this->service->selectWhere(['is_show'=>1,'is_del'=>0],'name,grade,background,icon,color,exp_num');
+            return successTrans("success.data",$level?$level->toArray():[]);
+        } catch (\Throwable $throwable) {
+            return error($throwable->getMessage());
+        }
+    }
+}

+ 47 - 4
app/extra/basic/Dao.php

@@ -38,18 +38,22 @@ abstract class Dao
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
      */
-    public function getOne(array $where, ?string $field = '*')
+    public function getOne(array $where, ?string $field = '*', ?string $order = '')
     {
-        return $this->getModel()->where($where)->field($field)->findOrEmpty();
+        return $this->getModel()->where($where)->field($field)->when($order,function($query)use($order){
+            $query->order($order);
+        })->find();
     }
 
     /**
      * @param array $where
      * @param string $field
      */
-    public function selectWhere(array $where, string $field = '*')
+    public function selectWhere(array $where, string $field = '*',string $order = '')
     {
-        return $this->getModel()->where($where)->field($field)->select();
+        return $this->getModel()->where($where)->field($field)->when($order,function($query)use($order){
+            $query->order($order);
+        })->select();
     }
 
     /**
@@ -134,4 +138,43 @@ abstract class Dao
     {
         return $this->getModel()->where($where)->dec($field, $num)->update();
     }
+
+    /**
+     * 获取单个字段值
+     * @param array $where
+     * @param string|null $field
+     * @return mixed
+     */
+    public function value(array $where, ?string $field = '')
+    {
+        $pk = $this->getModel()->getPk();
+        return $this->getModel()::where($where)->value($field ?: $pk);
+    }
+
+    /**
+     * 获取某个字段数组
+     * @param array $where
+     * @param string $field
+     * @param string $key
+     * @return array
+     */
+    public function getColumn(array $where, string $field, string $key = '')
+    {
+        return $this->getModel()::where($where)->column($field, $key);
+    }
+
+    /**
+     * 删除
+     * @param int|string|array $id
+     * @return bool
+     */
+    public function delete($id, ?string $key = null)
+    {
+        if (is_array($id)) {
+            $where = $id;
+        } else {
+            $where = [is_null($key) ? $this->getModel()->getPk() : $key => $id];
+        }
+        return $this->getModel()::where($where)->delete();
+    }
 }

+ 137 - 0
app/extra/basic/Http.php

@@ -0,0 +1,137 @@
+<?php
+
+namespace app\extra\basic;
+
+class Http
+{
+    /**
+     * 错误信息
+     * @var string
+     */
+    private static $curlError;
+
+    /**
+     * header头信息
+     * @var string
+     */
+    private static $headerStr;
+
+    /**
+     * 请求状态
+     * @var int
+     */
+    private static $status;
+
+    /**
+     * @return string
+     */
+    public static function getCurlError()
+    {
+        return self::$curlError;
+    }
+
+    /**
+     * @return mixed
+     */
+    public static function getStatus()
+    {
+        return self::$status;
+    }
+
+    /**
+     * 模拟GET发起请求
+     * @param $url
+     * @param array $data
+     * @param bool $header
+     * @param int $timeout
+     * @return bool|string
+     */
+    public static function getRequest($url, $data = array(), $header = false, $timeout = 10)
+    {
+        if (!empty($data)) {
+            $url .= (stripos($url, '?') === false ? '?' : '&');
+            $url .= (is_array($data) ? http_build_query($data) : $data);
+        }
+
+        return self::request($url, 'get', array(), $header, $timeout);
+    }
+
+    /**
+     * curl 请求
+     * @param $url
+     * @param string $method
+     * @param array $data
+     * @param bool $header
+     * @param int $timeout
+     * @return bool|string
+     */
+    public static function request($url, $method = 'get', $data = array(), $header = false, $timeout = 15)
+    {
+        self::$status = null;
+        self::$curlError = null;
+        self::$headerStr = null;
+
+        $curl = curl_init($url);
+        $method = strtoupper($method);
+        //请求方式
+        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
+        //post请求
+        if ($method == 'POST') curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
+        //超时时间
+        curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
+        //设置header头
+        if ($header !== false) curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
+
+        curl_setopt($curl, CURLOPT_FAILONERROR, false);
+        //返回抓取数据
+        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+        //输出header头信息
+        curl_setopt($curl, CURLOPT_HEADER, true);
+        //TRUE 时追踪句柄的请求字符串,从 PHP 5.1.3 开始可用。这个很关键,就是允许你查看请求header
+        curl_setopt($curl, CURLINFO_HEADER_OUT, true);
+        //https请求
+        if (1 == strpos("$" . $url, "https://")) {
+            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
+            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
+        }
+        self::$curlError = curl_error($curl);
+
+        list($content, $status) = [curl_exec($curl), curl_getinfo($curl), curl_close($curl)];
+        self::$status = $status;
+        self::$headerStr = trim(substr($content, 0, $status['header_size']));
+        $content = trim(substr($content, $status['header_size']));
+        return (intval($status["http_code"]) === 200) ? $content : false;
+    }
+
+    /**
+     * 模拟POST发起请求
+     * @param $url
+     * @param $data
+     * @param bool $header
+     * @param int $timeout
+     * @return bool|string
+     */
+    public static function postRequest($url, $data = array(), $header = false, $timeout = 10)
+    {
+        return self::request($url, 'post', $data, $header, $timeout);
+    }
+
+    /**
+     * 获取header头字符串类型
+     * @return mixed
+     */
+    public static function getHeaderStr()
+    {
+        return self::$headerStr;
+    }
+
+    /**
+     * 获取header头数组类型
+     * @return array
+     */
+    public static function getHeader()
+    {
+        $headArr = explode("\r\n", self::$headerStr);
+        return $headArr;
+    }
+}

+ 17 - 0
app/extra/basic/Service.php

@@ -4,6 +4,7 @@ namespace app\extra\basic;
 
 use app\model\system\SystemConfig;
 use Overtrue\EasySms\Strategies\OrderStrategy;
+use support\Request;
 use think\facade\Db;
 
 abstract class Service
@@ -122,4 +123,20 @@ abstract class Service
         return call_user_func_array([$this->dao, $name], $arguments);
     }
 
+
+    /**
+     * 获取分页配置
+     * @param bool $isPage
+     * @param bool $isRelieve
+     * @return int[]
+     */
+    public function getPageValue()
+    {
+        $request = Request();
+        $page = $request->get('page',0);
+        $limit = $request->get('limit',0);
+
+        return [(int)$page, (int)$limit];
+    }
+
 }

+ 25 - 0
app/extra/dao/cutter/CutterLabelDao.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace app\extra\dao\cutter;
+
+use app\extra\basic\Dao;
+use app\model\cutter\CutterLabel;
+
+class CutterLabelDao extends Dao
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    protected function setModel(): string
+    {
+        return CutterLabel::class;
+    }
+
+    public function getList(array $where,string $field = '*',int $page = 0, int $limit =0,string $order='id desc')
+    {
+        return $this->getModel()->where($where)->field($field)->when($page&&$limit,function($query)use($page,$limit){
+            $query->page($page,$limit);
+        })->select();
+    }
+}

+ 10 - 1
app/extra/dao/cutter/CutterOrderDao.php

@@ -30,7 +30,16 @@ class CutterOrderDao extends Dao
     {
         return $this->getModel()->where($where)->field($field)->when($page&&$limit,function($query)use($page,$limit){
             $query->page($page,$limit);
-        })->with('task')->select();
+        })->with('task')->order($order)->select();
+    }
+
+    public function getDetails(array $where,string $field = '*')
+    {
+        return $this->getModel()->where($where)->field($field)->with(['task'=>function($query){
+            $query->withField('id,title,explain,material,price,end_time,hot,kefu_id,created_at')->with(['kefu'=>function($query){
+                $query->field('id,name,wechat,phone,qrcode');
+            }])->withCount(['orderCount'=>'people']);
+        }])->findOrEmpty();
     }
 
     public function getOrder(array $where,string $field = '*')

+ 17 - 2
app/extra/dao/cutter/CutterTaskDao.php

@@ -17,10 +17,25 @@ class CutterTaskDao extends Dao
     }
 
 
-    public function getList(array $where,string $field = '*',int $page = 0, int $limit = 0,string $order='id desc')
+    public function getList($where,string $field = '*',int $page = 0, int $limit = 0,string $order='id desc')
     {
         return $this->getModel()->where($where)->field($field)->when($page&&$limit,function($query)use($page,$limit){
             $query->page($page,$limit);
-        })->select();
+        })->with(['grade'=>function ($query) {
+            $query->field('name,icon,grade,color');
+        },'label'=>function ($query) {
+            $query->field('id,label_name');
+        }])->withCount(['orderCount'=>'people'])->orderRaw($order)->select();
+    }
+
+    public function getInfo(array $where,string $field = '*')
+    {
+        return $this->getModel()->where($where)->field($field)->with(['kefu'=>function ($query) {
+            $query->field('id,name,wechat,qrcode');
+        },'grade'=>function ($query) {
+            $query->field('name,icon,grade,color');
+        },'label'=>function ($query) {
+            $query->field('id,label_name');
+        }])->withCount(['orderCount'=>'people'])->findOrEmpty();
     }
 }

+ 27 - 0
app/extra/dao/system/SystemAttachmentCategoryDao.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace app\extra\dao\system;
+
+use app\extra\basic\Dao;
+use app\model\system\SystemAttachmentCategory;
+
+class SystemAttachmentCategoryDao extends Dao
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    protected function setModel(): string
+    {
+        return SystemAttachmentCategory::class;
+    }
+
+    public function getList(array $where,string $field = '*',int $page = 0, int $limit = 0,string $order='id desc')
+    {
+        return $this->getModel()->where($where)->field($field)->when($page&&$limit,function($query)use($page,$limit){
+            $query->page($page,$limit);
+        })->select();
+    }
+
+
+}

+ 34 - 0
app/extra/dao/system/SystemAttachmentDao.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace app\extra\dao\system;
+
+use app\extra\basic\Dao;
+use app\model\system\SystemAttachment;
+
+class SystemAttachmentDao extends Dao
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    protected function setModel(): string
+    {
+        return SystemAttachment::class;
+    }
+
+    public function getList(array $where,string $field = '*',int $page = 0, int $limit = 0,string $order='id desc')
+    {
+        return $this->getModel()->where($where)->where('module_type', 1)->field($field)->when($page&&$limit,function($query)use($page,$limit){
+            $query->page($page,$limit);
+        })->select();
+    }
+
+    /**
+     * 移动图片
+     * @param array $data
+     */
+    public function move(array $data)
+    {
+        return $this->getModel()->whereIn('att_id', $data['images'])->update(['pid' => $data['pid']]);
+    }
+}

+ 43 - 0
app/extra/dao/system/SystemMenuDao.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace app\extra\dao\system;
+
+use app\extra\basic\Dao;
+use app\model\system\SystemMenu;
+
+class SystemMenuDao extends Dao
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    protected function setModel(): string
+    {
+        return SystemMenu::class;
+    }
+
+//    public function getList(array $where,string $field = '*',int $page = 0, int $limit = 0,string $order='id desc')
+//    {
+//        return $this->getModel()->where($where)->field($field)->when($page&&$limit,function($query)use($page,$limit){
+//            $query->page($page,$limit);
+//        })->select();
+//    }
+
+    /**
+     * 获取权限菜单列表
+     * @param array $where
+     * @param array|null $field
+     * @return array|\crmeb\basic\BaseModel[]|\think\Collection
+     * @throws \ReflectionException
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function getMenusRoule(array $where, ?array $field = [])
+    {
+        if (!$field) {
+            $field = ['id', 'title', 'icon', 'pid', 'sort', 'path', 'status'];
+        }
+        return $this->getModel()->where($where)->field($field)->order('sort DESC,id DESC')->failException(false)->select();
+    }
+}

+ 37 - 0
app/extra/dao/system/SystemRoleDao.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace app\extra\dao\system;
+
+use app\extra\basic\Dao;
+use app\model\system\SystemRole;
+
+class SystemRoleDao extends Dao
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    protected function setModel(): string
+    {
+        return SystemRole::class;
+    }
+
+    public function getList(array $where,string $field = '*',int $page = 0, int $limit = 0,string $order='id desc')
+    {
+        return $this->getModel()->where($where)->field($field)->when($page&&$limit,function($query)use($page,$limit){
+            $query->page($page,$limit);
+        })->select();
+    }
+
+    /**
+     * 获取权限id
+     * @param array $rules
+     * @return array
+     */
+    public function getRoleIds(array $rules)
+    {
+        $rules = $this->dao->getColumn([['id', 'IN', $rules], ['status', '=', '1']], 'rules', 'id');
+        return array_unique(explode(',', implode(',', $rules)));
+    }
+
+}

+ 25 - 0
app/extra/dao/system/SystemUserDao.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace app\extra\dao\system;
+
+use app\extra\basic\Dao;
+use app\model\system\SystemUser;
+
+class SystemUserDao extends Dao
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    protected function setModel(): string
+    {
+        return SystemUser::class;
+    }
+
+    public function getList(array $where,string $field = '*',int $page = 0, int $limit = 0,string $order='id desc')
+    {
+        return $this->getModel()->where($where)->field($field)->when($page&&$limit,function($query)use($page,$limit){
+            $query->page($page,$limit);
+        })->with('role')->select();
+    }
+}

+ 26 - 0
app/extra/dao/user/UserBillDao.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace app\extra\dao\user;
+
+use app\extra\basic\Dao;
+use app\model\user\UserBill;
+
+class UserBillDao extends Dao
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    protected function setModel(): string
+    {
+        return UserBill::class;
+    }
+
+    public function getList(array $where,string $field = '*',int $page = 0, int $limit = 0,string $order='id desc')
+    {
+        return $this->getModel()->where($where)->field($field)->when($page&&$limit,function($query)use($page,$limit){
+            $query->page($page,$limit);
+        })->select();
+    }
+
+}

+ 52 - 0
app/extra/dao/user/UserDao.php

@@ -20,6 +20,58 @@ class UserDao extends Dao
     {
         return $this->getModel()->where($where)->field($field)->when($page&&$limit,function($query)use($page,$limit){
             $query->page($page,$limit);
+        })->with(['level'=>function ($query) {
+            $query->field('id,name');
+        }])->select();
+    }
+
+    /**
+     * 排行榜列表
+     * @param array $where
+     * @param string $field
+     * @param int $type
+     * @return \think\Collection
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function getRank(array $where,string $field = '*',int $type=1)
+    {
+        return $this->getModel()->where($where)->field($field)->page(1,15)
+        ->when($type==1,function($query){
+            $query->withCount(['cutterOrder'=>function($query){
+                $query->where('status',3);
+            }])->having('cutter_order_count > 0')->order('cutter_order_count desc');
+        })
+        ->when($type==2,function($query){
+            $query->withSum(['brokerage'=>function($query){
+                $query->where('pm',1)->where('type','not in',['extract_fail']);
+            }],'number')->having('brokerage_sum > 0')->order('brokerage_sum desc');
         })->select();
     }
+
+    /**
+     * 查询一条排行榜数据
+     * @param array $where
+     * @param string $field
+     * @param int $type
+     * @return \think\Collection
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function getSelfRank(array $where,string $field = '*',int $type=1)
+    {
+        return $this->getModel()->where($where)->field($field)->page(1,15)
+            ->when($type==1,function($query){
+                $query->withCount(['cutterOrder'=>function($query){
+                    $query->where('status',3);
+                }]);
+            })
+            ->when($type==2,function($query){
+                $query->withSum(['brokerage'=>function($query){
+                    $query->where('pm',1)->where('type','not in',['extract_fail']);
+                }],'number');
+            })->findOrEmpty();
+    }
 }

+ 26 - 0
app/extra/dao/user/UserLevelDao.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace app\extra\dao\user;
+
+use app\extra\basic\Dao;
+use app\model\user\UserLevel;
+
+class UserLevelDao extends Dao
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    protected function setModel(): string
+    {
+        return UserLevel::class;
+    }
+
+    public function getList(array $where,string $field = '*',int $page = 0, int $limit = 0,string $order='id desc')
+    {
+        return $this->getModel()->where($where)->field($field)->when($page&&$limit,function($query)use($page,$limit){
+            $query->page($page,$limit);
+        })->select();
+    }
+
+}

+ 26 - 0
app/extra/dao/user/UserLevelLogDao.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace app\extra\dao\user;
+
+use app\extra\basic\Dao;
+use app\model\user\UserLevelLog;
+
+class UserLevelLogDao extends Dao
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    protected function setModel(): string
+    {
+        return UserLevelLog::class;
+    }
+
+    public function getList(array $where,string $field = '*',int $page = 0, int $limit = 0,string $order='id desc')
+    {
+        return $this->getModel()->where($where)->field($field)->when($page&&$limit,function($query)use($page,$limit){
+            $query->page($page,$limit);
+        })->select();
+    }
+
+}

+ 1 - 0
app/extra/service/basic/UploadService.php

@@ -24,6 +24,7 @@ class UploadService
         $config['storage']['single_limit'] = 1024 * 1024 * 200;
         $config['storage']['total_limit'] = 1024 * 1024 * 200;
         if (empty($type)) $type = $data['type'];
+
         switch ($type)
         {
             case "local":

+ 68 - 0
app/extra/service/cutter/CutterLabelService.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace app\extra\service\cutter;
+
+use app\extra\basic\Service;
+use app\extra\dao\cutter\CutterLabelDao;
+use app\extra\service\user\UserBrokerageService;
+use support\exception\BusinessException;
+
+class CutterLabelService extends Service
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    public function __construct()
+    {
+        $this->dao =  new CutterLabelDao();
+    }
+
+    /**
+     * 列表
+     * @param array $param
+     */
+    public function getList(array $param = [],string $field = '*', int $page = 0,int $limit = 0,string $order = 'id desc')
+    {
+        $list =  $this->dao->getList($this->searchFilter($param),$field,$page,$limit,$order);
+        $count = $this->dao->count($this->searchFilter($param));
+        return compact('list','count');
+    }
+
+    protected function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['status']) && $filter[] = ["status", '=', $param['status']];
+        !empty($param['is_del']) && $filter[] = ["is_del", '=', $param['is_del']];
+        !empty($param['type']) && $filter[] = ["type", '=', $param['type']];
+        return $filter;
+    }
+
+    public function getUserInfo(array $data):array
+    {
+        $user = $this->dao->getOne(['openid'=>$data['openid'],'is_del'=>0]);
+        if($user->isEmpty()){
+            $user = $this->dao->save(['openid'=>$data['openid'],'nickname'=>'wx'.time().rand(1000,9999),'login_ip'=>$data['login_ip'],'login_at'=>$data['login_at']]);
+        }else if($user['status'] == 0){
+            throw new BusinessException('用户已被封禁');
+        }
+        return $user->toArray();
+    }
+
+
+    public function getUserProfile(array $user)
+    {
+        if($user['is_del'])
+            throw new BusinessException('用户已注销');
+        if(!$user['status'])
+            throw new BusinessException('用户已被封禁');
+
+        $cutterOrderService = new CutterOrderService();
+        $userBrokerageService = new UserBrokerageService();
+        $user['order_count'] = $cutterOrderService->count(['uid'=>$user['uid']]);
+        $user['brokerage_sum'] = $userBrokerageService->sum([['uid','=',$user['uid']],['pm','=',1],['type','not in',['extract_fail']]],'number');
+
+        return $user;
+    }
+
+}

+ 16 - 4
app/extra/service/cutter/CutterOrderService.php

@@ -4,7 +4,9 @@ namespace app\extra\service\cutter;
 
 use app\extra\basic\Service;
 use app\extra\dao\cutter\CutterOrderDao;
+use app\extra\service\user\UserBillService;
 use app\extra\service\user\UserBrokerageService;
+use app\extra\service\user\UserLevelService;
 use app\extra\service\user\UserService;
 use app\model\cutter\CutterOrder;
 use app\model\cutter\CutterTask;
@@ -27,7 +29,17 @@ class CutterOrderService extends Service
         return $this->transaction(function () use ($id, $user) {
             $cutterTaskService = new CutterTaskService();
             $take = $cutterTaskService->getOne(["id"=>$id,'status'=>1,'is_del'=>0]);
+
+            if(!$cutterTaskService->decField([['id','=',$id],['total','>',1]],'total',1)){
+                throw new ValidateException('该任务已被领取完了,可以关注一下其它任务哦');
+            }
+
             if ($take->isEmpty()) throw new ValidateException('任务异常');
+            $userLevelService = new UserLevelService();
+            $grade = $userLevelService->value(['id'=>$user['level']],'grade');
+            if($take['grade'] > $grade){
+                throw new ValidateException("该任务需求更高等级,无法领取");
+            }
             $order = $this->dao->getOne(["task_id"=>$take['id'],'uid'=>$user['uid']]);
             if (!$order->isEmpty()) throw new ValidateException("同一个任务仅限领取一次");
             if(strtotime($take['end_time']) > time()){
@@ -35,7 +47,6 @@ class CutterOrderService extends Service
             }
             return $this->dao->save(['uid'=>$user['uid'],'task_id'=>$id]);
         });
-
     }
 
     public function submit(array $data,array $user)
@@ -140,13 +151,14 @@ class CutterOrderService extends Service
                 throw new ValidateException('修改用户信息失败');
             }
 
-            $balance = bcsub((string)$user['brokerage_price'], (string)$data['price'], 2) ?? 0;
+            $balance = bcadd((string)$user['brokerage_price'], (string)$task['price'], 2) ?? 0;
             //保存佣金记录
             $userBrokerageServices = new UserBrokerageService();
-
             $mark = '订单结算成功,获得' . $task['price'] . '元'."佣金";
-            $userBrokerageServices->income('order_settle', $user['uid'], ['mark' => $mark, 'number' => $task['price']], $balance, $res['id']);
+            $userBrokerageServices->income('order_settle', $user['uid'], ['mark' => $mark, 'number' => $task['price']], $balance, $id);
 
+            $userBillService = new UserBillService();
+            $userBillService->incomeExp($user['uid'],$task['exp'],'订单结算成功','订单结算成功,增加经验值'.$task['exp'],$id);
             return true;
         });
     }

+ 6 - 0
app/extra/service/cutter/CutterService.php

@@ -26,6 +26,12 @@ class CutterService extends Service
         $list =  $this->mode->where($this->searchFilter($param))->with('cutter_apply')->field($field)->when($page&&$limit,function($query)use($page,$limit){
             $query->page($page,$limit);
         })->select();
+
+        $cutterLabelService = new CutterLabelService();
+        foreach ($list as $k=>$v){
+            $v['trade'] = $cutterLabelService->getColumn([['id','in',$v['cutter_apply']['trade']],['is_del','=',0]],'label_name');
+            $v['style'] = $cutterLabelService->getColumn([['id','in',$v['cutter_apply']['trade']],['is_del','=',0]],'label_name');
+        }
         $count = $this->mode->where($this->searchFilter($param))->count();
         return compact('list','count');
     }

+ 22 - 2
app/extra/service/cutter/CutterTaskService.php

@@ -4,6 +4,7 @@ namespace app\extra\service\cutter;
 
 use app\extra\basic\Service;
 use app\extra\dao\cutter\CutterTaskDao;
+use DI\Attribute\Inject;
 
 class CutterTaskService extends Service
 {
@@ -16,13 +17,29 @@ class CutterTaskService extends Service
         $this->dao =  new CutterTaskDao();
     }
 
+    #[Inject]
+    protected CutterOrderService $orderService;
+
     /**
      * 列表
      * @param array $param
      */
     public function getList(array $param = [],string $field = '*', int $page = 0,int $limit = 0,string $order = 'id desc')
     {
-        $list =  $this->dao->getList($this->searchFilter($param),$field,$page,$limit,$order);
+        if(isset($param['order_key']) && $param['order_key']){
+            $order = ($param['order_key'] == 'time'?'created_at':$param['order_key']).' '.$param['order_sort']??'desc';
+        }
+        if(isset($param['id']) && $param['id']){
+            $order = "id={$param['id']} desc,".$order;
+        }
+        $list =  $this->dao->getList(function($query)use($param){
+            $query->where($this->searchFilter($param))->when(isset($param['uid']) && $param['uid'],function ($query)use($param){
+                $query->whereNotIn('id',function($query)use($param){
+                    $query->name('cutter_order')->where('uid',$param['uid'])->where('status','>=',0)->field('task_id');
+                });
+            });
+        },$field,$page,$limit,$order);
+
         $count = $this->dao->count($this->searchFilter($param));
         return compact('list','count');
     }
@@ -31,8 +48,11 @@ class CutterTaskService extends Service
     {
         $filter = [];
         !empty($param['status']) && $filter[] = ["status", '=', $param['status']];
-        !empty($param['is_del']) && $filter[] = ["is_del", '=', $param['is_del']];
+        !empty($param['grade']) && $filter[] = ["grade", '<=', $param['grade']];
+        isset($param['is_del']) && $filter[] = ["is_del", '=', $param['is_del']];
+        !empty($param['type']) && $filter[] = ["type", '=', $param['type']];
         return $filter;
     }
 
+
 }

+ 14 - 5
app/extra/service/service/KefuService.php

@@ -4,7 +4,6 @@ namespace app\extra\service\service;
 
 use app\extra\basic\Service;
 use app\extra\dao\kefu\KefuDao;
-use app\model\user\User;
 use support\exception\BusinessException;
 
 class KefuService extends Service
@@ -40,10 +39,20 @@ class KefuService extends Service
 
     public function save(array $data)
     {
-        $kefu = $this->dao->getOne([['wechat|phone','in',[$data['wechat'],$data['phone']]],['is_del','=',0]]);
-        if($kefu)
-            throw new BusinessException("客服已存在!");
-        return $this->dao->save($data);
+        $id = $data['id']??0;
+        if($id){
+            unset($data['id']);
+            $kefu = $this->dao->getOne(['id' => $id,'is_del' => 0]);
+            if($kefu->isEmpty())
+                throw new BusinessException("客服不存在!");
+            return $this->dao->update(['id'=>$id],$data);
+        }else{
+            $kefu = $this->dao->getOne([['wechat|phone','in',[$data['wechat'],$data['phone']]],['is_del','=',0]]);
+            if($kefu)
+                throw new BusinessException("客服已存在!");
+            return $this->dao->save($data);
+        }
+
     }
 
 }

+ 18 - 2
app/extra/service/system/MenuService.php

@@ -3,11 +3,20 @@
 namespace app\extra\service\system;
 
 use app\extra\basic\Service;
+use app\extra\dao\system\SystemMenuDao;
 use app\model\inmei\InmeiMenu;
 use app\model\system\SystemMenu;
 
 class MenuService extends Service
 {
+    /**
+     * 设置模型
+     * @return string
+     */
+    public function __construct()
+    {
+        $this->dao =  new SystemMenuDao();
+    }
 
     /**
      * @param int $super
@@ -15,11 +24,18 @@ class MenuService extends Service
      * @param int $type
      * @return array
      */
-    public function getMenuList(int $super = 0,int $hide = 0,int $type = 1): array
+    public function getMenuList(int $roles = 0,int $hide = 0,int $type = 1): array
     {
         $model = new SystemMenu();
         try {
-            $data = $model->where("status",1)->where("from",$type)->order("sort","asc")->select();
+            if($roles>-1){
+                $systemRoleService = new SystemRoleService();
+                $rules = $systemRoleService->getColumn(['id'=>$roles],'rules');
+                $rulesStr = array_unique(explode(',', implode(',', $rules)));
+                $data = $model->where("status",1)->whereIn('id',$rulesStr)->where("from",$type)->order("sort","asc")->select();
+            }else{
+                $data = $model->where("status",1)->where("from",$type)->order("sort","asc")->select();
+            }
         } catch (\Throwable $throwable) {
             return [];
         }

+ 108 - 0
app/extra/service/system/SystemAttachmentCategoryService.php

@@ -0,0 +1,108 @@
+<?php
+
+namespace app\extra\service\system;
+
+use app\extra\basic\Service;
+use app\extra\dao\system\SystemAttachmentCategoryDao;
+use think\exception\ValidateException;
+
+class SystemAttachmentCategoryService extends Service
+{
+
+    /**
+     * 设置模型
+     * @return string
+     */
+    public function __construct()
+    {
+        $this->dao =  new SystemAttachmentCategoryDao();
+    }
+
+    /**
+     * 获取分类列表
+     * @param array $where
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function getAll(array $where)
+    {
+        $list = $this->dao->getList($this->searchFilter($where));
+        foreach ($list as &$item) {
+            $item['title'] = $item['name'];
+            $item['children'] = [];
+            if (($where['name']??'') == '' && $this->dao->count(['pid' => $item['id'], 'file_type' => $where['file_type']])) $item['loading'] = false;
+        }
+        return compact('list');
+    }
+
+    protected function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['name']) && $filter[] = ["name", '=', $param['name']];
+        !empty($param['pid']) && $filter[] = ["pid", '=', $param['pid']];
+        !empty($param['file_type']) && $filter[] = ["file_type", '=', $param['file_type']];
+        return $filter;
+    }
+
+    /**
+     * 获取分类列表(添加修改)
+     * @param array $where
+     * @return mixed
+     */
+    public function getCateList(array $where)
+    {
+        $list = $this->dao->getList(['pid' => 0, 'file_type' => $where['file_type']]);
+        $options = [['value' => 0, 'label' => '所有分类']];
+        foreach ($list as $id => $cateName) {
+            $options[] = ['label' => $cateName['name'], 'value' => $cateName['id']];
+        }
+        return $options;
+    }
+
+    /**
+     * 保存新建的资源
+     * @param array $data
+     */
+    public function save(array $data)
+    {
+        if ($this->dao->getOne(['name' => $data['name']])) {
+            throw new ValidateException('该分类已经存在');
+        }
+        $res = $this->dao->save($data);
+        if (!$res) throw new ValidateException('新增失败!');
+        return $res;
+    }
+
+    /**
+     * 保存修改的资源
+     * @param int $id
+     * @param array $data
+     */
+    public function update(int $id, array $data)
+    {
+        $attachment = $this->dao->getOne(['name' => $data['name']]);
+        if ($attachment && $attachment['id'] != $id) {
+            throw new ValidateException('该分类已经存在');
+        }
+        $res = $this->dao->update($id, $data);
+        if (!$res) throw new ValidateException('编辑失败!');
+        return $res;
+    }
+
+    /**
+     * 删除分类
+     * @param int $id
+     */
+    public function del(int $id)
+    {
+        $count = $this->dao->count(['pid' => $id]);
+        if ($count) {
+            throw new ValidateException('请先删除下级分类!');
+        } else {
+            $res = $this->dao->delete($id);
+            if (!$res) throw new ValidateException('请先删除下级分类!');
+        }
+    }
+}

+ 155 - 0
app/extra/service/system/SystemAttachmentService.php

@@ -0,0 +1,155 @@
+<?php
+
+namespace app\extra\service\system;
+
+use app\extra\basic\Service;
+use app\extra\dao\system\SystemAttachmentDao;
+use app\extra\tools\UploadExtend;
+use think\exception\ValidateException;
+
+class SystemAttachmentService extends Service
+{
+
+    /**
+     * 设置模型
+     * @return string
+     */
+    public function __construct()
+    {
+        $this->dao =  new SystemAttachmentDao();
+    }
+
+    /**
+     * 列表
+     * @param array $param
+     */
+    public function getList(array $param = [])
+    {
+        [$page,$limit] = $this->getPageValue();
+        $list =  $this->dao->getList($this->searchFilter($param),'*',$page,$limit,'id desc');
+        $count = $this->dao->count($this->searchFilter($param));
+        return compact('list','count');
+    }
+
+    protected function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['status']) && $filter[] = ["status", '=', $param['status']];
+        !empty($param['is_del']) && $filter[] = ["is_del", '=', $param['is_del']];
+        !empty($param['file_type']) && $filter[] = ["file_type", '=', $param['file_type']];
+        !empty($param['real_name']) && $filter[] = ["real_name", 'like', '%'.$param['real_name'].'%'];
+        !empty($param['pid']) && $filter[] = ["pid", '=', $param['pid']];
+        return $filter;
+    }
+
+    /**
+     * 获取图片列表
+     * @param array $where
+     * @return array
+     */
+    public function getImageList(array $where)
+    {
+        [$page, $limit] = $this->getPageValue();
+        $list = $this->dao->getList($this->searchFilter($where), '*',$page, $limit);
+        if ($list) {
+            $site_url = sConf('service.site_url');
+            foreach ($list as &$item) {
+                if ($item['file_type'] == 1) {
+                    if ($site_url) {
+                        $item['satt_dir'] = (strpos($item['satt_dir'], $site_url) !== false || strstr($item['satt_dir'], 'http') !== false) ? $item['satt_dir'] : $site_url . $item['satt_dir'];
+                        $item['att_dir'] = (strpos($item['att_dir'], $site_url) !== false || strstr($item['att_dir'], 'http') !== false) ? $item['satt_dir'] : $site_url . $item['att_dir'];
+                    }
+                }
+                $item['att_size'] = formatFileSize($item['att_size']);
+                $item['time'] = date('Y-m-d H:i:s', $item['time']);
+            }
+//            $list = get_thumb_water($list, 'mid', ['satt_dir']);
+        }
+        $where['module_type'] = 1;
+        $count = $this->dao->count($this->searchFilter($where));
+        return compact('list', 'count');
+    }
+
+    /**
+     * 删除图片
+     * @param string $ids
+     */
+    public function del(string $ids)
+    {
+        $ids = explode(',', $ids);
+        if (empty($ids)) throw new ValidateException('请选择要删除的图片');
+        foreach ($ids as $v) {
+            $attinfo = $this->dao->getOne(['att_id'=>(int)$v]);
+            if ($attinfo) {
+                try {
+                    $upload = UploadExtend::disk($attinfo['image_type']);
+                    if ($attinfo['image_type'] == 'local') {
+                        $fileArr = parse_url($attinfo['att_dir']);
+                        $filePath = $fileArr['path'] ?? $attinfo['att_dir'];
+                        if (strpos($filePath, '/') == 0) {
+                            $filePath = substr($filePath, 1);
+                        }
+                        if ($filePath) $upload->delete($filePath);
+                    } else {
+                        if ($attinfo['name']) $upload->delete($attinfo['name']);
+                    }
+                } catch (\Throwable $e) {
+                }
+                $this->dao->delete((int)$v);
+            }
+        }
+    }
+
+    /**
+     * @param array $data
+     * @return \crmeb\basic\BaseModel
+     */
+    public function move(array $data)
+    {
+        $res = $this->dao->move($data);
+        if (!$res) throw new ValidateException('移动失败或不能重复移动到同一分类下');
+    }
+
+    /**
+     * 保存附件信息
+     * @param $fileInfo
+     * @param int $pid
+     * @param int $type
+     * @param int $relation_id
+     * @param int $file_type
+     * @param int $upload_type
+     * @return bool
+     */
+    public function saveAttachment($fileInfo,int $pid = 0,int $file_type = 1, int $upload_type = 1)
+    {
+        $fileType = pathinfo($fileInfo['name'], PATHINFO_EXTENSION);
+        if ($fileInfo && !in_array($fileType, ['xlsx', 'xls'])) {
+            $data['file_type'] = $file_type;
+            $data['name'] = $fileInfo['name'];
+            $data['real_name'] = $fileInfo['real_name'] ?? $fileInfo['name'] ?? '';
+            $data['att_dir'] = $fileInfo['dir'] ?? $fileInfo['name'] ?? '';
+            if ($data['att_dir'] && strpos($data['att_dir'], 'http') === false) {
+                $data['att_dir'] = sConf('service.site_url') . $data['att_dir'];
+            }
+            $data['satt_dir'] = $fileInfo['thumb_path'] ?? $fileInfo['cover_image'] ?? '';
+            if ($file_type == 2) {
+//                if (!$data['satt_dir']) {//视频 默认封面
+//                    $data['satt_dir'] = sys_config('site_url') . '/statics/images/video_default_cover.png';
+//                }
+                if ($data['real_name'] && strpos($data['real_name'], '/') !== false) {
+                    $nameArr = explode('/', $data['real_name']);
+                    $data['real_name'] = end($nameArr) ?? $data['real_name'];
+                }
+            }
+
+            $data['att_size'] = $fileInfo['size'] ?? '';
+            $data['att_type'] = $fileInfo['type'] ?? '';
+            $data['image_type'] = $fileInfo['image_type'];
+            $data['module_type'] = 1;
+            $data['time'] = $fileInfo['time'] ?? time();
+            $data['pid'] = $pid;
+            $this->dao->save($data);
+        }
+        return true;
+    }
+}

+ 82 - 0
app/extra/service/system/SystemRoleService.php

@@ -0,0 +1,82 @@
+<?php
+
+namespace app\extra\service\system;
+
+use app\extra\basic\Service;
+use app\extra\dao\system\SystemRoleDao;
+
+class SystemRoleService extends Service
+{
+
+    /**
+     * 设置模型
+     * @return string
+     */
+    public function __construct()
+    {
+        $this->dao =  new SystemRoleDao();
+    }
+
+    /**
+     * 列表
+     * @param array $param
+     */
+    public function getList(array $param = [])
+    {
+        [$page,$limit] = $this->getPageValue();
+        $list =  $this->dao->getList($this->searchFilter($param),'*',$page,$limit,'id desc');
+        $count = $this->dao->count($this->searchFilter($param));
+        return compact('list','count');
+    }
+
+    protected function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['status']) && $filter[] = ["status", '=', $param['status']];
+//        !empty($param['is_del']) && $filter[] = ["is_del", '=', $param['is_del']];
+        return $filter;
+    }
+
+    /**
+     * 获取添加身份规格
+     */
+    public function getMenus($roles = [], int $type = 1, int $is_show = 1): array
+    {
+        $field = ['title', 'pid', 'id'];
+//        $where = ['is_del' => 0, 'type' => $type];
+//        if ($is_show) $where['sta'] = 1;
+        $where = [];
+        $menuService = new MenuService();
+//        if (!$roles) {
+            $menus = $menuService->getMenusRoule($where, $field);
+//        } else {
+//            $roles = is_string($roles) ? explode(',', $roles) : $roles;
+//            $ids = $this->dao->getRoleIds($roles);
+//            $menus = $menuService->getMenusRoule(['rule' => $ids] + $where, $field);
+//        }
+        return $this->tidyMenuTier(false, $menus);
+    }
+
+    /**
+     * 组合菜单数据
+     * @param bool $adminFilter
+     * @param $menusList
+     * @param int $pid
+     * @param array $navList
+     * @return array
+     */
+    public function tidyMenuTier(bool $adminFilter = false, $menusList = [], int $pid = 0, array $navList = []): array
+    {
+        foreach ($menusList as $k => $menu) {
+            $menu = $menu->getData();
+            if ($menu['pid'] == $pid) {
+                unset($menusList[$k]);
+                $menu['children'] = $this->tidyMenuTier($adminFilter, $menusList, $menu['id']);
+                if ($pid == 0 && !count($menu['children'])) continue;
+                if ($menu['children']) $menu['expand'] = true;
+                $navList[] = $menu;
+            }
+        }
+        return $navList;
+    }
+}

+ 30 - 7
app/extra/service/system/UserService.php

@@ -3,28 +3,51 @@
 namespace app\extra\service\system;
 
 use app\extra\basic\Service;
+use app\extra\dao\system\SystemUserDao;
 use app\model\system\SystemUser;
 
 class UserService extends Service
 {
 
+    /**
+     * 设置模型
+     * @return string
+     */
+    public function __construct()
+    {
+        $this->dao =  new SystemUserDao();
+    }
+
+    /**
+     * 列表
+     * @param array $param
+     */
+//    public function getList(array $param = [])
+//    {
+//        $this->mode = new SystemUser();
+//        return $this->searchVal($param,$this->searchFilter($param))->with(['account' => function ($query) {
+//            $query->field("shop_id,shop_name");
+//        }])->paginate([
+//            "list_rows" => $param['pageSize'],
+//            "page"      => $param['page']
+//        ]);
+//    }
+
     /**
      * 列表
      * @param array $param
      */
     public function getList(array $param = [])
     {
-        $this->mode = new SystemUser();
-        return $this->searchVal($param,$this->searchFilter($param))->with(['account' => function ($query) {
-            $query->field("shop_id,shop_name");
-        }])->paginate([
-            "list_rows" => $param['pageSize'],
-            "page"      => $param['page']
-        ]);
+        [$page,$limit] = $this->getPageValue();
+        $list =  $this->dao->getList($this->searchFilter($param)+[['id','>',1]],'*',$page,$limit,'id desc');
+        $count = $this->dao->count($this->searchFilter($param)+[['id','>',1]]);
+        return compact('list','count');
     }
 
 
 
+
     protected function searchFilter(array $param = []): array
     {
         $filter = [];

+ 76 - 0
app/extra/service/user/UserBillService.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace app\extra\service\user;
+
+use app\extra\basic\Service;
+use app\extra\dao\user\UserBillDao;
+
+class UserBillService extends Service
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    public function __construct()
+    {
+        $this->dao =  new UserBillDao();
+    }
+
+    /**
+     * 列表
+     * @param array $param
+     */
+    public function getList(array $param = [],string $field = '*', int $page = 0,int $limit = 0,string $order = 'id desc')
+    {
+        $list =  $this->dao->getList($this->searchFilter($param),$field,$page,$limit,$order);
+        $count = $this->dao->count($this->searchFilter($param));
+        return compact('list','count');
+    }
+
+    protected function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['status']) && $filter[] = ["status", '=', $param['status']];
+        !empty($param['is_del']) && $filter[] = ["is_del", '=', $param['is_del']];
+        return $filter;
+    }
+
+
+    /**
+     * 用户增加经验
+     * @param int $uid
+     * @param int $exp_num
+     */
+    public function incomeExp(int $uid,int $exp_num,string $title,string $mark,$link_id = 0)
+    {
+        if (!$uid) {
+            return false;
+        }
+
+        $userService = new UserService();
+        $user = $userService->getOne(['uid'=>$uid]);
+        if (!$user) {
+            return false;
+        }
+        if ($exp_num) {
+            $userService->incField(['uid'=>$uid], 'exp', (int)$exp_num);
+            $data = [];
+            $data['uid'] = $uid;
+            $data['number'] = $exp_num;
+            $data['category'] = 'exp';
+            $data['type'] = 'invite_user';
+            $data['title'] = $title;
+            $data['mark'] = $mark;
+            $data['balance'] = (int)$user['exp'] + (int)$exp_num;
+            $data['pm'] = 1;
+            $data['status'] = 1;
+            $data['link_id'] = $link_id;
+            $this->dao->save($data);
+        }
+        //检测会员等级
+        $userLevelService = new UserLevelService();
+        $userLevelService->detection($uid);
+        return true;
+    }
+
+}

+ 4 - 1
app/extra/service/user/UserExtractService.php

@@ -41,7 +41,7 @@ class UserExtractService extends Service
     {
         $userService = new UserService();
         $extractPrice = $user['brokerage_price'];
-        $userExtractMinPrice = 0;
+        $userExtractMinPrice = sConf('extract.extract_min_price');
         if ($data['price'] < $userExtractMinPrice) {
             throw new ValidateException('提现金额不能小于' . $userExtractMinPrice . '元');
         }
@@ -60,6 +60,9 @@ class UserExtractService extends Service
         $insertData = [
             'real_name'=>$data['real_name'],
             'uid' => $user['uid'],
+            'bank_code' => $data['bank_code'],
+            'bank_address' => $data['bank_address'],
+            'card' => $data['card'],
 //            'extract_type' => $data['extract_type'],
             'price'         => $data['price'], //提现金额
             'extract_price' => $data['price'] - $charge, //到账金额

+ 39 - 0
app/extra/service/user/UserLevelLogService.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace app\extra\service\user;
+
+use app\extra\basic\Service;
+use app\extra\dao\user\UserLevelLogDao;
+
+class UserLevelLogService extends Service
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    public function __construct()
+    {
+        $this->dao =  new UserLevelLogDao();
+    }
+
+    /**
+     * 列表
+     * @param array $param
+     */
+    public function getList(array $param = [],string $field = '*', int $page = 0,int $limit = 0,string $order = 'id desc')
+    {
+        $list =  $this->dao->getList($this->searchFilter($param),$field,$page,$limit,$order);
+        $count = $this->dao->count($this->searchFilter($param));
+        return compact('list','count');
+    }
+
+    protected function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['status']) && $filter[] = ["status", '=', $param['status']];
+        !empty($param['is_del']) && $filter[] = ["is_del", '=', $param['is_del']];
+        return $filter;
+    }
+
+
+}

+ 181 - 0
app/extra/service/user/UserLevelService.php

@@ -0,0 +1,181 @@
+<?php
+
+namespace app\extra\service\user;
+
+use app\extra\basic\Service;
+use app\extra\dao\user\UserLevelDao;
+use app\extra\service\cutter\CutterOrderService;
+use support\exception\BusinessException;
+use think\exception\ValidateException;
+
+class UserLevelService extends Service
+{
+    /**
+     * 设置模型
+     * @return string
+     */
+    public function __construct()
+    {
+        $this->dao =  new UserLevelDao();
+    }
+
+    /**
+     * 列表
+     * @param array $param
+     */
+    public function getList(array $param = [],string $field = '*', int $page = 0,int $limit = 0,string $order = 'id desc')
+    {
+        $list =  $this->dao->getList($this->searchFilter($param),$field,$page,$limit,$order);
+        $count = $this->dao->count($this->searchFilter($param));
+        return compact('list','count');
+    }
+
+    protected function searchFilter(array $param = []): array
+    {
+        $filter = [];
+        !empty($param['is_show']) && $filter[] = ["is_show", '=', $param['is_show']];
+        !empty($param['is_del']) && $filter[] = ["is_del", '=', $param['is_del']];
+        return $filter;
+    }
+
+    /**
+     * 设置用户等级
+     * @param $uid 用户uid
+     * @param $level_id 等级id
+     * @return UserLevel|bool|\think\Model
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function setUserLevel(int $uid, int $level_id, $vipinfo = [])
+    {
+        /** @var SystemUserLevelServices $systemLevelServices */
+        $systemLevelServices = app()->make(SystemUserLevelServices::class);
+        if (!$vipinfo) {
+            $vipinfo = $systemLevelServices->getLevel($level_id);
+            if (!$vipinfo) {
+                throw new AdminException('用户等级不存在');
+            }
+        }
+        /** @var  $user */
+        $user = app()->make(UserServices::class);
+        $userinfo = $user->getUserInfo($uid);
+        //把之前等级作废
+        $this->dao->update(['uid' => $uid], ['status' => 0, 'is_del' => 1]);
+        //检查是否购买过
+        $uservipinfo = $this->getWhereLevel(['uid' => $uid, 'level_id' => $level_id, 'is_del' => 0]);
+        $data['mark'] = '尊敬的用户' . $userinfo['nickname'] . '在' . date('Y-m-d H:i:s', time()) . '成为了' . $vipinfo['name'];
+        $data['add_time'] = time();
+        if ($uservipinfo) {
+            $data['status'] = 1;
+            $data['is_del'] = 0;
+            if (!$this->dao->update(['id' => $uservipinfo['id']], $data))
+                throw new AdminException('修改用户等级信息失败');
+        } else {
+            $data = array_merge($data, [
+                'is_forever' => $vipinfo->is_forever,
+                'status' => 1,
+                'is_del' => 0,
+                'grade' => $vipinfo->grade,
+                'uid' => $uid,
+                'level_id' => $level_id,
+                'discount' => $vipinfo->discount,
+            ]);
+            $data['valid_time'] = 0;
+            if (!$this->dao->save($data)) throw new AdminException('写入用户等级信息失败');
+        }
+        if ($level_id > $userinfo['level']) {
+            $change_exp = $vipinfo['exp_num'] - $userinfo['exp'];
+            $change_exp = $change_exp<0?0:$change_exp;
+            $pm = 1;
+            $type = 'system_exp_add';
+            $title = '系统增加经验';
+            $mark = '系统增加' . $change_exp . '经验';
+        } else {
+            $change_exp = $userinfo['exp'] - $vipinfo['exp_num'];
+            $change_exp = $change_exp<0?0:$change_exp;
+            $pm = 0;
+            $type = 'system_exp_sub';
+            $title = '系统减少经验';
+            $mark = '系统减少' . $change_exp . '经验';
+        }
+
+        $bill_data['uid'] = $uid;
+        $bill_data['pm'] = $pm;
+        $bill_data['title'] = $title;
+        $bill_data['category'] = 'exp';
+        $bill_data['type'] = $type;
+        $bill_data['number'] = $change_exp;
+        $bill_data['balance'] = $userinfo['exp'];
+        $bill_data['mark'] = $mark;
+        $bill_data['status'] = 1;
+        $bill_data['add_time'] = time();
+        /** @var UserBillServices $userBillService */
+        $userBillService = app()->make(UserBillServices::class);
+
+        if (!$userBillService->save($bill_data)) throw new AdminException('增加记录失败');
+        if (!$user->update(['uid' => $uid], ['level' => $level_id, 'exp' => $vipinfo['exp_num']])) throw new AdminException('修改用户用户等级失败');
+        return true;
+    }
+
+
+    /**
+     * 检测用户会员升级
+     * @param $uid
+     * @return bool
+     */
+    public function detection(int $uid)
+    {
+        $userService = new UserService();
+        $userLevelLogService = new UserLevelLogService();
+        $user = $userService->getOne(['uid'=>$uid]);
+        if (!$user) {
+            throw new ValidateException('没有此用户,无法检测升级用户等级');
+        }
+
+        $userAllLevel = $this->selectWhere([['is_del', '=', 0], ['is_show', '=', 1], ['exp_num', '<=', (float)$user['exp']]]);
+        if ($userAllLevel->isEmpty()) {
+            $userLevelLogService->update([['uid'
+                    ,'=',$uid],['grade','>',0]], ['status' =>'0','is_del'=>1]);
+            return true;
+        }
+        $userAllLevel = $userAllLevel->toArray();
+        $data = [];
+
+        $userLevel = $userLevelLogService->getColumn(['uid' => $uid, 'status' => 1, 'is_del' => 0], 'level_id');
+        foreach ($userAllLevel as $vipinfo) {
+            if (in_array($vipinfo['id'], $userLevel)) {
+                continue;
+            }
+            $data['mark'] = '尊敬的用户' . $user['nickname'] . '在' . date('Y-m-d H:i:s', time()) . '成为了' . $vipinfo['name'];
+            $uservip = $userLevelLogService->getOne(['uid' => $uid, 'level_id' => $vipinfo['id']]);
+
+            if (!$uservip->isEmpty()) {
+                //降级在升级情况
+                $data['status'] = 1;
+                $data['is_del'] = 0;
+                if (!$userLevelLogService->update($uservip['id'], $data, 'id')) {
+                    throw new ValidateException('检测升级失败2');
+                }
+            } else {
+                $data = array_merge($data, [
+                    'status' => 1,
+                    'is_del' => 0,
+                    'grade' => $vipinfo['grade'],
+                    'uid' => $uid,
+                    'level_id' => $vipinfo['id'],
+                ]);
+                if (!$userLevelLogService->save($data)) {
+                    throw new ValidateException('检测升级失败3');
+                }
+            }
+        }
+
+        $userLevelLogService->update([['uid','=',$uid],['grade','<>',end($userAllLevel)['id']??0]], ['status' =>'0']);
+        $userLevelLogService->update([['uid','=',$uid],['grade','>',end($userAllLevel)['id']??0]], ['status' =>'0','is_del' => 1]);
+        if (!$userService->update($uid, ['level' => end($userAllLevel)['id']], 'uid')) {
+            throw new ValidateException('检测升级失败4');
+        }
+        return true;
+    }
+}

+ 32 - 4
app/extra/service/user/UserService.php

@@ -22,8 +22,9 @@ class UserService extends Service
      * 列表
      * @param array $param
      */
-    public function getList(array $param = [],string $field = '*', int $page = 0,int $limit = 0,string $order = 'id desc')
+    public function getList(array $param = [],string $field = '*',string $order = 'id desc')
     {
+        [$page,$limit] = $this->getPageValue();
         $list =  $this->dao->getList($this->searchFilter($param),$field,$page,$limit,$order);
         $count = $this->dao->count($this->searchFilter($param));
         return compact('list','count');
@@ -37,6 +38,14 @@ class UserService extends Service
         return $filter;
     }
 
+    /**
+     * 用户详情
+     * @param array $data
+     * @return array
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
     public function getUserInfo(array $data):array
     {
         $user = $this->dao->getOne(['openid'=>$data['openid'],'is_del'=>0]);
@@ -48,7 +57,11 @@ class UserService extends Service
         return $user->toArray();
     }
 
-
+    /**
+     * 个人中心数据
+     * @param array $user
+     * @return array
+     */
     public function getUserProfile(array $user)
     {
         if($user['is_del'])
@@ -59,9 +72,24 @@ class UserService extends Service
         $cutterOrderService = new CutterOrderService();
         $userBrokerageService = new UserBrokerageService();
         $user['order_count'] = $cutterOrderService->count(['uid'=>$user['uid']]);
-        $user['brokerage_sum'] = $userBrokerageService->sum(['uid'=>$user['uid'],'pm'=>1],'number');
-
+        $user['brokerage_sum'] = $userBrokerageService->sum([['uid','=',$user['uid']],['pm','=',1],['type','not in',['extract_fail']]],'number');
+        if($user['level']){
+            $userLevelService = new UserLevelService();
+            $user['vip'] = $userLevelService->getOne(['id'=>$user['level']],'name,icon');
+        }
         return $user;
     }
 
+    public function rank(int $type,array $user):array
+    {
+        $where = ['is_del'=>0,'status'=>1];
+        $list =  $this->dao->getRank($where,'uid,nickname,avatar',$type);
+
+        $where['uid'] = $user['uid'];
+        $self = $this->dao->getSelfRank($where,'uid,nickname,avatar',$type);
+        $self['brokerage_sum'] = $self['brokerage_sum']?:0;
+        $jackpot = 20000;
+        return compact('list','self','jackpot');
+    }
+
 }

+ 330 - 0
app/extra/tools/JingLinExtend.php

@@ -0,0 +1,330 @@
+<?php
+
+namespace app\extra\tools;
+
+use app\extra\basic\Http;
+use think\exception\ValidateException;
+
+class JingLinExtend
+{
+
+    /**
+     * 加密方式常量
+     */
+    const ENCRYPT_NONE = 'NONE';
+    const ENCRYPT_3DES_RSA = '3DES_RSA';
+
+    /**
+     * 签名算法
+     */
+    const SIGN_ALGO = OPENSSL_ALGO_SHA256;
+
+    /**
+     * @var string 商户私钥路径或内容
+     */
+    private $privateKey;
+
+    /**
+     * @var string 平台公钥路径或内容
+     */
+    private $publicKey;
+
+    /**
+     * @var string 3DES密钥(自动生成或外部传入)
+     */
+    private $secretKey;
+
+    /**
+     * @var string 加密方式
+     */
+    private $encryptType = self::ENCRYPT_NONE;
+
+    /**
+     * 构造函数
+     *
+     * @param string $privateKey 商户私钥(文件路径或内容)
+     * @param string $publicKey 平台公钥(文件路径或内容)
+     * @param string $encryptType 加密方式 NONE/3DES_RSA
+     */
+    public function __construct($privateKey, $publicKey, $encryptType = self::ENCRYPT_NONE)
+    {
+        $this->privateKey = $this->loadKey($privateKey, 'private');
+        $this->publicKey = $this->loadKey($publicKey, 'public');
+        $this->encryptType = $encryptType;
+    }
+
+    /**
+     * 加载密钥
+     */
+    private function loadKey($key, $type)
+    {
+        // 如果是文件路径
+        if (is_file($key)) {
+            $key = file_get_contents($key);
+        }
+
+        if ($type === 'private') {
+            return openssl_pkey_get_private($key);
+        } else {
+            return openssl_pkey_get_public($key);
+        }
+    }
+
+    /**
+     * 构建请求(包含签名和加密)
+     *
+     * @param array $bizContent 业务参数(明文)
+     * @param array $extraParams 额外的公共参数(会自动过滤jrgw开头的)
+     * @return array 完整的请求参数
+     */
+    public function buildRequest($bizContent, $extraParams = [])
+    {
+        $requestParams = [];
+
+        // 1. 处理业务内容
+        if ($this->encryptType === self::ENCRYPT_3DES_RSA) {
+            // 生成随机3DES密钥
+            $this->secretKey = $this->generate3DesKey();
+
+            // 加密业务参数
+            $encryptedBiz = $this->encrypt3Des(json_encode($bizContent), $this->secretKey);
+
+            // 使用RSA加密3DES密钥
+            $encryptedKey = $this->encryptRsa($this->secretKey);
+
+            $requestParams['encrypt'] = $encryptedKey;
+            $requestParams['biz-content'] = $encryptedBiz;
+        } else {
+            // 明文模式
+            $requestParams['biz-content'] = json_encode($bizContent);
+        }
+
+        // 合并额外参数(只保留以jrgw开头的)
+        foreach ($extraParams as $key => $value) {
+            if (strpos($key, 'jrgw') === 0 && $value !== '' && $value !== null) {
+                $requestParams[$key] = $value;
+            }
+        }
+
+        // 2. 生成签名
+        $sign = $this->generateSign($requestParams);
+
+        return $sign;
+    }
+
+    /**
+     * 解析响应(包含验签和解密)
+     *
+     * @param array $responseParams 响应参数
+     * @return array 解密后的业务参数
+     * @throws Exception
+     */
+    public function parseResponse($responseParams)
+    {
+        // 1. 验签
+        $sign = isset($responseParams['sign']) ? $responseParams['sign'] : '';
+        if (!$this->verifySign($responseParams, $sign)) {
+            throw new Exception('响应签名验证失败');
+        }
+
+        // 2. 解密
+        if ($this->encryptType === self::ENCRYPT_3DES_RSA) {
+            if (!isset($responseParams['encrypt']) || !isset($responseParams['biz-content'])) {
+                throw new Exception('加密响应缺少必要参数');
+            }
+
+            // 使用私钥解密3DES密钥
+            $secretKey = $this->decryptRsa($responseParams['encrypt']);
+
+            // 使用3DES解密业务内容
+            $bizContent = $this->decrypt3Des($responseParams['biz-content'], $secretKey);
+
+            return json_decode($bizContent, true);
+        } else {
+            // 明文模式
+            if (!isset($responseParams['biz-content'])) {
+                throw new Exception('响应缺少biz-content参数');
+            }
+
+            return json_decode($responseParams['biz-content'], true);
+        }
+    }
+
+    /**
+     * 生成签名
+     *
+     * @param array $params 所有参数(包含biz-content和jrgw开头的参数)
+     * @return string 签名值
+     */
+    public function generateSign($params)
+    {
+        // 1. 筛选:获取jrgw开头的参数和biz-content
+        $signParams = [];
+        foreach ($params as $key => $value) {
+            if ((strpos($key, 'jrgw') === 0 || $key === 'biz-content') && $value !== '' && $value !== null) {
+                $signParams[$key] = $value;
+            }
+        }
+
+        // 2. 排序:按ASCII码升序
+        ksort($signParams, SORT_STRING);
+
+        // 3. 拼接:key=value&key=value
+        $stringToSign = [];
+        foreach ($signParams as $key => $value) {
+            $stringToSign[] = $key . '=' . $value;
+        }
+        $stringToSign = implode('&', $stringToSign);
+
+        // 4. 使用私钥进行SHA256withRSA签名
+        $signature = '';
+        openssl_sign($stringToSign, $signature, $this->privateKey, self::SIGN_ALGO);
+
+        return base64_encode($signature);
+    }
+
+    /**
+     * 验证签名
+     *
+     * @param array $params 所有参数(不包含sign)
+     * @param string $sign 待验证的签名值
+     * @return bool
+     */
+    public function verifySign($params, $sign)
+    {
+        // 1. 筛选:获取jrgw开头的参数和biz-content(除去sign)
+        $signParams = [];
+        foreach ($params as $key => $value) {
+            if ($key === 'sign') {
+                continue;
+            }
+            if ((strpos($key, 'jrgw') === 0 || $key === 'biz-content') && $value !== '' && $value !== null) {
+                $signParams[$key] = $value;
+            }
+        }
+
+        // 2. 排序:按ASCII码升序
+        ksort($signParams, SORT_STRING);
+
+        // 3. 拼接
+        $stringToVerify = [];
+        foreach ($signParams as $key => $value) {
+            $stringToVerify[] = $key . '=' . $value;
+        }
+        $stringToVerify = implode('&', $stringToVerify);
+
+        // 4. 验签
+        $signature = base64_decode($sign);
+        $result = openssl_verify($stringToVerify, $signature, $this->publicKey, self::SIGN_ALGO);
+
+        return $result === 1;
+    }
+
+    /**
+     * 生成3DES密钥(24字节)
+     *
+     * @return string
+     */
+    private function generate3DesKey()
+    {
+        return substr(base64_encode(openssl_random_pseudo_bytes(24)), 0, 24);
+    }
+
+    /**
+     * 3DES加密
+     *
+     * @param string $data 明文
+     * @param string $key 密钥
+     * @return string 密文(base64编码)
+     */
+    private function encrypt3Des($data, $key)
+    {
+        $iv = substr($key, 0, 8);
+        $encrypted = openssl_encrypt($data, 'DES-EDE3-CBC', $key, OPENSSL_RAW_DATA, $iv);
+        return base64_encode($encrypted);
+    }
+
+    /**
+     * 3DES解密
+     *
+     * @param string $encryptedData 密文(base64编码)
+     * @param string $key 密钥
+     * @return string 明文
+     */
+    private function decrypt3Des($encryptedData, $key)
+    {
+        $iv = substr($key, 0, 8);
+        $decrypted = openssl_decrypt(base64_decode($encryptedData), 'DES-EDE3-CBC', $key, OPENSSL_RAW_DATA, $iv);
+        return $decrypted;
+    }
+
+    /**
+     * RSA加密(用于加密3DES密钥)
+     *
+     * @param string $data 明文
+     * @return string 密文(base64编码)
+     * @throws Exception
+     */
+    private function encryptRsa($data)
+    {
+        $encrypted = '';
+        if (!openssl_public_encrypt($data, $encrypted, $this->publicKey)) {
+            throw new Exception('RSA加密失败');
+        }
+        return base64_encode($encrypted);
+    }
+
+    /**
+     * RSA解密(用于解密3DES密钥)
+     *
+     * @param string $encryptedData 密文(base64编码)
+     * @return string 明文
+     * @throws Exception
+     */
+    private function decryptRsa($encryptedData)
+    {
+        $decrypted = '';
+        if (!openssl_private_decrypt(base64_decode($encryptedData), $decrypted, $this->privateKey)) {
+            throw new Exception('RSA解密失败');
+        }
+        return $decrypted;
+    }
+
+    /**
+     * 获取当前时间(格式:yyyyMMddHHmmssSSS)
+     *
+     * @return string
+     */
+    private function getCurrentTimeMillis()
+    {
+        $now = new DateTime();
+        return $now->format('YmdHis') . sprintf('%03d', floor(microtime(true) * 1000) % 1000);
+    }
+
+    public function request(string $url,array $bizContent = [])
+    {
+        $http = new Http();
+        $extraParams = [
+            'jrgw-request-time' => $this->getCurrentTimeMillis(),
+            'jrgw-enterprise-user-id' => '',
+            'jrgw-user-id-type' => '0',
+            'gw-encrypt-type' => 'NONE',
+            'gw-sign-type' => 'SHA256withRSA',
+        ];
+
+        $extraParams['gw-sign'] = $this->buildRequest($bizContent,$extraParams);
+        $res = $http->postRequest('https://api.jddglobal.com'.$url,$bizContent,$extraParams);
+        $res = json_decode($res, true);
+        if($res && $res['code'] == 00000){
+            return $res['responseData'];
+        }else{
+            throw new ValidateException('错误码'.$res['errCode'].'错误信息'.$res['errDesc']);
+        }
+    }
+
+    public function sendBrokerage(array $bizContent = [])
+    {
+        return $this->request('/smapi/v1/ffp-common/submitNormalSalaryApi',$bizContent);
+    }
+
+}

+ 25 - 0
app/extra/tools/UploadExtend.php

@@ -119,4 +119,29 @@ class UploadExtend
         return static::disk()->{$name}(...$arguments);
     }
 
+    /**
+     * 获取上传信息
+     * @return array
+     */
+    public static function getUploadInfo($file)
+    {
+        if ($file) {
+            $config = self::getDefaultStorage();
+            $info = [];
+            foreach ($file as $k => $v) {
+                $info[] = [
+                    'name' => $v['save_name'],
+                    'image_type' => $config,
+                    'real_name' => $v['origin_name'] ?? '',
+                    'size' => $v['size'] ?? 0,
+                    'type' => $v['mime_type'] ?? 'image/jpeg',
+                    'dir' => $v['url'],
+                    'time' => time(),
+                ];
+            }
+            return $info;
+        } else {
+            return [];
+        }
+    }
 }

+ 32 - 0
app/functions.php

@@ -579,4 +579,36 @@ if (!function_exists('debase64url')) {
     {
         return CodeExtend::deSafe64($string);
     }
+}
+
+if (!function_exists('formatFileSize')) {
+
+    /**
+     * 格式化文件大小
+     * @param $size
+     * @return mixed|string|null
+     */
+    function formatFileSize($size)
+    {
+        if (!$size) {
+            return '0KB';
+        }
+        try {
+            $toKb = 1024;
+            $toMb = $toKb * 1024;
+            $toGb = $toMb * 1024;
+            if ($size >= $toGb) {
+                return round($size / $toGb, 2) . 'GB';
+            } elseif ($size >= $toMb) {
+                return round($size / $toMb, 2) . 'MB';
+            } elseif ($size >= $toKb) {
+                return round($size / $toKb, 2) . 'KB';
+            } else {
+                return $size . 'B';
+            }
+        } catch (\Exception $e) {
+            return '0KB';
+        }
+    }
+
 }

+ 46 - 0
app/model/cutter/CutterLabel.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace app\model\cutter;
+
+use app\extra\basic\Model;
+
+
+/**
+ * 用户
+ */
+class CutterLabel extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "cutter_label";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+//    public function cutterApply(): HasOne
+//    {
+//        return $this->hasOne(CutterApply::class,"uid","uid");
+//    }
+
+}

+ 28 - 4
app/model/cutter/CutterTask.php

@@ -3,6 +3,10 @@
 namespace app\model\cutter;
 
 use app\extra\basic\Model;
+use app\model\kefu\Kefu;
+use app\model\user\UserLevel;
+use think\model\relation\HasMany;
+use think\model\relation\HasOne;
 
 
 /**
@@ -38,9 +42,29 @@ class CutterTask extends Model
      */
     public bool $timestamps = false;
 
-//    public function account(): HasOne
-//    {
-//        return $this->hasOne("app\model\saas\SaasShop","shop_id","agent_id");
-//    }
+    public function kefu(): HasOne
+    {
+        return $this->hasOne(Kefu::class,"id","kefu_id")->where('is_del',0);
+    }
+
+    public function orderCount(): HasMany
+    {
+        return $this->hasMany(CutterOrder::class,"task_id","id");
+    }
+
+    public function UserOrder(): HasOne
+    {
+        return $this->hasOne(CutterOrder::class,"task_id","id");
+    }
+
+    public function grade(): HasOne
+    {
+        return $this->hasOne(UserLevel::class,"grade","grade");
+    }
+
+    public function label(): HasOne
+    {
+        return $this->hasOne(CutterLabel::class,"id","label_id");
+    }
 
 }

+ 42 - 0
app/model/system/SystemAttachment.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace app\model\system;
+
+use app\extra\basic\Model;
+
+
+/**
+ *
+ */
+class SystemAttachment extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "system_attachment";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "att_id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+}

+ 42 - 0
app/model/system/SystemAttachmentCategory.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace app\model\system;
+
+use app\extra\basic\Model;
+
+
+/**
+ *
+ */
+class SystemAttachmentCategory extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "system_attachment_category";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+}

+ 42 - 0
app/model/system/SystemRole.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace app\model\system;
+
+use app\extra\basic\Model;
+
+
+/**
+ *
+ */
+class SystemRole extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "system_role";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+
+}

+ 2 - 2
app/model/system/SystemUser.php

@@ -55,9 +55,9 @@ class SystemUser extends Model
      */
     public bool $timestamps = false;
 
-    public function account(): HasOne
+    public function role(): HasOne
     {
-        return $this->hasOne("app\model\saas\SaasShop","shop_id","agent_id");
+        return $this->hasOne(SystemRole::class,"id","roles");
     }
 
 }

+ 16 - 0
app/model/user/User.php

@@ -4,6 +4,8 @@ namespace app\model\user;
 
 use app\extra\basic\Model;
 use app\model\cutter\CutterApply;
+use app\model\cutter\CutterOrder;
+use think\model\relation\HasMany;
 use think\model\relation\HasOne;
 
 
@@ -44,5 +46,19 @@ class User extends Model
     {
         return $this->hasOne(CutterApply::class,"uid","uid");
     }
+    public function level(): HasOne
+    {
+        return $this->hasOne(UserLevel::class,"id","level");
+    }
+
+    public function cutterOrder(): HasMany
+    {
+        return $this->hasMany(CutterOrder::class,"uid","uid");
+    }
+
+    public function brokerage(): HasMany
+    {
+        return $this->hasMany(UserBrokerage::class,"uid","uid");
+    }
 
 }

+ 51 - 0
app/model/user/UserBill.php

@@ -0,0 +1,51 @@
+<?php
+
+namespace app\model\user;
+
+use app\extra\basic\Model;
+use app\model\cutter\CutterApply;
+use app\model\cutter\CutterOrder;
+use think\model\relation\HasMany;
+use think\model\relation\HasOne;
+
+
+/**
+ * 用户
+ */
+class UserBill extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "user_bill";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+//    public function cutterApply(): HasOne
+//    {
+//        return $this->hasOne(CutterApply::class,"uid","uid");
+//    }
+
+
+}

+ 60 - 0
app/model/user/UserLevel.php

@@ -0,0 +1,60 @@
+<?php
+
+namespace app\model\user;
+
+use app\extra\basic\Model;
+use app\model\cutter\CutterApply;
+use app\model\cutter\CutterOrder;
+use think\model\relation\HasMany;
+use think\model\relation\HasOne;
+
+
+/**
+ * 用户
+ */
+class UserLevel extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "user_level";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+    public function cutterApply(): HasOne
+    {
+        return $this->hasOne(CutterApply::class,"uid","uid");
+    }
+
+    public function cutterOrder(): HasMany
+    {
+        return $this->hasMany(CutterOrder::class,"uid","uid");
+    }
+
+    public function brokerage(): HasMany
+    {
+        return $this->hasMany(UserBrokerage::class,"uid","uid");
+    }
+
+}

+ 60 - 0
app/model/user/UserLevelLog.php

@@ -0,0 +1,60 @@
+<?php
+
+namespace app\model\user;
+
+use app\extra\basic\Model;
+use app\model\cutter\CutterApply;
+use app\model\cutter\CutterOrder;
+use think\model\relation\HasMany;
+use think\model\relation\HasOne;
+
+
+/**
+ * 用户
+ */
+class UserLevelLog extends Model
+{
+    /**
+     * The connection name for the model.
+     *
+     * @var string|null
+     */
+    protected $connection = 'mysql';
+    
+    /**
+     * The table associated with the model.
+     *
+     * @var string
+     */
+    protected string $table = "user_level_log";
+    
+    /**
+     * The primary key associated with the table.
+     *
+     * @var string
+     */
+    protected string $primaryKey = "id";
+    
+    /**
+     * Indicates if the model should be timestamped.
+     *
+     * @var bool
+     */
+    public bool $timestamps = false;
+
+    public function cutterApply(): HasOne
+    {
+        return $this->hasOne(CutterApply::class,"uid","uid");
+    }
+
+    public function cutterOrder(): HasMany
+    {
+        return $this->hasMany(CutterOrder::class,"uid","uid");
+    }
+
+    public function brokerage(): HasMany
+    {
+        return $this->hasMany(UserBrokerage::class,"uid","uid");
+    }
+
+}

+ 18 - 5
app/validate/adminapi/cutter/CutterTaskValidate.php

@@ -11,24 +11,37 @@ class CutterTaskValidate extends Validate
         "title"      => "require",
         "explain"    => "require",
         "material"    => "array",
-        "pirce"     => "require",
+        "price"     => "require",
         "end_time"    => "require",
-        "service_id"    => "require",
+        "kefu_id"    => "require",
         "status"     => "number|egt:0",  // 可选,传值时必须 >=0 的数字
         "id"         => "number|egt:0",  // 可选,传值时必须 >=0 的数字
+        "grade"      => "number",
+        "exp"      => "number",
+        "total"      => "number",
+        "type"      => "number",
+        "cover_video"      => "url",
+        "cover_video"      => "url",
+        "label_id"      => "number",
     ];
 
 
     protected $message = [
         "title.require"          => "请输入任务标题",
         "explain.require"        => "请输入任务说明",
-        "pirce.require"         => "请输入预算价格",
-        "end_time.require"        => "请输入截稿日期",
-        "service_id.require"        => "请设置关联客服",
+        "price.require"          => "请输入预算价格",
+        "end_time.require"       => "请输入截稿日期",
+        "kefu_id.require"        => "请设置关联客服",
         "status.number"          => "状态必须是数字",
         "status.egt"             => "状态值必须大于等于0",
         "id.number"              => "ID必须是数字",
         "id.egt"                 => "ID必须大于等于0",
+        "grade.number"           => "等级参数异常",
+        "exp.number"             => "经验值参数异常",
+        "total.number"           => "总量参数异常",
+        "type.number"            => "任务类型参数异常",
+        "cover_video.url"        => "视频链接参数异常",
+        "label_id.number"        => "标签参数异常",
     ];
 
     protected $scene = [

+ 1 - 0
app/validate/adminapi/kefu/KefuValidate.php

@@ -12,6 +12,7 @@ class KefuValidate extends Validate
         "wechat"    => "require",
         "phone"     => "require|mobile",
         "qrcode"    => "require",
+        "id"        => "int",
     ];
 
 

+ 36 - 0
app/validate/adminapi/user/UserLevelValidate.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace app\validate\adminapi\user;
+
+use think\Validate;
+
+class UserLevelValidate extends Validate
+{
+
+    protected $rule = [
+        "name"         => "require",
+        "grade"        => "int|gt:0",
+        "icon"         => "url",
+        "background"   => "url",
+        "explain"      => "string",
+        "exp_num"      => "require|int",
+        "color"        => "array",
+    ];
+
+
+    protected $message = [
+        "name.require"      => "请输入等级名称",
+        "grade.int"         => "等级类型错误",
+        "grade.gt"          => "请输入大于0的等级",
+        "icon.url"          => "请上传正确的图标地址",
+        "background.url"    => "请上传正确的背景图地址",
+        "exp_num.require"   => "请输入经验值",
+        "exp_num.int"       => "经验值需为整数",
+        "color.array"       => "颜色参数错误",
+    ];
+
+    protected $scene = [
+
+    ];
+
+}

+ 4 - 4
app/validate/api/user/CutterApplyValidate.php

@@ -9,19 +9,19 @@ class CutterApplyValidate extends Validate
 
     protected $rule = [
         "real_name"      => "require",
-        "card"           => "require",
+//        "card"           => "require",
         "phone"          => "require|mobile",
-        "wxchat"         => "require",
+        "wechat"         => "require",
         "works"          => "require",
     ];
 
 
     protected $message = [
         "real_name.require"      => "请输入真实姓名",
-        "card.require"           => "请输入身份证号",
+//        "card.require"           => "请输入身份证号",
         "phone.require"          => "请输入手机号",
         "phone.mobile"          =>  "手机号格式错误",
-        "wxchat.require"         => "请输入微信号",
+        "wechat.require"         => "请输入微信号",
         "works.require"          => "请上传作品",
     ];
 

+ 12 - 2
app/validate/api/user/UserExtractValidate.php

@@ -8,12 +8,22 @@ class UserExtractValidate extends Validate
 {
 
     protected $rule = [
-        "fail_msg"      => "require",
+        "real_name"      => "require",
+        "price"      => "require|float|gt:0",
+        "bank_code"      => "require",
+        "bank_address"      => "require",
+        "card"      => "require",
     ];
 
 
     protected $message = [
-        "fail_msg.require"      => "拒绝理由不能为空",
+        "real_name.require"      => "请填写真实姓名",
+        "price.require"      => "请填写提现金额",
+        "price.float"      => "金额类型错误",
+        "price.gt"      => "提现金额必须大于0",
+        "bank_code.require"      => "请填写银行卡号",
+        "bank_address.require"      => "请选择开户行",
+        "card.require"      => "请填写身份证号",
     ];
 
     protected $scene = [

+ 2 - 2
app/validate/system/UserValidate.php

@@ -10,14 +10,14 @@ class UserValidate extends Validate
     protected $rule = [
         "username"      => "require",
         "password"      => "require",
-        "salt"          => "require",
+//        "salt"          => "require",
     ];
 
 
     protected $message = [
         "username.require"      => "请输入登录账号",
         "password.require"      => "请输入密码",
-        "salt.require"          => "数据加密失败",
+//        "salt.require"          => "数据加密失败",
     ];
 
     protected $scene = [

+ 1 - 1
config/plugin/shopwwi/auth/app.php

@@ -25,7 +25,7 @@
 
      ],
      'jwt' => [
-         'redis' => false,
+         'redis' => true,
          // redis前缀
          'redis_prefix' => '',
          // 算法类型 ES256、HS256、HS384、HS512、RS256、RS384、RS512

+ 1 - 1
config/plugin/webman/redis-queue/redis.php

@@ -3,7 +3,7 @@ return [
     'default' => [
         'host' => 'redis://127.0.0.1:6379',
         'options' => [
-            'auth' => null,
+            'auth' => '',
             'db' => 0,
             'prefix' => '',
             'max_attempts'  => 1,

+ 1 - 1
windows.bat

@@ -1,3 +1,3 @@
 CHCP 65001
-php windows.php
+D:\phpstudy_pro\Extensions\php\php8.2.9nts\php windows.php
 pause