Kirin 2 months ago
parent
commit
eb56b51c7f
100 changed files with 6573 additions and 4517 deletions
  1. 1 1
      app/AppService.php
  2. 1 0
      app/Request.php
  3. 67 0
      app/common.php
  4. 8 2
      app/controller/admin/Common.php
  5. 1 1
      app/controller/admin/Login.php
  6. 8 8
      app/controller/admin/system/Qrcode.php
  7. 1 0
      app/controller/admin/system/SystemAdmins.php
  8. 2 1
      app/controller/admin/system/SystemClearData.php
  9. 2 2
      app/controller/admin/system/SystemMenus.php
  10. 7 6
      app/controller/admin/system/attachment/SystemAttachment.php
  11. 6 1
      app/controller/admin/system/config/SystemConfig.php
  12. 1 1
      app/controller/admin/system/config/SystemConfigTab.php
  13. 2 0
      app/controller/admin/system/config/SystemUserLevel.php
  14. 254 0
      app/controller/admin/system/store/SystemStore.php
  15. 3 4
      app/controller/admin/user/User.php
  16. 75 0
      app/controller/admin/user/UserBank.php
  17. 81 0
      app/controller/admin/user/UserExtract.php
  18. 52 51
      app/controller/api/Login.php
  19. 52 6
      app/controller/api/Pub.php
  20. 177 0
      app/controller/api/chat/Chat.php
  21. 282 0
      app/controller/api/chat/ChatGroup.php
  22. 39 0
      app/controller/api/user/User.php
  23. 111 0
      app/controller/api/user/UserFinance.php
  24. 28 28
      app/controller/api/wechat/Routine.php
  25. 14 14
      app/controller/api/wechat/Wechat.php
  26. 177 0
      app/controller/chat/Chat.php
  27. 282 0
      app/controller/chat/ChatGroup.php
  28. 2 1
      app/event.php
  29. 1 1
      app/http/middleware/api/LocationMiddleware.php
  30. 2 2
      app/listener/wechat/RoutineListener.php
  31. 143 0
      app/model/chat/ChatGroup.php
  32. 176 0
      app/model/chat/ChatGroupMember.php
  33. 133 0
      app/model/chat/ChatLog.php
  34. 1 8
      app/model/system/CityArea.php
  35. 3 3
      app/model/system/Qrcode.php
  36. 0 1
      app/model/system/SystemLog.php
  37. 13 0
      app/model/system/admin/SystemAdmin.php
  38. 12 12
      app/model/system/attachment/SystemAttachmentCategory.php
  39. 10 0
      app/model/system/config/SystemConfig.php
  40. 9 9
      app/model/system/config/SystemStorage.php
  41. 3 2
      app/model/system/config/SystemUserLevel.php
  42. 257 0
      app/model/system/store/SystemStore.php
  43. 2 2
      app/model/user/User.php
  44. 102 29
      app/model/user/UserBank.php
  45. 179 0
      app/model/user/UserExtract.php
  46. 44 0
      app/services/chat/ChatGroupMemberServices.php
  47. 44 0
      app/services/chat/ChatGroupServices.php
  48. 171 0
      app/services/chat/ChatLogServices.php
  49. 185 0
      app/services/pay/PayNotifyServices.php
  50. 153 0
      app/services/pay/PayServices.php
  51. 3 4
      app/services/system/admin/SystemAdminServices.php
  52. 14 0
      app/services/system/admin/SystemRoleServices.php
  53. 7 1
      app/services/system/attachment/SystemAttachmentServices.php
  54. 1 1
      app/services/system/config/SystemStorageServices.php
  55. 249 0
      app/services/system/store/SystemStoreServices.php
  56. 2 2
      app/services/user/LoginServices.php
  57. 10 4
      app/services/user/UserAddressServices.php
  58. 58 0
      app/services/user/UserBankServices.php
  59. 69 2
      app/services/user/UserBillServices.php
  60. 19 5
      app/services/user/UserBrokerageServices.php
  61. 198 0
      app/services/user/UserExtractServices.php
  62. 0 1
      app/services/user/UserLevelServices.php
  63. 28 2
      app/services/user/UserMoneyServices.php
  64. 2 886
      app/services/user/UserServices.php
  65. 44 44
      app/services/wechat/MessageServices.php
  66. 1 0
      app/services/wechat/RoutineServices.php
  67. 5 3
      app/services/wechat/WechatUserServices.php
  68. 72 0
      app/validate/admin/system/store/SystemStoreValidate.php
  69. 52 0
      app/validate/admin/user/UserBankValidate.php
  70. 62 0
      app/validate/admin/user/UserExtractValidate.php
  71. 1 1
      app/validate/api/LoginValidate.php
  72. 2 2
      app/validate/api/user/RegisterValidates.php
  73. 7 210
      app/webscoket/BaseHandler.php
  74. 18 4
      app/webscoket/Manager.php
  75. 2 4
      app/webscoket/Room.php
  76. 88 0
      app/webscoket/SocketPush.php
  77. 252 21
      app/webscoket/handler/UserHandler.php
  78. 6 1
      composer.json
  79. 2 8
      composer.lock
  80. 1 1
      config/cookie.php
  81. 11 12
      config/database.php
  82. 13 1
      config/swoole.php
  83. 228 676
      database.sql
  84. 0 32
      eb_store_product_description.sql
  85. 2 2
      qiniu/basic/BaseController.php
  86. 4 4
      qiniu/services/AliPayService.php
  87. 1 1
      qiniu/services/upload/storage/Cos.php
  88. 36 36
      qiniu/services/upload/storage/Local.php
  89. 31 5
      route/admin.php
  90. 93 21
      route/api.php
  91. 18 0
      vendor/autoload.php
  92. 134 34
      vendor/composer/ClassLoader.php
  93. 348 1250
      vendor/composer/InstalledVersions.php
  94. 1 1
      vendor/composer/autoload_classmap.php
  95. 8 8
      vendor/composer/autoload_files.php
  96. 1 1
      vendor/composer/autoload_namespaces.php
  97. 1 1
      vendor/composer/autoload_psr4.php
  98. 12 37
      vendor/composer/autoload_real.php
  99. 8 8
      vendor/composer/autoload_static.php
  100. 969 984
      vendor/composer/installed.php

+ 1 - 1
app/AppService.php

@@ -26,7 +26,7 @@ class AppService extends Service
     public $bind = [
         'json' => Json::class,
         'sysConfig' => SystemConfigService::class,
-];
+    ];
     public function register()
     {
         // 服务注册

+ 1 - 0
app/Request.php

@@ -132,6 +132,7 @@ class Request extends \think\Request
      * @param array $params
      * @param bool $suffix
      * @param callable|null $deal
+     * @param int $update_id
      * @param bool $filter
      * @return array
      */

+ 67 - 0
app/common.php

@@ -2,11 +2,15 @@
 // 应用公共文件
 
 use app\model\user\User;
+use app\services\user\UserServices;
 use Fastknife\Service\BlockPuzzleCaptchaService;
 use Fastknife\Service\ClickWordCaptchaService;
 use qiniu\exceptions\AuthException;
 use qiniu\services\CacheService;
 use qiniu\services\UploadService;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\DbException;
+use think\db\exception\ModelNotFoundException;
 use think\exception\ValidateException;
 use think\facade\Log;
 
@@ -732,6 +736,7 @@ if (!function_exists('check_trade_password')) {
 if (!function_exists('check_sms_captcha')) {
     function check_sms_captcha($phone, $type, $code)
     {
+        if (!check_phone($phone)) throw new AuthException('手机号码格式错误');
         $verifyCode = CacheService::get('code_' . $phone . '_' . $type);
         if (!$verifyCode)
             throw new AuthException('请先获取验证码');
@@ -786,4 +791,66 @@ if (!function_exists('curl_file_exist')) {
         curl_close($ch);
         return $httpCode == 200;
     }
+}
+
+
+if (!function_exists('checkCoordinates')) {
+    /**
+     * 检测经纬度数据
+     * @param $longitude
+     * @param $latitude
+     * @return bool
+     */
+    function checkCoordinates($longitude, $latitude)
+    {
+        if ($longitude) {
+            $longitudePattern = '/^(-?\d{1,3}(?:\.\d+)?)$/'; // 经度,允许1到3位整数,后面跟着小数
+            if (!preg_match($longitudePattern, $longitude)) {
+                return false; // 经度格式不正确
+            }
+            // 检查经纬度是否在有效范围内
+            if (($longitude < -180) || ($longitude > 180)) {
+                return false; // 经度超出范围
+            }
+        }
+        if ($latitude) {
+            $latitudePattern = '/^[-+]?([0-8]?\d(\.\d+)?|90(\.0+)?)$/'; // 纬度,允许-90到90,包括小数部分
+            if (!preg_match($latitudePattern, $latitude)) {
+                return false; // 纬度格式不正确
+            }
+            if (($latitude < -90) || ($latitude > 90)) {
+                return false; // 纬度超出范围
+            }
+        }
+        // 如果所有检查都通过,则返回true
+        return true;
+    }
+}
+
+if (!function_exists('trade_password')) {
+    /**
+     * 交易密码验证
+     * @param $password
+     * @param $uid
+     * @return void
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    function trade_password($password, $uid)
+    {
+        if (!$password) {
+            throw new ValidateException('请输入交易密码');
+        }
+        /** @var UserServices $userService */
+        $userService = app()->make(UserServices::class);
+        $user = $userService->getUserInfo($uid);
+
+        if (!$user['trade_pwd']) {
+            throw new ValidateException('请先设置交易密码');
+        }
+        if (password($password, $user['trade_salt'])[0] != $user['trade_pwd']) {
+            throw new ValidateException('交易密码错误');
+        }
+    }
 }

+ 8 - 2
app/controller/admin/Common.php

@@ -37,10 +37,16 @@ class Common extends AdminBaseController
                 'real_name' => $adminInfo['real_name'],
                 'head_pic' => $adminInfo['head_pic'],
                 'roles' => $roleServices->getRolesNames($adminInfo['roles'])
-            ]
+            ],
+            'map_key' => sys_config('tengxun_map_key')
         ]);
     }
 
+    public function getConfig()
+    {
+        return $this->success([$this->request->get('key', 'site_name') => sys_config($this->request->get('key', 'site_name'))]);
+    }
+
     /**
      * 格式化菜单
      * @return mixed
@@ -77,7 +83,7 @@ class Common extends AdminBaseController
             $list = sort_list_tier($data);
             CacheService::redisHandler()->set($cahcheKey, $list, 86400);
         }
-        return app('json')->success($list);
+        return $this->success($list);
     }
 
     /**

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

@@ -51,7 +51,7 @@ class Login extends AdminBaseController
      */
     public function info()
     {
-        $data = SystemConfigService::more(['site_name','admin_login_slide', 'site_logo_square', 'site_logo', 'login_logo'],true);
+        $data = SystemConfigService::more(['site_name', 'admin_login_slide', 'site_logo_square', 'site_logo', 'login_logo'], true);
         return $this->success([
             'slide' => sys_config('admin_login_slide') ?? [],
             'logo_square' => $data['site_logo_square'] ?? '',//透明

+ 8 - 8
app/controller/admin/system/Qrcode.php

@@ -30,14 +30,14 @@ class Qrcode extends AdminBaseController
         };
         $this->createParams = [
             ['third_type', ''],
-	        ['third_id', 0],
-	        ['ticket', ''],
-	        ['expire_seconds', 0],
-	        ['status', '1'],
-	        ['url', ''],
-	        ['qrcode_url', ''],
-	        ['scan', 0],
-	        ['type', '3']
+            ['third_id', 0],
+            ['ticket', ''],
+            ['expire_seconds', 0],
+            ['status', '1'],
+            ['url', ''],
+            ['qrcode_url', ''],
+            ['scan', 0],
+            ['type', '3']
         ];
         $this->saveDeal = $this->updateDeal = function (&$data){
         };

+ 1 - 0
app/controller/admin/system/SystemAdmins.php

@@ -15,6 +15,7 @@ use app\services\system\admin\SystemAdminServices;
 use app\services\system\admin\SystemRoleServices;
 use app\validate\admin\SystemAdminValidate;
 use think\exception\ValidateException;
+use think\Validate;
 
 class SystemAdmins extends AdminBaseController
 {

+ 2 - 1
app/controller/admin/system/SystemClearData.php

@@ -95,7 +95,8 @@ class SystemClearData extends AdminBaseController
     public function userRelevantData()
     {
         $this->service->clearData([
-            'user_money', 'user_brokerage', 'user_bill', 'user', 'user_spread', 'user_group', 'user_address'
+            'user_money', 'user_brokerage', 'user_bill', 'user', 'user_spread', 'user_group', 'user_address', 'user_level',
+            'wechat_user'
         ], true);
         $this->service->delDirAndFile('./public/uploads/store/comment');
         return $this->success('清除数据成功!');

+ 2 - 2
app/controller/admin/system/SystemMenus.php

@@ -93,7 +93,7 @@ class SystemMenus extends AdminBaseController
     public function menus()
     {
         [$menus, $unique] = $this->service->getMenusList($this->adminInfo['roles'], (int)$this->adminInfo['level']);
-        return app('json')->success(['menus' => $menus, 'unique' => $unique]);
+        return $this->success(['menus' => $menus, 'unique' => $unique]);
     }
 
 
@@ -166,6 +166,6 @@ class SystemMenus extends AdminBaseController
                 $list[] = $item;
             }
         }
-        return app('json')->success($list);
+        return $this->success($list);
     }
 }

+ 7 - 6
app/controller/admin/system/attachment/SystemAttachment.php

@@ -15,8 +15,8 @@ use app\Request;
 use app\services\system\attachment\SystemAttachmentServices;
 use app\services\system\admin\SystemAdminServices;
 use Exception;
-use qiniu\services\UploadService;
 use qiniu\services\CacheService;
+use qiniu\services\UploadService;
 use think\db\exception\DataNotFoundException;
 use think\db\exception\DbException;
 use think\db\exception\ModelNotFoundException;
@@ -37,7 +37,7 @@ class SystemAttachment extends AdminBaseController
         parent::__construct($request);
         $this->service = $service;
         $this->searchable = [
-            ['name', ''],
+            ['name', '', '', 'like_name'],
             ['pid', 0],
             ['file_type', 1]
         ];
@@ -52,6 +52,7 @@ class SystemAttachment extends AdminBaseController
     {
         $where = $this->request->getMore($this->searchable);
         $where['type'] = 1;
+        $where['module_type'] = 1;
         return $this->success($this->service->getImageList($where));
     }
 
@@ -121,7 +122,7 @@ class SystemAttachment extends AdminBaseController
     public function uploadType()
     {
         $data['upload_type'] = (string)sys_config('upload_type', 1);
-        return app('json')->success($data);
+        return $this->success($data);
     }
 
     /**
@@ -143,7 +144,7 @@ class SystemAttachment extends AdminBaseController
         $fileHandle = $this->request->file($data['file']);
         if (!$fileHandle) return $this->error('上传信息为空');
         $res = $this->service->videoUpload($data, $fileHandle);
-        return app('json')->success($res);
+        return $this->success($res);
     }
 
     /**
@@ -159,7 +160,7 @@ class SystemAttachment extends AdminBaseController
             ['upload_type', 1],//上传类型
         ]);
         $res = $this->service->saveOssVideoAttachment($data, 1, 0, (int)$data['upload_type']);
-        return app('json')->success($res);
+        return $this->success($res);
     }
 
     /**网络图片上传
@@ -173,7 +174,7 @@ class SystemAttachment extends AdminBaseController
             ['images', []]
         ]);
         $this->service->onlineUpload($data);
-        return app('json')->success('上传完成');
+        return $this->success('上传完成');
     }
 
     /**

+ 6 - 1
app/controller/admin/system/config/SystemConfig.php

@@ -20,6 +20,7 @@ use think\db\exception\DbException;
 use think\db\exception\ModelNotFoundException;
 use think\facade\App;
 use think\Response;
+use think\Validate;
 
 /**
  * 系统配置
@@ -193,18 +194,22 @@ class SystemConfig extends AdminBaseController
     public function saveConfig(Request $request)
     {
         $post = $this->request->post();
+//        var_dump($post);
         foreach ($post as $k => $v) {
             if (is_array($v)) {
                 $res = $this->service->getUploadTypeList($k);
                 foreach ($res as $kk => $vv) {
                     if ($kk == 'Upload') {
-                        if (($vv['upload_type'] ?? 1) == 1 || ($vv['upload_type'] ?? 1) == 3) {
+                        $config = json_decode($vv, true);
+                        if (($config['upload_type'] ?? 1) == 1 || ($config['upload_type'] ?? 1) == 3) {
                             $post[$k] = $v[0];
                         }
                     }
                 }
             }
         }
+//        var_dump($post);
+//        var_dump($post['spread_banner']);
         $this->validate($post, new SystemConfigValidate());
         if (isset($post['upload_type'])) {
             $this->service->checkThumbParam($post);

+ 1 - 1
app/controller/admin/system/config/SystemConfigTab.php

@@ -57,7 +57,7 @@ class SystemConfigTab extends AdminBaseController
             if (!$data['title']) throw new ValidateException('请输入分类名称');
             if ($data['pid'] > 0) {
                 $p = $this->service->getOne(['id' => $data['pid']]);
-                if (!$p) throw new ValidateException('请选择上级分类');
+                if (!$p) throw new ValidateException('请选择正确的上级分类');
                 if ($p['pid'] > 0) throw new ValidateException('仅支持二级分类');
             }
         };

+ 2 - 0
app/controller/admin/system/config/SystemUserLevel.php

@@ -72,6 +72,7 @@ class SystemUserLevel extends AdminBaseController
             return $this->error('数据不存在');
         }
         $info = $info->toArray();
+        unset($info['add_time']);
         $this->service->update((int)$id, array_merge($info, ['is_show' => $status]));
         return $this->success($status == 0 ? '关闭成功' : '开启成功');
     }
@@ -88,6 +89,7 @@ class SystemUserLevel extends AdminBaseController
             return $this->error('数据不存在');
         }
         $info = $info->toArray();
+        unset($info['add_time']);
         $res = $this->service->update((int)$id, array_merge($info, [$data['field'] => $data['value']]));
         if ($res)
             return $this->success('保存成功');

+ 254 - 0
app/controller/admin/system/store/SystemStore.php

@@ -0,0 +1,254 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+namespace app\controller\admin\system\store;
+
+use app\Request;
+use app\services\system\admin\SystemAdminServices;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\DbException;
+use think\db\exception\ModelNotFoundException;
+use think\exception\ValidateException;
+use app\common\AdminBaseController;
+use app\services\system\store\SystemStoreServices;
+use app\validate\admin\system\store\SystemStoreValidate;
+use think\Response;
+
+/**
+ * 门店控制器
+ * Class SystemStore
+ * @package app\controller\admin\system\store
+ */
+class SystemStore extends AdminBaseController
+{
+    /**
+     * @param Request $request
+     * @param SystemStoreServices $services
+     * @param SystemStoreValidate $validate
+     */
+    public function __construct(Request $request, SystemStoreServices $services, SystemStoreValidate $validate)
+    {
+        parent::__construct($request);
+        $this->service = $services;
+        $this->validate = $validate;
+        $this->searchable = [
+            ['id', ''],
+            ['type', ''],
+            ['name', ''],
+            ['product_status', ''],
+            ['product_verify_status', '']
+        ];
+        $this->searchDeal = function (&$data) {
+        };
+        $this->createParams = [
+            ['type', 1],//门店类型1:自营2加盟
+            ['name', ''],
+            ['manager_name', ''],
+            ['introduction', ''],
+            ['is_show', 1],
+            ['logo', ''],
+            ['slide_images', []],
+            ['phone', ''],
+            ['address', ''],
+            ['province', ''],
+            ['city', ''],
+            ['area', ''],
+            ['detailed_address', ''],
+            ['longitude', ''],
+            ['latitude', ''],
+            ['valid_range', 0],
+            ['store_account', ''],
+            ['store_password', ''],
+            ['product_status', 1],
+            ['uid', 0],
+            ['product_verify_status', 0],
+        ];
+        $this->saveDeal = $this->updateDeal = function (&$data, $id) {
+            $uid = $data['uid'];
+            $store = $this->service->getOne(['uid' => $uid]);
+            if ($id) {
+                if ($store['id'] != $id) {
+                    throw new ValidateException('该用户已有店铺');
+                }
+            } else {
+                if ($store) {
+                    throw new ValidateException('该用户已有店铺');
+                }
+            }
+            if (!$uid) {
+               throw new ValidateException('请选择门店管理员');
+            }
+        };
+    }
+
+    /*
+    简易路由
+
+    //门店导出
+    Route::get('store/export', 'system.store.SystemStore')->option(['real_name' => '门店导出']);
+    //门店资源路由
+    Route::resource('store', 'system.store.SystemStore')
+        ->only(['index', 'read', 'save', 'update', 'delete'])
+        ->option(['real_name' => [
+            'index' => '门店列表',
+            'read' => '门店详情',
+            'save' => '保存门店',
+            'update' => '修改门店',
+            'delete' => '删除门店'
+        ]]);
+    */
+
+
+    /**
+     * 保存新建的资源
+     *
+     * @return Response
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function save()
+    {
+        $data = $this->request->postMore($this->createParams);
+        $this->validate($data, $this->validate, 'save');
+        if (!floatval(trim($data['valid_range']))) {
+            return $this->error('请输入有效的配送范围');
+        }
+        if ($data['address'] == '') return $this->error('请选择门店地址');
+        if ($data['detailed_address'] == '') return $this->error('请输入门店详细地址');
+        $res = $this->service->saveStore(0, $data);
+        if ($res)
+            return $this->success('添加门店成功!');
+        return $this->error('添加门店失败!');
+    }
+
+
+    /**
+     * 保存新建的资源
+     *
+     * @return Response
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function update($id)
+    {
+        $data = $this->request->postMore($this->createParams);
+        $this->validate($data, $this->validate, 'update');
+        if (!floatval(trim($data['valid_range']))) {
+            return $this->error('请输入有效的配送范围');
+        }
+        if ($data['address'] == '') return $this->error('请选择门店地址');
+        if ($data['detailed_address'] == '') return $this->error('请输入门店详细地址');
+//        if ($data['type'] == 1) {//自营门店不允许自主上传商品
+//            $data['product_status'] = 0;
+//            $data['product_verify_status'] = 0;
+//        }
+        $res = $this->service->saveStore($id, $data);
+        if ($res)
+            return $this->success('保存门店成功!');
+        return $this->error('保存门店失败!');
+    }
+
+    /**
+     * 设置单个门店是否显示
+     * @param string $is_show
+     * @param string $id
+     * @return Response
+     */
+    public function set_show($is_show = '', $id = '')
+    {
+        ($is_show == '' || $id == '') && $this->error('缺少参数');
+        $res = $this->service->update((int)$id, ['is_show' => (int)$is_show]);
+        if ($res) {
+            return $this->success('设置成功');
+        } else {
+            return $this->error('设置失败');
+        }
+    }
+
+
+    /**
+     * 重置门店超级管理员账号密码
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function resetAdmin($id)
+    {
+        if (!$id) {
+            return $this->error('缺少参数');
+        }
+        $data = $this->request->postMore([
+            ['admin_id', 0],
+            ['phone', ''],
+            ['manager_name', ''],
+            ['account', ''],
+            ['password', ''],
+            ['true_password', ''],
+        ]);
+        $this->validate(['store_account' => $data['account'], 'true_password' => $data['true_password'], 'store_password' => $data['password']], new SystemStoreValidate(), 'reset');
+        if (!$data['staff_id']) {
+            return $this->error('参数错误');
+        }
+        if (!$data['password']) {
+            return $this->error('请输入密码');
+        }
+        if (!$data['true_password']) {
+            return $this->error('请输入确认密码');
+        }
+        if ($data['password'] != $data['true_password']) {
+            return $this->error('两次输入的密码不正确');
+        }
+        $this->service->resetAdmin((int)$id, $data);
+        return $this->success('操作成功!');
+    }
+
+
+    /**
+     * 删除门店
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function delete($id)
+    {
+        $id = (int)$id;
+        if (!$id) return $this->error('数据不存在');
+        $storeInfo = $this->service->get($id);
+        if (!$storeInfo) {
+            return $this->error('数据不存在');
+        }
+        /** @var SystemAdminServices $storeStaffServices */
+        $storeStaffServices = app()->make(SystemAdminServices::class);
+
+//        /** @var StoreOrderServices $storeOrderServices */
+//        $storeOrderServices = app()->make(StoreOrderServices::class);
+//        $orderCount = $storeOrderServices->count(['store_id' => $id, 'status' => 0]);
+//        if (!$orderCount) {
+//            $orderCount = $storeOrderServices->count(['store_id' => $id, 'status' => 1]);
+//            if (!$orderCount) {
+//                $orderCount = $storeOrderServices->count(['store_id' => $id, 'status' => 5]);
+//            }
+//        }
+//        if ($orderCount) {
+//            return $this->fail('删除失败,该门店还有待处理订单');
+//        }
+        if (!$storeInfo->delete()) {
+            return $this->error('删除失败,请稍候再试!');
+        } else {
+            $storeStaffServices->delete(['relation_id' => $id, 'admin_type' => 2]);
+
+            return $this->success('删除门店成功!');
+        }
+    }
+}

+ 3 - 4
app/controller/admin/user/User.php

@@ -13,7 +13,6 @@ namespace app\controller\admin\user;
 
 use app\common\AdminBaseController;
 use app\Request;
-use app\services\user\UserBillServices;
 use app\services\user\UserGroupServices;
 use app\services\user\UserLevelServices;
 use app\services\user\UserServices;
@@ -215,7 +214,7 @@ class User extends AdminBaseController
             ['group_id', 0],
             ['uids', ''],
             ['all', 0],
-            ['where', ""],
+            ['where', []],
         ], true);
         if (!$uids && $all == 0) return $this->error('缺少参数');
         if (!$group_id) return $this->error('请选择分组');
@@ -223,7 +222,7 @@ class User extends AdminBaseController
             $uids = explode(',', $uids);
         }
         if ($all == 1) {
-            $where = $where ? json_decode($where, true) : [];
+            $where = is_array($where) ? $where : json_decode($where, true);
             /** @var UserWechatuserServices $userWechatUser */
             $userWechatUser = app()->make(UserWechatuserServices::class);
             $fields = 'u.uid';
@@ -320,7 +319,7 @@ class User extends AdminBaseController
             if (!check_password($data['pwd'])) {
                 return $this->error('您设置的密码太过简单:至少6位,最多18位,包含大小写字母、数字和特殊字符');
             }
-            $this->validate(['pwd' => $data['pwd']], UserValidate::class);
+            $this->validate(['pwd' => $data['pwd'], 'phone' => $data['phone']], app()->make(UserValidate::class));
             [$data['pwd'], $data['salt']] = password($data['pwd']);
         } else {
             unset($data['pwd']);

+ 75 - 0
app/controller/admin/user/UserBank.php

@@ -0,0 +1,75 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+namespace app\controller\admin\user;
+
+use app\Request;
+use think\exception\ValidateException;
+use app\common\AdminBaseController;
+use app\services\user\UserBankServices;
+use app\validate\admin\user\UserBankValidate;
+
+/**
+ * 收款方式控制器
+ * Class UserBank
+ * @package app\controller\admin\user
+ */
+class UserBank extends AdminBaseController
+{
+    /**
+     * @param Request $request
+     * @param UserBankServices $services
+     * @param UserBankValidate $validate
+     */
+    public function __construct(Request $request, UserBankServices $services, UserBankValidate $validate)
+    {
+        parent::__construct($request);
+        $this->service = $services;
+        $this->validate = $validate;
+        $this->searchable = [
+            ['uid', ''],
+	        ['type', ''],
+	        ['bank_name', ''],
+	        ['real_name', ''],
+	        ['time', '']
+        ];
+        $this->searchDeal = function (&$data){
+        };
+        $this->createParams = [
+            ['uid', 0],
+	        ['type', ''],
+	        ['bank', ''],
+	        ['bank_name', ''],
+	        ['bank_code', ''],
+	        ['real_name', ''],
+	        ['phone', ''],
+	        ['account', ''],
+	        ['qrcode', ''],
+	        ['default', 0]
+        ];
+        $this->saveDeal = $this->updateDeal = function (&$data, $id){
+        };
+    }
+
+    /*
+    简易路由
+
+    //收款方式导出
+    Route::get('bank/export', 'user.UserBank')->option(['real_name' => '收款方式导出']);
+    //收款方式资源路由
+    Route::resource('bank', 'user.UserBank')
+        ->only(['index', 'read', 'save', 'update', 'delete'])
+        ->option(['real_name' => [
+            'index' => '收款方式列表',
+            'read' => '收款方式详情',
+            'save' => '保存收款方式',
+            'update' => '修改收款方式',
+            'delete' => '删除收款方式'
+        ]]);
+    */
+}

+ 81 - 0
app/controller/admin/user/UserExtract.php

@@ -0,0 +1,81 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+namespace app\controller\admin\user;
+
+use app\Request;
+use think\exception\ValidateException;
+use app\common\AdminBaseController;
+use app\services\user\UserExtractServices;
+use app\validate\admin\user\UserExtractValidate;
+
+/**
+ * 用户提现控制器
+ * Class UserExtract
+ * @package app\controller\admin\user
+ */
+class UserExtract extends AdminBaseController
+{
+    /**
+     * @param Request $request
+     * @param UserExtractServices $services
+     * @param UserExtractValidate $validate
+     */
+    public function __construct(Request $request, UserExtractServices $services, UserExtractValidate $validate)
+    {
+        parent::__construct($request);
+        $this->service = $services;
+        $this->validate = $validate;
+        $this->searchable = [
+            ['uid', ''],
+	        ['real_name', ''],
+	        ['extract_type', ''],
+	        ['fail_time', ''],
+	        ['time', ''],
+	        ['status', '']
+        ];
+        $this->searchDeal = function (&$data){
+        };
+        $this->createParams = [
+            ['uid', 0],
+	        ['real_name', ''],
+	        ['extract_type', '0'],
+	        ['bank_code', '0'],
+	        ['bank_address', ''],
+	        ['alipay_code', ''],
+	        ['extract_price', 0.00],
+	        ['extract_fee', 0.00],
+	        ['balance', 0.00],
+	        ['mark', ''],
+	        ['fail_msg', ''],
+	        ['fail_time', '0'],
+	        ['status', '0'],
+	        ['wechat', ''],
+	        ['qrcode_url', '']
+        ];
+        $this->saveDeal = $this->updateDeal = function (&$data, $id){
+        };
+    }
+
+    /*
+    简易路由
+
+    //用户提现导出
+    Route::get('extract/export', 'user.UserExtract')->option(['real_name' => '用户提现导出']);
+    //用户提现资源路由
+    Route::resource('extract', 'user.UserExtract')
+        ->only(['index', 'read', 'save', 'update', 'delete'])
+        ->option(['real_name' => [
+            'index' => '用户提现列表',
+            'read' => '用户提现详情',
+            'save' => '保存用户提现',
+            'update' => '修改用户提现',
+            'delete' => '删除用户提现'
+        ]]);
+    */
+}

+ 52 - 51
app/controller/api/Login.php

@@ -43,13 +43,13 @@ class Login extends ApiBaseController
      * @return mixed
      * @throws DataNotFoundException|ModelNotFoundException|DbException
      */
-    public function login(Request $request)
+    public function login()
     {
-        [$account, $password, $spread_uid, $login_type] = $request->postMore([
+        [$account, $password, $spread_uid, $login_type] = $this->request->postMore([
             'account', 'password', 'spread_uid', ['login_type', 'account']
         ], true);
         if (!$account || !$password) {
-            return app('json')->fail('请输入账号和密码');
+            return $this->error('请输入账号和密码');
         }
         if (!in_array($login_type, ['phone', 'account'])) {
             return $this->error('请选择登录方式');
@@ -57,24 +57,23 @@ class Login extends ApiBaseController
         validate(\app\validate\api\LoginValidate::class)->check(['account' => $account, 'pwd' => $password]);
 
         if ($login_type == 'phone') {
-            if (!check_phone($account)) return app('json')->fail('请输入正确的手机号码');
+            if (!check_phone($account)) return $this->error('请输入正确的手机号码');
         }
 
-        return app('json')->success('登录成功', $this->service->login($account, $login_type, $password, $spread_uid));
+        return $this->success('登录成功', $this->service->login($account, $login_type, $password, $spread_uid));
     }
 
 
     /**
      * 退出登录
-     * @param Request $request
      * @return mixed
      * @throws InvalidArgumentException
      */
-    public function logout(Request $request)
+    public function logout()
     {
-        $key = trim(ltrim($request->header(Config::get('cookie.token_name')), 'Bearer'));
+        $key = trim(ltrim($this->request->header(Config::get('cookie.token_name')), 'Bearer'));
         CacheService::redisHandler()->delete(md5($key));
-        return app('json')->success('成功');
+        return $this->success('成功');
     }
 
 
@@ -83,15 +82,15 @@ class Login extends ApiBaseController
         $unique = password_hash(uniqid(true), PASSWORD_BCRYPT);
         CacheService::set('sms.key.' . $unique, 0, 300);
         $time = sys_config('verify_expire_time', 1);
-        return app('json')->success(['key' => $unique, 'expire_time' => $time]);
+        return $this->success(['key' => $unique, 'expire_time' => $time]);
     }
 
-    public function captcha(Request $request)
+    public function captcha()
     {
         ob_clean();
         $rep = captcha();
         $key = app('session')->get('captcha.key');
-        $uni = $request->get('key');
+        $uni = $this->request->get('key');
         if ($uni)
             CacheService::set('sms.key.cap.' . $uni, $key, 300);
 
@@ -129,28 +128,28 @@ class Login extends ApiBaseController
     /**
      * @return mixed
      */
-    public function ajcaptcha(Request $request)
+    public function ajcaptcha()
     {
-        $captchaType = $request->get('captchaType');
-        return app('json')->success(aj_captcha_create((string)$captchaType));
+        $captchaType = $this->request->get('captchaType');
+        return $this->success(aj_captcha_create((string)$captchaType));
     }
 
     /**
      * 一次验证
      * @return mixed
      */
-    public function ajcheck(Request $request)
+    public function ajcheck()
     {
-        [$token, $pointJson, $captchaType] = $request->postMore([
+        [$token, $pointJson, $captchaType] = $this->request->postMore([
             ['token', ''],
             ['pointJson', ''],
             ['captchaType', ''],
         ], true);
         try {
             aj_captcha_check_one($captchaType, $token, $pointJson);
-            return app('json')->success();
+            return $this->success();
         } catch (\Throwable $e) {
-            return app('json')->fail(400336);
+            return $this->error(400336);
         }
     }
 
@@ -163,9 +162,9 @@ class Login extends ApiBaseController
      * @throws InvalidArgumentException
      * @throws ModelNotFoundException
      */
-    public function verify(Request $request)
+    public function verify()
     {
-        [$phone, $type, $key, $captchaType, $captchaVerification] = $request->postMore([
+        [$phone, $type, $key, $captchaType, $captchaVerification] = $this->request->postMore([
             ['phone', 0],
             ['type', ''],
             ['key', ''],
@@ -184,29 +183,29 @@ class Login extends ApiBaseController
         if (CacheService::has($nowKey)) {
             $total = CacheService::get($nowKey);
             if ($total > Config::get('sms.maxMinuteCount', 20))
-                return app('json')->success('触发分钟级流控:' . Config::get('sms.maxMinuteCount', 20));
+                return $this->success('触发分钟级流控:' . Config::get('sms.maxMinuteCount', 20));
         }
 
         //二次验证
         try {
             aj_captcha_check_two($captchaType, $captchaVerification);
         } catch (\Throwable $e) {
-            return app('json')->fail($e->getError());
+            return $this->error($e->getError());
         }
 
         try {
             validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
         } catch (ValidateException $e) {
-            return app('json')->fail($e->getError());
+            return $this->error($e->getError());
         }
         $time = sys_config('verify_expire_time', 1);
         $smsCode = $this->service->verify($phone, $type, $time, app()->request->ip());
         if ($smsCode) {
             CacheService::set('code_' . $phone . '_' . $type, $smsCode, $time * 60);
             CacheService::set($nowKey, $total, 61);
-            return app('json')->success('发送成功');
+            return $this->success('发送成功');
         } else {
-            return app('json')->fail('发送失败');
+            return $this->error('发送失败');
         }
 
     }
@@ -215,11 +214,13 @@ class Login extends ApiBaseController
      * H5注册新用户
      * @param Request $request
      * @return mixed
-     * @throws InvalidArgumentException
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
      */
-    public function register(Request $request)
+    public function register()
     {
-        [$phone, $captcha, $password, $nickname, $spread_uid] = $request->postMore([
+        [$phone, $captcha, $password, $nickname, $spread_uid] = $this->request->postMore([
             ['phone', ''],//手机号
             ['captcha', ''],//验证码
             ['password', ''],//密码
@@ -233,15 +234,15 @@ class Login extends ApiBaseController
                 'password' => $password,
             ]);
         } catch (ValidateException $e) {
-            return app('json')->fail($e->getError());
+            return $this->error($e->getError());
         }
         check_sms_captcha($phone, 'register', $captcha);
-        $user_type = $request->getFromType() ? $request->getFromType() : 'h5';
+        $user_type = $this->request->getFromType() ? $this->request->getFromType() : 'h5';
         $registerStatus = $this->service->register($phone, $password, $spread_uid, $user_type, $nickname);
         if ($registerStatus) {
-            return app('json')->success('注册成功');
+            return $this->success('注册成功');
         }
-        return app('json')->fail('注册失败');
+        return $this->error('注册失败');
     }
 
     /**
@@ -252,9 +253,9 @@ class Login extends ApiBaseController
      * @throws DbException
      * @throws ModelNotFoundException
      */
-    public function reset(Request $request)
+    public function reset()
     {
-        [$account, $captcha, $password] = $request->postMore([['phone', ''], ['captcha', ''], ['password', '']], true);
+        [$account, $captcha, $password] = $this->request->postMore([['phone', ''], ['captcha', ''], ['password', '']], true);
         check_sms_captcha($account, 'reset', $captcha);
         try {
             validate(RegisterValidates::class)->scene('register')->check([
@@ -263,13 +264,13 @@ class Login extends ApiBaseController
                 'password' => $password,
             ]);
         } catch (ValidateException $e) {
-            return app('json')->fail($e->getError());
+            return $this->error($e->getError());
         }
         $resetStatus = $this->service->reset($account, $password);
         if ($resetStatus) {
-            return app('json')->success('修改成功');
+            return $this->success('修改成功');
         }
-        return app('json')->fail('修改失败');
+        return $this->error('修改失败');
     }
 
     /**
@@ -280,18 +281,18 @@ class Login extends ApiBaseController
      * @throws DbException
      * @throws ModelNotFoundException
      */
-    public function reset_trade_pwd(Request $request)
+    public function reset_trade_pwd()
     {
-        [$captcha, $password] = $request->postMore([['captcha', ''], ['password', '']], true);
-        $account = $request->user()['phone'] ?? '0';
-        check_sms_captcha($account, 'reset', $captcha);
+        [$captcha, $password] = $this->request->postMore([['captcha', ''], ['password', '']], true);
+        $account = $this->request->user()['phone'] ?? '0';
+        check_sms_captcha($account, 'reset_trade', $captcha);
         if (!check_trade_password($password))
-            return app('json')->fail('交易密码为6位数字');
+            return $this->error('交易密码为6位数字');
         $resetStatus = $this->service->trade_reset($account, $password);
         if ($resetStatus) {
-            return app('json')->success('修改成功');
+            return $this->success('修改成功');
         }
-        return app('json')->fail('修改失败');
+        return $this->error('修改失败');
     }
 
     /**
@@ -300,22 +301,22 @@ class Login extends ApiBaseController
      * @return mixed
      * @throws Exception
      */
-    public function mobile(Request $request)
+    public function mobile()
     {
-        [$phone, $captcha, $spread_uid] = $request->postMore([['phone', ''], ['captcha', ''], ['spread_uid', 0]], true);
+        [$phone, $captcha, $spread_uid] = $this->request->postMore([['phone', ''], ['captcha', ''], ['spread_uid', 0]], true);
         //验证手机号
         try {
             validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
         } catch (ValidateException $e) {
-            return app('json')->fail($e->getError());
+            return $this->error($e->getError());
         }
         check_sms_captcha($phone, 'mobile', $captcha);
-        $user_type = $request->getFromType() ? $request->getFromType() : 'h5';
+        $user_type = $this->request->getFromType() ? $this->request->getFromType() : 'h5';
         $token = $this->service->mobile($phone, $spread_uid, $user_type);
         if ($token) {
-            return app('json')->success('登录成功', $token);
+            return $this->success('登录成功', $token);
         } else {
-            return app('json')->fail('登录失败');
+            return $this->error('登录失败');
         }
     }
 }

+ 52 - 6
app/controller/api/Pub.php

@@ -9,6 +9,8 @@
 namespace app\controller\api;
 
 use app\common\ApiBaseController;
+use app\Request;
+use app\services\system\store\SystemStoreServices;
 use app\services\system\CityAreaServices;
 use app\services\system\attachment\SystemAttachmentServices;
 use Psr\SimpleCache\InvalidArgumentException;
@@ -21,6 +23,10 @@ use think\db\exception\ModelNotFoundException;
 class Pub extends ApiBaseController
 {
 
+    public function test()
+    {
+    }
+
     /**
      * 获取版本信息
      * @return mixed
@@ -29,7 +35,20 @@ class Pub extends ApiBaseController
     {
         $version = sys_config('app_version', '');
         $apk = sys_config('app_apk', '');
-        return $this->success(compact('version', 'apk'));
+        $ios_up_url = sys_config('ios_up_url', '');
+        return $this->success(compact('version', 'apk', 'ios_up_url'));
+    }
+
+    /**
+     * 获取站点基本配置
+     * @return mixed
+     */
+    public function index()
+    {
+        $site_name = sys_config('site_name', '');
+        $site_logo = sys_config('site_logo', '');
+        $address = $this->getAddress();
+        return $this->success(compact('site_name', 'site_logo', 'address'));
     }
 
     /**
@@ -52,7 +71,7 @@ class Pub extends ApiBaseController
             return $this->error($upload->getError());
         }
         $res = $upload->getUploadInfo();
-        $services->attachmentAdd($res['name'], $res['size'], $res['type'], $res['dir'], $res['thumb_path'], 1, (int)sys_config('upload_type', 1), $res['time'], 3);
+        $services->attachmentAdd($res['name'], $res['size'], $res['type'], $res['dir'], $res['thumb_path'], 1, (int)sys_config('upload_type', 1), $res['time'], 2);
         if (CacheService::has('start_uploads_' . $request->uid()))
             $start_uploads = (int)CacheService::get('start_uploads_' . $request->uid());
         else
@@ -61,7 +80,7 @@ class Pub extends ApiBaseController
         CacheService::set('start_uploads_' . $request->uid(), $start_uploads, 86400);
         $res['dir'] = path_to_url($res['dir']);
         if (strpos($res['dir'], 'http') === false) $res['dir'] = sys_config('site_url') . $res['dir'];
-        return $this->success('图片上传成功!', ['name' => $res['name'], 'url' => $res['dir']]);
+        return $this->success('上传成功!', ['name' => $res['name'], 'url' => $res['dir']]);
     }
 
     /**
@@ -92,11 +111,38 @@ class Pub extends ApiBaseController
     {
         $address = $this->request->param('address', '');
         if (!$address)
-            return app('json')->fail('地址不存在');
+            return $this->error('地址不存在');
 
         $city = $services->searchCity(compact('address'));
-        if (!$city) return app('json')->fail('地址暂未录入,请联系管理员');
+        if (!$city) return $this->error('地址暂未录入,请联系管理员');
         $where = [['id', 'in', array_merge([$city['id']], explode('/', trim($city->path, '/')))]];
-        return app('json')->success($services->getCityList($where, 'id as value,id,name as label,parent_id as pid', ['children']));
+        return $this->success($services->getCityList($where, 'id as value,id,name as label,parent_id as pid', ['children']));
+    }
+
+
+    /**
+     * 门店列表
+     * @param Request $request
+     * @param SystemStoreServices $services
+     * @return mixed
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\DbException
+     * @throws \think\db\exception\ModelNotFoundException
+     */
+    public function store_list(SystemStoreServices $services)
+    {
+        list($latitude, $longitude) = $this->request->location();
+        [$store_id, $keyword] = $this->request->getMore([
+            ['store_id', 0],    //选择门店ID
+            ['keyword', '']
+        ], true);
+        if (!checkCoordinates($longitude, $latitude)) {
+            return $this->error('参数错误');
+        }
+        $where = ['type' => '', 'is_show' => 1, 'keyword' => $keyword];
+        $field = ['id', 'name', 'introduction', 'phone', 'logo', 'slide_images', 'latitude', 'longitude', 'address', 'detailed_address', 'is_show', 'valid_range'];
+        $data['list'] = $services->getStoreList($where, $field, $latitude, $longitude, [], $store_id);
+//        $data['tengxun_map_key'] = sys_config('tengxun_map_key');
+        return $this->success($data);
     }
 }

+ 177 - 0
app/controller/api/chat/Chat.php

@@ -0,0 +1,177 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @author: Kirin
+ * @day: 2024/11/12
+ * @time: 16:31
+ */
+
+namespace app\controller\api\chat;
+
+
+use app\common\ApiBaseController;
+use app\Request;
+use app\services\chat\ChatGroupMemberServices;
+use app\services\chat\ChatGroupServices;
+use app\services\chat\ChatLogServices;
+use app\services\decoration\DecorationDesignerServices;
+use app\services\decoration\DecorationSalespersonServices;
+use app\services\decoration\DecorationWorkerServices;
+use app\services\system\store\SystemStoreServices;
+use app\services\user\UserServices;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\DbException;
+use think\db\exception\ModelNotFoundException;
+
+class Chat extends ApiBaseController
+{
+    private $groupMemberService;
+    private $groupService;
+
+    public function __construct(Request $request, ChatLogServices $service, ChatGroupMemberServices $groupMemberService, ChatGroupServices $groupService)
+    {
+        parent::__construct($request);
+        $this->service = $service;
+        $this->groupMemberService = $groupMemberService;
+        $this->groupService = $groupService;
+    }
+
+
+    /**
+     * 聊天列表
+     * @param Request $request
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function index(Request $request)
+    {
+        $user_chat = $this->service->search()
+            ->where('uid|to_uid', $request->uid())
+//            ->where('add_time', '>=', time() - 7 * 86400)
+            ->where('group_id', 0)
+            ->field('if(uid=' . $request->uid() . ',to_uid,uid) as user_id,sum(if(status=0 && to_uid=' . $request->uid() . ',1,0)) as unread_count,max(add_time) as last_time,to_uid_type,uid_type')
+            ->group('user_id,to_uid_type,uid_type')
+            ->select();
+        foreach ($user_chat as &$v) {
+            $v['is_group'] = 0;
+            $v['f_info'] = $this->service->getInfo($v['to_uid_type'], $v['user_id']);
+            $user_uid = $request->uid();
+            $to_uid = $v['user_id'];
+            $v['last_msn'] = $this->service->search()->where(function ($query) use ($user_uid, $to_uid) {
+                $query->where(function ($q) use ($user_uid, $to_uid) {
+                    $q->where('uid', $user_uid)->where('to_uid', $to_uid);
+                })->whereOr(function ($q) use ($user_uid, $to_uid) {
+                    $q->where('uid', $to_uid)->where('to_uid', $user_uid);
+                });
+            })->order('add_time desc,id desc')->find();
+        }
+
+        $groups = $this->groupMemberService->search()->where('uid', $request->uid())->column('chat_group_id');
+        $groups = $this->groupService->search()->where('id', 'in', $groups)->column('id');
+        $group_chat = $this->service->search()->where('group_id', 'in', $groups)
+//            ->where('add_time', '>=', time() - 7 * 86400)
+            ->where('group_id', '>', 0)
+            ->field('group_id,sum(if(find_in_set(' . $request->uid() . ',group_see),0,1)) as unread_count,max(add_time) as last_time')
+            ->group('group_id')->select();
+        foreach ($group_chat as &$v) {
+            $v['is_group'] = 1;
+            $v['last_msn'] = $this->service->search()->where('group_id', $v['group_id'])
+                ->order('add_time desc,id desc')->find();
+            $v['at'] = $this->service->search()->where('group_id', $v['group_id'])
+                ->where('at', $request->uid())
+                ->where('find_in_set(' . $request->uid() . ',group_see)', '<=', 0)
+                ->where('find_in_set(' . $request->uid() . ',at)')
+                ->count();
+            $v['group_info'] = $this->groupService->get($v['group_id']);
+            $v['identity'] = $this->groupMemberService->search()->where('uid', $request->uid())->where('chat_group_id', $v['group_id'])->value('identity');
+        }
+        $log_list = array_merge($user_chat->toArray(), $group_chat->toArray());
+        usort($log_list, function ($a, $b) {
+            return -($a['last_time'] <=> $b['last_time']);
+        });
+        return $this->success('ok', $log_list);
+    }
+
+    /**
+     * 聊天记录
+     * @param $uid
+     * @param $type
+     * @param Request $request
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function chatLog(Request $request)
+    {
+        $page = $request->get('page', 1);
+        $limit = $request->get('limit', 30);
+        $user_uid = $request->uid();
+        list($uid, $user_type, $type) = $this->request->getMore([
+            ['uid', 0],
+            ['user_type', 0],
+            ['type', 0]
+        ], true);
+        $to_uid = $uid;
+        $log_list = $this->service->search()->where(function ($query) use ($user_uid, $to_uid, $type, $user_type) {
+            $query->where(function ($q) use ($user_uid, $to_uid, $type, $user_type) {
+                $q->where('uid', $user_uid)->where('to_uid', $to_uid)->where('to_uid_type', $type)->where('uid_type', $user_type);
+            })->whereOr(function ($q) use ($user_uid, $to_uid, $type, $user_type) {
+                $q->where('uid', $to_uid)->where('to_uid', $user_uid)->where('uid_type', $type)->where('to_uid_type', $user_type);
+            });
+        })->page($page, $limit)->order('add_time desc,id desc')->select();
+        $f_info = $this->service->getInfo($type, $to_uid);
+        $u_info = $this->service->getInfo($user_type, $user_uid);
+        return $this->success('ok', compact('log_list', 'f_info', 'u_info'));
+    }
+
+
+    public function setRead(Request $request)
+    {
+        list($uid, $user_type, $type) = $this->request->postMore([
+            ['uid', 0],
+            ['user_type', 0],
+            ['type', 0]
+        ], true);
+        $this->service->search()->where('uid', $uid)->where('to_uid', $request->uid())->where('uid_type', $user_type)->where('to_uid_type', $type)->update(['status' => 1]);
+        return $this->success('ok');
+    }
+
+
+    public function groupChatLog($group_id, Request $request)
+    {
+        if (!$user = $this->groupMemberService->search()->where('uid', $request->uid())->where('chat_group_id', $group_id)->find()) {
+            return $this->error('你没有权限');
+        }
+        $group = $this->groupService->search()->where('id', $group_id)->find();
+        if (!$group) return $this->error('群不存在');
+        $page = $request->get('page', 1);
+        $limit = $request->get('limit', 30);
+        $log_list = $this->service->search()->where('group_id', $group_id)
+            ->page($page, $limit)
+            ->where('add_time', '>=', $user['add_time'])
+            ->order('add_time desc,id desc')
+            ->select();
+        foreach ($log_list as &$v) {
+            $member = $this->groupMemberService->search()->where('chat_group_id', $group_id)->where('uid', $v['uid'])->find();
+            $v['f_info'] = $this->service->getInfo($member['identity'], $member['uid']);
+            $v['member_info'] = $member;
+        }
+        return $this->success('ok', compact('log_list'));
+    }
+
+    public function setGroupRead($group_id, Request $request)
+    {
+        if (!$user = $this->groupMemberService->search()->where('uid', $request->uid())->where('chat_group_id', $group_id)->find()) {
+            return $this->error('你没有权限');
+        }
+        $group = $this->groupService->search()->where('id', $group_id)->find();
+        if (!$group) return $this->error('群不存在');
+        $this->service->search()->where('group_id', $group_id)
+            ->where('!find_in_set(' . $request->uid() . ',group_see)')
+            ->update(['group_see' => ['exp', 'CONCAT(group_see,",' . $request->uid() . '")']]);
+        return $this->success();
+    }
+}

+ 282 - 0
app/controller/api/chat/ChatGroup.php

@@ -0,0 +1,282 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @author: Kirin
+ * @day: 2024/11/12
+ * @time: 16:35
+ */
+
+namespace app\controller\api\chat;
+
+
+use app\common\ApiBaseController;
+use app\Request;
+use app\services\chat\ChatGroupMemberServices;
+use app\services\chat\ChatGroupServices;
+use app\services\chat\ChatLogServices;
+use app\services\user\UserServices;
+use app\webscoket\SocketPush;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\DbException;
+use think\db\exception\ModelNotFoundException;
+use think\Exception;
+
+/**
+ * Class ChatGroup
+ * @package app\controller\api\chat
+ */
+class ChatGroup extends ApiBaseController
+{
+    /** @var ChatGroupServices $groupService */
+    private $groupService;
+    /** @var ChatGroupMemberServices $groupMemberService */
+    private $groupMemberService;
+
+    /**
+     * @param Request $request
+     * @param ChatLogServices $service
+     * @param ChatGroupMemberServices $groupMemberService
+     * @param ChatGroupServices $groupService
+     */
+    public function __construct(Request $request, ChatLogServices $service, ChatGroupMemberServices $groupMemberService, ChatGroupServices $groupService)
+    {
+        parent::__construct($request);
+        $this->service = $service;
+        $this->groupMemberService = $groupMemberService;
+        $this->groupService = $groupService;
+    }
+
+    /**
+     * 我的群列表
+     * @para
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function group()
+    {
+        $groups = $this->groupMemberService->getColumn(['uid' => $this->request->uid()], 'id');
+        $list = $this->groupService->search()->where('id', 'in', $groups)
+            ->order('last_message_time', 'desc')
+            ->select();
+        return $this->success('ok', compact('list'));
+    }
+
+
+    /**
+     * 群详情
+     * @param $id
+     * @para
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function groupInfo($id)
+    {
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        return $this->success('ok', compact('group'));
+    }
+
+    /**
+     * 群成员列表
+     * @param $id
+     * @para
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function groupMembers($id)
+    {
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        $list = $this->groupMemberService->search()->where('chat_group_id', $id)->select();
+        foreach ($list as &$v) {
+            $v['ext_info'] = $this->service->getInfo($v['identity'], $v['uid']);
+        }
+        return $this->success('ok', compact('list'));
+    }
+
+    /**
+     * 添加群成员
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     * @para
+     */
+    public function groupAddMember($id)
+    {
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        if (!$this->groupMemberService->search()->where('uid', $this->request->uid())->where('chat_group_id', $id)->where('is_hoster', 1)->find()) {
+            return $this->error('你没有权限');
+        }
+        $uid = $this->request->post('uid', 0);
+        $identity = $this->request->post('identity', 0);
+        if ($this->groupMemberService->search()->where('uid', $uid)->where('chat_group_id', $id)->find()) {
+            return $this->error('用户已在群聊中');
+        }
+        /** @var UserServices $userService */
+        $userService = app()->make(UserServices::class);
+        $user = $userService->getUserInfo($uid);
+        if (!$user) return $this->error('用户不存在');
+        $ext_info = $this->service->getInfo($identity, $uid);
+        if (!$ext_info) return $this->error('用户不存在');
+        try {
+            $this->groupMemberService->create([
+                'uid' => $uid,
+                'chat_group_id' => $id,
+                'identity' => $identity,
+            ]);
+            $this->service->create([
+                'uid' => $uid,
+                'to_uid' => 0,
+                'add_time' => time(),
+                'status' => 1,
+                'msn_type' => 'notice',
+                'group_id' => $id,
+                'msn' => $ext_info['info']['name'] . ' 加入群聊',
+                'group_see' => $uid,
+            ]);
+            $this->groupService->update($id, ['last_message_time' => time()]);
+            return $this->success('ok', ['date' => ['name' => $ext_info['info']['name'], 'type' => $ext_info['type'], 'uid' => $uid, 'add_time' => time(), 'group_id' => $id], 'type' => 'group:new_member']);
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+    }
+
+
+    /**
+     * 移除群成员
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     * @para
+     */
+    public function groupRemoveMember($id)
+    {
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        if (!$this->groupMemberService->search()->where('uid', $this->request->uid())->where('chat_group_id', $id)->where('is_hoster', 1)->find()) {
+            return $this->error('你没有权限');
+        }
+        $uid = $this->request->post('uid', 0);
+        if (!$user = $this->groupMemberService->search()->where('uid', $uid)->where('chat_group_id', $id)->find()) {
+            return $this->error('用户不在群聊中');
+        }
+        if ($user['is_hoster']) return $this->error('群主不能移除');
+
+        try {
+            $this->groupMemberService->delete($user['id']);
+            return $this->success('ok');
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+    }
+
+
+    /**
+     * 修改群昵称
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function setMark($id)
+    {
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        $mark = $this->request->post('mark');
+        $info = $this->groupMemberService->search()->where('uid', $this->request->uid())->where('chat_group_id', $id)->find();
+        if (!$info) return $this->error('你没有权限');
+        $info->nickname = $mark;
+        $res = $info->save();
+        if ($res)
+            return $this->success('修改成功');
+        else
+            return $this->error('修改失败');
+    }
+
+
+    /**
+     * 修改群信息
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     * @para
+     */
+    public function editGroup($id)
+    {
+        $info = $this->request->post('info', '');
+        $name = $this->request->post('name', '');
+        $avatar = $this->request->post('avatar', '');
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        if (!$this->groupMemberService->search()->where('uid', $this->request->uid())->where('chat_group_id', $id)->where('is_hoster', 1)->find()) {
+            return $this->error('你没有权限');
+        }
+        $res = $this->groupService->update($id, ['name' => $name, 'info' => $info, 'avatar' => $avatar]);
+        if ($res)
+            return $this->success('修改成功');
+        else
+            return $this->error('修改失败');
+    }
+
+    /**
+     * 新增群公告
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     * @para
+     */
+    public function setNotice($id)
+    {
+        $notice = $this->request->post('notice', '');
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        if (!$this->groupMemberService->search()->where('uid', $this->request->uid())->where('chat_group_id', $id)->where('is_hoster', 1)->find()) {
+            return $this->error('你没有权限');
+        }
+        $res = $this->groupService->update($id, ['notice' => $notice]);
+        $this->service->create([
+            'uid' => $this->request->uid(),
+            'to_uid' => 0,
+            'add_time' => time(),
+            'status' => 1,
+            'msn_type' => 'announcement',
+            'group_id' => $id,
+            'msn' => '群公告' . ':' . $notice,
+            'group_see' => $this->request->uid(),
+        ]);
+
+        /** @var ChatGroupMemberServices $chatMemberService */
+        $chatMemberService = app()->make(ChatGroupMemberServices::class);
+
+        $members = $chatMemberService->getColumn(['chat_group_id' => $id], 'uid');
+        foreach ($members as $member) {
+            SocketPush::user()->toGroup($member, $id)->type('announcement')
+                ->data('群公告' . ':' . $notice)
+                ->push();
+        }
+
+        $res = $this->groupService->update($id, ['last_message_time' => time()]);
+        if ($res)
+            return $this->success('修改成功', ['type' => 'group:notice', 'data' => ['notice' => $notice]]);
+        else
+            return $this->error('修改失败');
+    }
+
+
+}

+ 39 - 0
app/controller/api/user/User.php

@@ -66,5 +66,44 @@ class User extends ApiBaseController
         }
     }
 
+    /**
+     * 手机号换绑
+     */
+    public function changeMobile()
+    {
+        $user = $this->request->user();
+        [$new_phone, $old_captcha, $new_captcha] = $this->request->postMore([['new_phone', ''], ['old_captcha', ''], ['new_captcha', '']], true);
+        //验证手机号
+
+        check_sms_captcha($user['phone'], 'change', $old_captcha);
+        check_sms_captcha($new_phone, 'change_new', $new_captcha);
+
+        $res = $this->service->update($user['uid'], ['phone' => $new_phone]);
+        if ($res) {
+            return $this->success('修改成功');
+        } else {
+            return $this->error('修改失败');
+        }
+    }
+
+    public function edit()
+    {
+        $user = $this->request->user();
+        $data = $this->request->postMore([
+            ['nickname', ''],
+            ['avatar', '']
+        ]);
+        $data = array_filter($data);
+        if (!$data) {
+            return $this->error('没有修改任何信息');
+        }
+        $res = $this->service->update($user['uid'], $data);
+        if ($res) {
+            return $this->success('修改成功');
+        } else {
+            return $this->error('修改失败');
+        }
+    }
+
 
 }

+ 111 - 0
app/controller/api/user/UserFinance.php

@@ -0,0 +1,111 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @author: Kirin
+ * @day: 2024/12/16
+ * @time: 11:29
+ */
+
+namespace app\controller\api\user;
+
+
+use app\common\ApiBaseController;
+use app\Request;
+use app\services\user\UserBillServices;
+use app\services\user\UserBrokerageServices;
+use app\services\user\UserMoneyServices;
+use app\services\user\UserServices;
+
+/**
+ * 用户财务类
+ * Class UserFinance
+ * @package app\controller\api\user
+ */
+class UserFinance extends ApiBaseController
+{
+    protected $brokerageServices;
+    protected $moneyServices;
+    protected $billServices;
+
+    public function __construct(Request $request, UserServices $userService, UserBrokerageServices $brokerageServices, UserMoneyServices $moneyServices, UserBillServices $billServices)
+    {
+        $this->service = $userService;
+        $this->brokerageServices = $brokerageServices;
+        $this->moneyServices = $moneyServices;
+        $this->billServices = $billServices;
+        parent::__construct($request);
+    }
+
+    public function getMoneyInfo()
+    {
+        $balance = $this->service->getOneValue(['uid' => $this->request->uid()],  'now_money');
+        $pm = $this->request->param('pm', '');
+        $start_time = $this->request->param('start_time', '');
+        $end_time = $this->request->param('end_time', '');
+        $data = $this->moneyServices->getMoneyList(['uid' => $this->request->uid(), 'pm' => $pm, 'start_time' => $start_time, 'end_time' => $end_time], '*');
+        $all_income = $this->moneyServices->getUserMoneySum($this->request->uid(), '', 1);
+        $all_expend = $this->moneyServices->getUserMoneySum($this->request->uid(), '', 0);
+        $types = $this->moneyServices->bill_type();
+        return $this->success(compact('types', 'data', 'all_income', 'all_expend', 'balance'));
+    }
+
+    public function tradeMoney()
+    {
+        $num = $this->request->post('num', 0);
+        $to_uid = $this->request->post('to_uid', 0);
+        $res = $this->moneyServices->trade($this->request->uid(), $to_uid, $num);
+        if ($res)
+            return $this->success($res);
+        return $this->error('操作失败');
+    }
+
+
+    public function getBrokerageInfo()
+    {
+        $balance = $this->service->getOneValue(['uid' => $this->request->uid()], 'brokerage_price');
+        $frozen = $this->brokerageServices->getUserFrozenPrice($this->request->uid());
+        $extractable = bcsub($balance, $frozen, 2);
+        if ($extractable < 0) $extractable = 0;
+        $pm = $this->request->param('pm', '');
+        $start_time = $this->request->param('start_time', '');
+        $end_time = $this->request->param('end_time', '');
+        $data = $this->brokerageServices->getBrokerageList(['uid' => $this->request->uid(), 'pm' => $pm, 'start_time' => $start_time, 'end_time' => $end_time], '*');
+        $all_income = $this->brokerageServices->getUserBillBrokerageSum($this->request->uid(), '', 1);
+        $all_expend = $this->brokerageServices->getUserBillBrokerageSum($this->request->uid(), '', 0);
+        $types = $this->brokerageServices->bill_type();
+        return $this->success(compact('types', 'data', 'all_income', 'all_expend', 'balance', 'extractable', 'frozen'));
+    }
+
+    public function tradeBrokerage()
+    {
+        $num = $this->request->post('num', 0);
+        $to_uid = $this->request->post('to_uid', 0);
+        $res = $this->brokerageServices->trade($this->request->uid(), $to_uid, $num);
+        if ($res)
+            return $this->success($res);
+        return $this->error('操作失败');
+    }
+
+    public function getBillInfo($category)
+    {
+        $pm = $this->request->param('pm', '');
+        $start_time = $this->request->param('start_time', '');
+        $end_time = $this->request->param('end_time', '');
+        $data = $this->billServices->getUserBillList($category, ['uid' => $this->request->uid(), 'pm' => $pm, 'start_time' => $start_time, 'end_time' => $end_time], '*');
+        $all_income = $this->billServices->getUserBillSum($this->request->uid(), $category, '', 1);
+        $all_expend = $this->billServices->getUserBillSum($this->request->uid(), $category, '', 0);
+        $types = $this->billServices->getBillType();
+        return $this->success(compact('data', 'all_income', 'all_expend', 'types'));
+    }
+
+    public function tradeOther()
+    {
+        $num = $this->request->post('num', 0);
+        $category = $this->request->post('category', '');
+        $to_uid = $this->request->post('to_uid', 0);
+        $res = $this->billServices->trade($this->request->uid(), $to_uid, $category, $num);
+        if ($res)
+            return $this->success($res);
+        return $this->error('操作失败');
+    }
+}

+ 28 - 28
app/controller/api/wechat/Routine.php

@@ -42,9 +42,9 @@ class Routine
      */
     public function authType($code, $spread_code = '', $spread_spid = '')
     {
-        if (!$code) return app('json')->fail('参数有误');
+        if (!$code) return $this->error('参数有误');
         $data = $this->services->authType($code, $spread_spid, $spread_code);
-        return app('json')->success($data);
+        return $this->success($data);
     }
 
     /**
@@ -54,9 +54,9 @@ class Routine
      */
     public function authLogin($key)
     {
-        if (!$key) return app('json')->fail('参数有误');
+        if (!$key) return $this->error('参数有误');
         $data = $this->services->authLogin($key);
-        return app('json')->success($data);
+        return $this->success($data);
     }
 
     /**
@@ -74,14 +74,14 @@ class Routine
         //验证验证码
         $verifyCode = CacheService::get('code_' . $phone);
         if (!$verifyCode)
-            return app('json')->fail('请先获取验证码');
+            return $this->error('请先获取验证码');
         $verifyCode = substr($verifyCode, 0, 6);
         if ($verifyCode != $captcha) {
-            return app('json')->fail('验证码错误');
+            return $this->error('验证码错误');
         }
         CacheService::delete('code_' . $phone);
         $data = $this->services->phoneLogin($key, $phone, $spread_spid, $spread_code, $code);
-        return app('json')->success($data);
+        return $this->success($data);
     }
 
     /**
@@ -93,9 +93,9 @@ class Routine
      */
     public function bindingPhone($code = '', $iv = '', $encryptedData = '')
     {
-        if (!$code || !$iv || !$encryptedData) return app('json')->fail('参数有误');
+        if (!$code || !$iv || !$encryptedData) return $this->error('参数有误');
         $this->services->bindingPhone($code, $iv, $encryptedData);
-        return app('json')->success(410016);
+        return $this->success(410016);
     }
 
 
@@ -120,12 +120,12 @@ class Routine
         $token = $this->services->newAuth($code, $spread_spid, $spread_code, $iv, $encryptedData);
         if ($token) {
             if (isset($token['key']) && $token['key']) {
-                return app('json')->successful('授权成功,请绑定手机号', $token);
+                return $this->successful('授权成功,请绑定手机号', $token);
             } else {
-                return app('json')->successful('登录成功!', ['token' => $token['token'], 'userInfo' => $token['userInfo'], 'expires_time' => $token['params']['exp'], 'store_user_avatar' => $token['store_user_avatar'] ?? 0]);
+                return $this->successful('登录成功!', ['token' => $token['token'], 'userInfo' => $token['userInfo'], 'expires_time' => $token['params']['exp'], 'store_user_avatar' => $token['store_user_avatar'] ?? 0]);
             }
         } else
-            return app('json')->fail('获取用户访问token失败!');
+            return $this->error('获取用户访问token失败!');
     }
 
     /**
@@ -138,11 +138,11 @@ class Routine
     {
         $token = $this->services->silenceAuth($code, (int)$spread_code, (int)$spread_spid);
         if ($token && isset($token['key'])) {
-            return app('json')->success('授权成功,请绑定手机号', $token);
+            return $this->success('授权成功,请绑定手机号', $token);
         } else if ($token) {
-            return app('json')->success('登录成功', ['token' => $token['token'], 'expires_time' => $token['params']['exp'], 'store_user_avatar' => $token['store_user_avatar'] ?? 0]);
+            return $this->success('登录成功', ['token' => $token['token'], 'expires_time' => $token['params']['exp'], 'store_user_avatar' => $token['store_user_avatar'] ?? 0]);
         } else
-            return app('json')->fail('登录失败');
+            return $this->error('登录失败');
     }
 
     /**
@@ -155,11 +155,11 @@ class Routine
     {
         $token = $this->services->silenceAuth($code, (int)$spread_code, (int)$spread_spid, true);
         if ($token && isset($token['auth_login'])) {
-            return app('json')->success('授权成功');
+            return $this->success('授权成功');
         } else if ($token) {
-            return app('json')->success('登录成功', ['token' => $token['token'], 'userInfo' => $token['userInfo'], 'expires_time' => $token['params']['exp'], 'store_user_avatar' => $token['store_user_avatar'] ?? 0]);
+            return $this->success('登录成功', ['token' => $token['token'], 'userInfo' => $token['userInfo'], 'expires_time' => $token['params']['exp'], 'store_user_avatar' => $token['store_user_avatar'] ?? 0]);
         } else
-            return app('json')->fail('登录失败');
+            return $this->error('登录失败');
     }
 
     /**
@@ -173,18 +173,18 @@ class Routine
         //验证验证码
         $verifyCode = CacheService::get('code_' . $phone);
         if (!$verifyCode)
-            return app('json')->fail('请先获取验证码');
+            return $this->error('请先获取验证码');
         $verifyCode = substr($verifyCode, 0, 6);
         if ($verifyCode != $captcha) {
             CacheService::delete('code_' . $phone);
-            return app('json')->fail('验证码错误');
+            return $this->error('验证码错误');
         }
         $token = $this->services->silenceAuthBindingPhone($code, $spread_code, $spread_spid, $phone);
         if ($token) {
             CacheService::delete('code_' . $phone);
-            return app('json')->success('登录成功', ['token' => $token['token'], 'expires_time' => $token['params']['exp'], 'store_user_avatar' => $token['store_user_avatar'] ?? 0]);
+            return $this->success('登录成功', ['token' => $token['token'], 'expires_time' => $token['params']['exp'], 'store_user_avatar' => $token['store_user_avatar'] ?? 0]);
         } else
-            return app('json')->fail('登录失败');
+            return $this->error('登录失败');
     }
 
     /**
@@ -197,12 +197,12 @@ class Routine
     public function authBindingPhone($code = '', $iv = '', $encryptedData = '', $spread_code = '', $spread_spid = '', $key = '')
     {
         if (!$code || !$iv || !$encryptedData)
-            return app('json')->fail('参数有误');
+            return $this->error('参数有误');
         $token = $this->services->authBindingPhone($code, $iv, $encryptedData, $spread_code, $spread_spid, $key);
         if ($token) {
-            return app('json')->success('登录成功', $token);
+            return $this->success('登录成功', $token);
         } else
-            return app('json')->fail('登录失败');
+            return $this->error('登录失败');
     }
 
     /**
@@ -213,13 +213,13 @@ class Routine
     public function updateInfo(Request $request, $userInfo)
     {
         if (!$userInfo) {
-            return app('json')->fail('参数有误');
+            return $this->error('参数有误');
         }
         $uid = (int)$request->uid();
         $re = $this->services->updateUserInfo($uid, $userInfo);
         if ($re) {
-            return app('json')->success('更新成功');
+            return $this->success('更新成功');
         } else
-            return app('json')->fail('更新失败');
+            return $this->error('更新失败');
     }
 }

+ 14 - 14
app/controller/api/wechat/Wechat.php

@@ -72,7 +72,7 @@ class Wechat extends ApiBaseController
     public function config(Request $request)
     {
         $url = $request->get('url', '') ?: sys_config('site_url');
-        return app('json')->success($this->service->config($url));
+        return $this->success($this->service->config($url));
     }
 
     /**
@@ -92,11 +92,11 @@ class Wechat extends ApiBaseController
         ], true);
         $token = $this->service->auth($spread_spid, $login_type);
         if ($token && isset($token['key'])) {
-            return app('json')->success('授权成功,请绑定手机号', $token);
+            return $this->success('授权成功,请绑定手机号', $token);
         } else if ($token) {
-            return app('json')->success('登录成功', ['token' => $token['token'], 'userInfo' => $token['userInfo'], 'expires_time' => $token['params']['exp']]);
+            return $this->success('登录成功', ['token' => $token['token'], 'userInfo' => $token['userInfo'], 'expires_time' => $token['params']['exp']]);
         } else
-            return app('json')->fail('登录失败');
+            return $this->error('登录失败');
     }
 
 
@@ -112,11 +112,11 @@ class Wechat extends ApiBaseController
     {
         $token = $this->service->silenceAuth($spread_spid);
         if ($token && isset($token['key'])) {
-            return app('json')->success('授权成功,请绑定手机号', $token);
+            return $this->success('授权成功,请绑定手机号', $token);
         } else if ($token) {
-            return app('json')->success('登录成功', ['token' => $token['token'], 'expires_time' => $token['params']['exp']]);
+            return $this->success('登录成功', ['token' => $token['token'], 'expires_time' => $token['params']['exp']]);
         } else
-            return app('json')->fail('登录失败');
+            return $this->error('登录失败');
     }
 
     /**
@@ -131,11 +131,11 @@ class Wechat extends ApiBaseController
     {
         $token = $this->service->silenceAuth($spread_spid, true, $snsapi);
         if ($token && isset($token['auth_login'])) {
-            return app('json')->success('授权成功', $token);
+            return $this->success('授权成功', $token);
         } else if ($token) {
-            return app('json')->success('登录成功', ['token' => $token['token'], 'userInfo' => $token['userInfo'], 'expires_time' => $token['params']['exp']]);
+            return $this->success('登录成功', ['token' => $token['token'], 'userInfo' => $token['userInfo'], 'expires_time' => $token['params']['exp']]);
         } else
-            return app('json')->fail('登录失败');
+            return $this->error('登录失败');
     }
 
 
@@ -155,9 +155,9 @@ class Wechat extends ApiBaseController
         check_sms_captcha($phone, 'wechat_auth', $captcha);
         $token = $this->service->authBindingPhone($key, $phone);
         if ($token) {
-            return app('json')->success('登录成功', $token);
+            return $this->success('登录成功', $token);
         } else
-            return app('json')->fail('登录失败');
+            return $this->error('登录失败');
     }
 
     /**
@@ -168,9 +168,9 @@ class Wechat extends ApiBaseController
     {
         $data = $this->service->follow();
         if ($data) {
-            return app('json')->success('ok', $data);
+            return $this->success('ok', $data);
         } else {
-            return app('json')->fail('获取失败');
+            return $this->error('获取失败');
         }
 
     }

+ 177 - 0
app/controller/chat/Chat.php

@@ -0,0 +1,177 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @author: Kirin
+ * @day: 2024/11/12
+ * @time: 16:31
+ */
+
+namespace app\controller\api\chat;
+
+
+use app\common\ApiBaseController;
+use app\Request;
+use app\services\chat\ChatGroupMemberServices;
+use app\services\chat\ChatGroupServices;
+use app\services\chat\ChatLogServices;
+use app\services\decoration\DecorationDesignerServices;
+use app\services\decoration\DecorationSalespersonServices;
+use app\services\decoration\DecorationWorkerServices;
+use app\services\system\store\SystemStoreServices;
+use app\services\user\UserServices;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\DbException;
+use think\db\exception\ModelNotFoundException;
+
+class Chat extends ApiBaseController
+{
+    private $groupMemberService;
+    private $groupService;
+
+    public function __construct(Request $request, ChatLogServices $service, ChatGroupMemberServices $groupMemberService, ChatGroupServices $groupService)
+    {
+        parent::__construct($request);
+        $this->service = $service;
+        $this->groupMemberService = $groupMemberService;
+        $this->groupService = $groupService;
+    }
+
+
+    /**
+     * 聊天列表
+     * @param Request $request
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function index(Request $request)
+    {
+        $user_chat = $this->service->search()
+            ->where('uid|to_uid', $request->uid())
+//            ->where('add_time', '>=', time() - 7 * 86400)
+            ->where('group_id', 0)
+            ->field('if(uid=' . $request->uid() . ',to_uid,uid) as user_id,sum(if(status=0 && to_uid=' . $request->uid() . ',1,0)) as unread_count,max(add_time) as last_time,to_uid_type,uid_type')
+            ->group('user_id,to_uid_type,uid_type')
+            ->select();
+        foreach ($user_chat as &$v) {
+            $v['is_group'] = 0;
+            $v['f_info'] = $this->service->getInfo($v['to_uid_type'], $v['user_id']);
+            $user_uid = $request->uid();
+            $to_uid = $v['user_id'];
+            $v['last_msn'] = $this->service->search()->where(function ($query) use ($user_uid, $to_uid) {
+                $query->where(function ($q) use ($user_uid, $to_uid) {
+                    $q->where('uid', $user_uid)->where('to_uid', $to_uid);
+                })->whereOr(function ($q) use ($user_uid, $to_uid) {
+                    $q->where('uid', $to_uid)->where('to_uid', $user_uid);
+                });
+            })->order('add_time desc,id desc')->find();
+        }
+
+        $groups = $this->groupMemberService->search()->where('uid', $request->uid())->column('chat_group_id');
+        $groups = $this->groupService->search()->where('id', 'in', $groups)->column('id');
+        $group_chat = $this->service->search()->where('group_id', 'in', $groups)
+//            ->where('add_time', '>=', time() - 7 * 86400)
+            ->where('group_id', '>', 0)
+            ->field('group_id,sum(if(find_in_set(' . $request->uid() . ',group_see),0,1)) as unread_count,max(add_time) as last_time')
+            ->group('group_id')->select();
+        foreach ($group_chat as &$v) {
+            $v['is_group'] = 1;
+            $v['last_msn'] = $this->service->search()->where('group_id', $v['group_id'])
+                ->order('add_time desc,id desc')->find();
+            $v['at'] = $this->service->search()->where('group_id', $v['group_id'])
+                ->where('at', $request->uid())
+                ->where('find_in_set(' . $request->uid() . ',group_see)', '<=', 0)
+                ->where('find_in_set(' . $request->uid() . ',at)')
+                ->count();
+            $v['group_info'] = $this->groupService->get($v['group_id']);
+            $v['identity'] = $this->groupMemberService->search()->where('uid', $request->uid())->where('chat_group_id', $v['group_id'])->value('identity');
+        }
+        $log_list = array_merge($user_chat->toArray(), $group_chat->toArray());
+        usort($log_list, function ($a, $b) {
+            return -($a['last_time'] <=> $b['last_time']);
+        });
+        return $this->success('ok', $log_list);
+    }
+
+    /**
+     * 聊天记录
+     * @param $uid
+     * @param $type
+     * @param Request $request
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function chatLog(Request $request)
+    {
+        $page = $request->get('page', 1);
+        $limit = $request->get('limit', 30);
+        $user_uid = $request->uid();
+        list($uid, $user_type, $type) = $this->request->getMore([
+            ['uid', 0],
+            ['user_type', 0],
+            ['type', 0]
+        ], true);
+        $to_uid = $uid;
+        $log_list = $this->service->search()->where(function ($query) use ($user_uid, $to_uid, $type, $user_type) {
+            $query->where(function ($q) use ($user_uid, $to_uid, $type, $user_type) {
+                $q->where('uid', $user_uid)->where('to_uid', $to_uid)->where('to_uid_type', $type)->where('uid_type', $user_type);
+            })->whereOr(function ($q) use ($user_uid, $to_uid, $type, $user_type) {
+                $q->where('uid', $to_uid)->where('to_uid', $user_uid)->where('uid_type', $type)->where('to_uid_type', $user_type);
+            });
+        })->page($page, $limit)->order('add_time desc,id desc')->select();
+        $f_info = $this->service->getInfo($type, $to_uid);
+        $u_info = $this->service->getInfo($user_type, $user_uid);
+        return $this->success('ok', compact('log_list', 'f_info', 'u_info'));
+    }
+
+
+    public function setRead(Request $request)
+    {
+        list($uid, $user_type, $type) = $this->request->postMore([
+            ['uid', 0],
+            ['user_type', 0],
+            ['type', 0]
+        ], true);
+        $this->service->search()->where('uid', $uid)->where('to_uid', $request->uid())->where('uid_type', $user_type)->where('to_uid_type', $type)->update(['status' => 1]);
+        return $this->success('ok');
+    }
+
+
+    public function groupChatLog($group_id, Request $request)
+    {
+        if (!$user = $this->groupMemberService->search()->where('uid', $request->uid())->where('chat_group_id', $group_id)->find()) {
+            return $this->error('你没有权限');
+        }
+        $group = $this->groupService->search()->where('id', $group_id)->find();
+        if (!$group) return $this->error('群不存在');
+        $page = $request->get('page', 1);
+        $limit = $request->get('limit', 30);
+        $log_list = $this->service->search()->where('group_id', $group_id)
+            ->page($page, $limit)
+            ->where('add_time', '>=', $user['add_time'])
+            ->order('add_time desc,id desc')
+            ->select();
+        foreach ($log_list as &$v) {
+            $member = $this->groupMemberService->search()->where('chat_group_id', $group_id)->where('uid', $v['uid'])->find();
+            $v['f_info'] = $this->service->getInfo($member['identity'], $member['uid']);
+            $v['member_info'] = $member;
+        }
+        return $this->success('ok', compact('log_list'));
+    }
+
+    public function setGroupRead($group_id, Request $request)
+    {
+        if (!$user = $this->groupMemberService->search()->where('uid', $request->uid())->where('chat_group_id', $group_id)->find()) {
+            return $this->error('你没有权限');
+        }
+        $group = $this->groupService->search()->where('id', $group_id)->find();
+        if (!$group) return $this->error('群不存在');
+        $this->service->search()->where('group_id', $group_id)
+            ->where('!find_in_set(' . $request->uid() . ',group_see)')
+            ->update(['group_see' => ['exp', 'CONCAT(group_see,",' . $request->uid() . '")']]);
+        return $this->success();
+    }
+}

+ 282 - 0
app/controller/chat/ChatGroup.php

@@ -0,0 +1,282 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @author: Kirin
+ * @day: 2024/11/12
+ * @time: 16:35
+ */
+
+namespace app\controller\api\chat;
+
+
+use app\common\ApiBaseController;
+use app\Request;
+use app\services\chat\ChatGroupMemberServices;
+use app\services\chat\ChatGroupServices;
+use app\services\chat\ChatLogServices;
+use app\services\user\UserServices;
+use app\webscoket\SocketPush;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\DbException;
+use think\db\exception\ModelNotFoundException;
+use think\Exception;
+
+/**
+ * Class ChatGroup
+ * @package app\controller\api\chat
+ */
+class ChatGroup extends ApiBaseController
+{
+    /** @var ChatGroupServices $groupService */
+    private $groupService;
+    /** @var ChatGroupMemberServices $groupMemberService */
+    private $groupMemberService;
+
+    /**
+     * @param Request $request
+     * @param ChatLogServices $service
+     * @param ChatGroupMemberServices $groupMemberService
+     * @param ChatGroupServices $groupService
+     */
+    public function __construct(Request $request, ChatLogServices $service, ChatGroupMemberServices $groupMemberService, ChatGroupServices $groupService)
+    {
+        parent::__construct($request);
+        $this->service = $service;
+        $this->groupMemberService = $groupMemberService;
+        $this->groupService = $groupService;
+    }
+
+    /**
+     * 我的群列表
+     * @para
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function group()
+    {
+        $groups = $this->groupMemberService->getColumn(['uid' => $this->request->uid()], 'id');
+        $list = $this->groupService->search()->where('id', 'in', $groups)
+            ->order('last_message_time', 'desc')
+            ->select();
+        return $this->success('ok', compact('list'));
+    }
+
+
+    /**
+     * 群详情
+     * @param $id
+     * @para
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function groupInfo($id)
+    {
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        return $this->success('ok', compact('group'));
+    }
+
+    /**
+     * 群成员列表
+     * @param $id
+     * @para
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function groupMembers($id)
+    {
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        $list = $this->groupMemberService->search()->where('chat_group_id', $id)->select();
+        foreach ($list as &$v) {
+            $v['ext_info'] = $this->service->getInfo($v['identity'], $v['uid']);
+        }
+        return $this->success('ok', compact('list'));
+    }
+
+    /**
+     * 添加群成员
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     * @para
+     */
+    public function groupAddMember($id)
+    {
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        if (!$this->groupMemberService->search()->where('uid', $this->request->uid())->where('chat_group_id', $id)->where('is_hoster', 1)->find()) {
+            return $this->error('你没有权限');
+        }
+        $uid = $this->request->post('uid', 0);
+        $identity = $this->request->post('identity', 0);
+        if ($this->groupMemberService->search()->where('uid', $uid)->where('chat_group_id', $id)->find()) {
+            return $this->error('用户已在群聊中');
+        }
+        /** @var UserServices $userService */
+        $userService = app()->make(UserServices::class);
+        $user = $userService->getUserInfo($uid);
+        if (!$user) return $this->error('用户不存在');
+        $ext_info = $this->service->getInfo($identity, $uid);
+        if (!$ext_info) return $this->error('用户不存在');
+        try {
+            $this->groupMemberService->create([
+                'uid' => $uid,
+                'chat_group_id' => $id,
+                'identity' => $identity,
+            ]);
+            $this->service->create([
+                'uid' => $uid,
+                'to_uid' => 0,
+                'add_time' => time(),
+                'status' => 1,
+                'msn_type' => 'notice',
+                'group_id' => $id,
+                'msn' => $ext_info['info']['name'] . ' 加入群聊',
+                'group_see' => $uid,
+            ]);
+            $this->groupService->update($id, ['last_message_time' => time()]);
+            return $this->success('ok', ['date' => ['name' => $ext_info['info']['name'], 'type' => $ext_info['type'], 'uid' => $uid, 'add_time' => time(), 'group_id' => $id], 'type' => 'group:new_member']);
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+    }
+
+
+    /**
+     * 移除群成员
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     * @para
+     */
+    public function groupRemoveMember($id)
+    {
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        if (!$this->groupMemberService->search()->where('uid', $this->request->uid())->where('chat_group_id', $id)->where('is_hoster', 1)->find()) {
+            return $this->error('你没有权限');
+        }
+        $uid = $this->request->post('uid', 0);
+        if (!$user = $this->groupMemberService->search()->where('uid', $uid)->where('chat_group_id', $id)->find()) {
+            return $this->error('用户不在群聊中');
+        }
+        if ($user['is_hoster']) return $this->error('群主不能移除');
+
+        try {
+            $this->groupMemberService->delete($user['id']);
+            return $this->success('ok');
+        } catch (Exception $e) {
+            return $this->error($e->getMessage());
+        }
+    }
+
+
+    /**
+     * 修改群昵称
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function setMark($id)
+    {
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        $mark = $this->request->post('mark');
+        $info = $this->groupMemberService->search()->where('uid', $this->request->uid())->where('chat_group_id', $id)->find();
+        if (!$info) return $this->error('你没有权限');
+        $info->nickname = $mark;
+        $res = $info->save();
+        if ($res)
+            return $this->success('修改成功');
+        else
+            return $this->error('修改失败');
+    }
+
+
+    /**
+     * 修改群信息
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     * @para
+     */
+    public function editGroup($id)
+    {
+        $info = $this->request->post('info', '');
+        $name = $this->request->post('name', '');
+        $avatar = $this->request->post('avatar', '');
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        if (!$this->groupMemberService->search()->where('uid', $this->request->uid())->where('chat_group_id', $id)->where('is_hoster', 1)->find()) {
+            return $this->error('你没有权限');
+        }
+        $res = $this->groupService->update($id, ['name' => $name, 'info' => $info, 'avatar' => $avatar]);
+        if ($res)
+            return $this->success('修改成功');
+        else
+            return $this->error('修改失败');
+    }
+
+    /**
+     * 新增群公告
+     * @param $id
+     * @return mixed
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     * @para
+     */
+    public function setNotice($id)
+    {
+        $notice = $this->request->post('notice', '');
+        $group = $this->groupService->get($id);
+        if (!$group) return $this->error('群不存在');
+        if (!$this->groupMemberService->search()->where('uid', $this->request->uid())->where('chat_group_id', $id)->where('is_hoster', 1)->find()) {
+            return $this->error('你没有权限');
+        }
+        $res = $this->groupService->update($id, ['notice' => $notice]);
+        $this->service->create([
+            'uid' => $this->request->uid(),
+            'to_uid' => 0,
+            'add_time' => time(),
+            'status' => 1,
+            'msn_type' => 'announcement',
+            'group_id' => $id,
+            'msn' => '群公告' . ':' . $notice,
+            'group_see' => $this->request->uid(),
+        ]);
+
+        /** @var ChatGroupMemberServices $chatMemberService */
+        $chatMemberService = app()->make(ChatGroupMemberServices::class);
+
+        $members = $chatMemberService->getColumn(['chat_group_id' => $id], 'uid');
+        foreach ($members as $member) {
+            SocketPush::user()->toGroup($member, $id)->type('announcement')
+                ->data('群公告' . ':' . $notice)
+                ->push();
+        }
+
+        $res = $this->groupService->update($id, ['last_message_time' => time()]);
+        if ($res)
+            return $this->success('修改成功', ['type' => 'group:notice', 'data' => ['notice' => $notice]]);
+        else
+            return $this->error('修改失败');
+    }
+
+
+}

+ 2 - 1
app/event.php

@@ -22,13 +22,14 @@ return [
         'swoole.workerError' => [],
         'swoole.workerStop' => [],
 //        'swoole.shutDown' => [\qiniu\listeners\SwooleShutdownListen::class],//swoole 停止事件
-//        'swoole.websocket.user' => [\app\webscoket\handler\UserHandler::class],//socket 用户调用事件
+        'swoole.websocket.user' => [\app\webscoket\handler\UserHandler::class],//socket 用户调用事件
 //        'swoole.websocket.kefu' => [\app\webscoket\handler\KefuHandler::class],//socket 客服事件
 //        'swoole.websocket.admin' => [\app\webscoket\handler\AdminHandler::class],//socket 后台事件
         'config.create' => [\app\listener\system\config\CreateSuccess::class],//创建配置事件
         'config.delete' => [\app\listener\system\config\DeleteSuccess::class],//删除配置事件
         'config.update' => [\app\listener\system\config\StatusSuccess::class],//删除配置事件
         'user.cancelUser' => [\app\listener\user\CancelUser::class],
+        'decoration.cases_audit' => [\app\listener\decoration\CasesAudit::class],
 
     ],
 

+ 1 - 1
app/http/middleware/api/LocationMiddleware.php

@@ -31,7 +31,7 @@ class LocationMiddleware implements MiddlewareInterface
      */
     public function handle(Request $request, Closure $next)
     {
-        $location = $request->header('QN-Location', '');
+        $location = $request->header('Qn-Location', '');
         if ($location) {
             $location = explode(',', $location);
         }

+ 2 - 2
app/listener/wechat/RoutineListener.php

@@ -44,7 +44,7 @@ class RoutineListener implements EventHandlerInterface
                             $prefix = substr($payload['order_info']['trade_no'],0,2);
                             //处理一下参数
                             switch ($prefix) {
-								case 'wx':
+                                case 'wx':
                                 case 'cp':
                                     $data['attach'] = 'Product';
                                     break;
@@ -65,7 +65,7 @@ class RoutineListener implements EventHandlerInterface
                             }
                             Log::error(['data'=>$data,'res'=>$response,'message'=>$payload]);
                             break;
-						case 'trade_manage_remind_access_api':  // 小程序完成账期授权时  小程序产生第一笔交易时 已产生交易但从未发货的小程序,每天一次
+                        case 'trade_manage_remind_access_api':  // 小程序完成账期授权时  小程序产生第一笔交易时 已产生交易但从未发货的小程序,每天一次
                             break;
                         case 'trade_manage_remind_shipping':   // 曾经发过货的小程序,订单超过48小时未发货时
                             break;

+ 143 - 0
app/model/chat/ChatGroup.php

@@ -0,0 +1,143 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types = 1);
+
+namespace app\model\chat;
+
+use qiniu\basic\BaseModel;
+use qiniu\traits\ModelTrait;
+use think\model\concern\SoftDelete;
+
+/**
+ * 聊天群模型
+ * Class ChatGroup
+ * @package app\model\chat
+ */
+class ChatGroup extends BaseModel
+{
+
+    use ModelTrait;
+    use SoftDelete;
+
+
+    // 表名
+    protected $name = 'chat_group';
+
+    // 表中文名
+    protected $chsName = '聊天群';
+
+    //主键
+    protected $pk = 'id';
+
+    
+
+    //隐藏属性
+    protected $hidden = [
+        'delete_time'
+    ];
+
+    // 追加属性
+    protected $append = [
+        'last_message_time_chs'
+    ];
+
+
+
+
+    protected function setAddTimeAttr($value)
+    {
+        return $value ?: time();
+    }
+
+    /**
+     * 添加时间获取器
+     * @param $value
+     * @return false|string
+     */
+    public function getAddTimeAttr($value)
+    {
+        if (!empty($value)) {
+            if (is_string($value)) {
+                return $value;
+            } elseif (is_int($value)) {
+                return date('Y-m-d H:i:s', (int)$value);
+            }
+        }
+        return '--';
+    }
+
+
+    public function getLastMessageTimeChsAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['last_message_time']) ? $data['last_message_time'] : '--');
+        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
+    }
+
+    protected function setLastMessageTimeAttr($value)
+    {
+        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
+    }
+
+
+    /**
+     * 群名称 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchNameAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('name', 'like', "%{$value}%");
+        }
+    }
+
+
+    /**
+     * 群介绍 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchInfoAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('info', 'like', "%{$value}%");
+        }
+    }
+
+
+    /**
+     * 关联主订单 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchMainOrderIdAttr($query, $value)
+    {
+        if (is_array($value))
+            $query->whereIn('main_order_id', $value);
+        else {
+            if ($value !== '') {
+                $query->where('main_order_id', $value);
+            }
+        }
+    }
+
+
+    /**
+     * 最新消息时间 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchLastMessageTimeAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->whereTime('last_message_time', $value);
+        }
+    }
+
+}

+ 176 - 0
app/model/chat/ChatGroupMember.php

@@ -0,0 +1,176 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types = 1);
+
+namespace app\model\chat;
+
+use qiniu\basic\BaseModel;
+use qiniu\traits\ModelTrait;
+
+
+/**
+ * 群成员模型
+ * Class ChatGroupMember
+ * @package app\model\chat
+ */
+class ChatGroupMember extends BaseModel
+{
+
+    use ModelTrait;
+    
+
+
+    // 表名
+    protected $name = 'chat_group_member';
+
+    // 表中文名
+    protected $chsName = '群成员';
+
+    //主键
+    protected $pk = 'id';
+
+    
+
+    //隐藏属性
+    protected $hidden = [
+    
+    ];
+
+    // 追加属性
+    protected $append = [
+        'is_manager_chs',
+	    'is_hoster_chs',
+	    'identity_chs'
+    ];
+
+    public function getIsManagerList()
+    {
+        return ['0' => '否', '1' => '是'];
+    }
+
+    public function getIsHosterList()
+    {
+        return ['0' => '否', '1' => '是'];
+    }
+
+
+
+    protected function setAddTimeAttr($value)
+    {
+        return $value ?: time();
+    }
+
+    /**
+     * 添加时间获取器
+     * @param $value
+     * @return false|string
+     */
+    public function getAddTimeAttr($value)
+    {
+        if (!empty($value)) {
+            if (is_string($value)) {
+                return $value;
+            } elseif (is_int($value)) {
+                return date('Y-m-d H:i:s', (int)$value);
+            }
+        }
+        return '--';
+    }
+
+
+    public function getIsManagerChsAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['is_manager']) ? $data['is_manager'] : '');
+        $list = $this->getIsManagerList();
+        return isset($list[$value]) ? $list[$value] : '';
+    }
+
+
+    public function getIsHosterChsAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['is_hoster']) ? $data['is_hoster'] : '');
+        $list = $this->getIsHosterList();
+        return isset($list[$value]) ? $list[$value] : '';
+    }
+
+
+
+    /**
+     * 聊天群 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchChatGroupIdAttr($query, $value)
+    {
+        if (is_array($value))
+            $query->whereIn('chat_group_id', $value);
+        else{
+            if ($value !== '') {
+                $query->where('chat_group_id', $value);
+            }
+        }
+    }
+
+
+    /**
+     * 用户ID 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchUidAttr($query, $value)
+    {
+        if (is_array($value))
+            $query->whereIn('uid', $value);
+        else{
+            if ($value !== '') {
+                $query->where('uid', $value);
+            }
+        }
+    }
+
+
+    /**
+     * 昵称 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchNicknameAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('nickname', 'like', "%{$value}%");
+        }
+    }
+
+
+    /**
+     * 是否管理员 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchIsManagerAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('is_manager', $value);
+        }
+    }
+
+
+    /**
+     * 是否群主 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchIsHosterAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('is_hoster', $value);
+        }
+    }
+
+}

+ 133 - 0
app/model/chat/ChatLog.php

@@ -0,0 +1,133 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types=1);
+
+namespace app\model\chat;
+
+use qiniu\basic\BaseModel;
+use qiniu\traits\ModelTrait;
+use think\model\concern\SoftDelete;
+
+/**
+ * 聊天记录模型
+ * Class ChatLog
+ * @package app\model\chat
+ */
+class ChatLog extends BaseModel
+{
+
+    use ModelTrait;
+    use SoftDelete;
+
+
+    // 表名
+    protected $name = 'chat_log';
+
+    // 表中文名
+    protected $chsName = '聊天记录';
+
+    //主键
+    protected $pk = 'id';
+
+
+    //隐藏属性
+    protected $hidden = [
+        'delete_time'
+    ];
+
+    // 追加属性
+    protected $append = [
+        'status_chs'
+    ];
+
+    public function getStatusList()
+    {
+        return ['0' => '否', '1' => '是'];
+    }
+
+
+    protected function setAddTimeAttr($value)
+    {
+        return $value ?: time();
+    }
+
+
+
+    public function getStatusChsAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
+        $list = $this->getStatusList();
+        return isset($list[$value]) ? $list[$value] : '';
+    }
+
+
+    /**
+     * 发送人uid 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchUidAttr($query, $value)
+    {
+        if (is_array($value))
+            $query->whereIn('uid', $value);
+        else {
+            if ($value !== '') {
+                $query->where('uid', $value);
+            }
+        }
+    }
+
+
+    /**
+     * 接收人uid 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchToUidAttr($query, $value)
+    {
+        if (is_array($value))
+            $query->whereIn('to_uid', $value);
+        else {
+            if ($value !== '') {
+                $query->where('to_uid', $value);
+            }
+        }
+    }
+
+
+    /**
+     * 是否已读 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchStatusAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('status', $value);
+        }
+    }
+
+
+    /**
+     * 群ID 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchGroupIdAttr($query, $value)
+    {
+        if (is_array($value))
+            $query->whereIn('group_id', $value);
+        else {
+            if ($value !== '') {
+                $query->where('group_id', $value);
+            }
+        }
+    }
+
+}

+ 1 - 8
app/model/system/CityArea.php

@@ -60,20 +60,13 @@ class CityArea extends BaseModel
                 array_shift($address);
             }
             $p = array_shift($address);
-            if (mb_strlen($p) - 1 === mb_strpos($p, '市')) {
-                $p = mb_substr($p, 0, -1);
-            } elseif (mb_strlen($p) - 1 === mb_strpos($p, '省')) {
-                $p = mb_substr($p, 0, -1);
-            } elseif (mb_strlen($p) - 3 === mb_strpos($p, '自治区')) {
-                $p = mb_substr($p, 0, -3);
-            }
             $pcity = $this->getModel()->where('name', $p)->value('id');
             $path = ['', $pcity];
             $street = $p;
             $i = 0;
             foreach ($address as $item) {
                 //县级市,只有三级地址;市和县相同
-                if ($item == ($address[$i-1] ?? '')) continue;
+                if ($item == ($address[$i - 1] ?? '')) continue;
                 $pcity = $this->getModel()->whereLike('path', implode('/', $path) . '/%')->where('name', $item)->value('id');
                 if (!$pcity) {
                     break;

+ 3 - 3
app/model/system/Qrcode.php

@@ -16,7 +16,7 @@ class Qrcode extends BaseModel
 {
 
     use ModelTrait;
-    
+
 
 
     // 表名
@@ -27,13 +27,13 @@ class Qrcode extends BaseModel
 
     //隐藏属性
     protected $hidden = [
-    
+
     ];
 
     // 追加属性
     protected $append = [
         'status_chs',
-	    'type_chs'
+        'type_chs'
     ];
 
     public function getStatusList()

+ 0 - 1
app/model/system/SystemLog.php

@@ -46,7 +46,6 @@ class SystemLog extends BaseModel
         return time();
     }
 
-
     protected function getParamsAttr($value)
     {
         return json_decode($value, true);

+ 13 - 0
app/model/system/admin/SystemAdmin.php

@@ -119,6 +119,7 @@ class SystemAdmin extends BaseModel
             $query->where("CONCAT(',',roles,',')  LIKE '%,$roles,%'");
         }
     }
+
     /**
      * 状态搜索器
      * @param Model $query
@@ -155,4 +156,16 @@ class SystemAdmin extends BaseModel
         }
     }
 
+    /**
+     * 关联ID搜索器
+     * @param Model $query
+     * @param $value
+     */
+    public function searchStoreIdAttr($query, $value)
+    {
+        if ($value !== '' && $value != null) {
+            $query->where('relation_id', $value)->where('admin_type', 2);
+        }
+    }
+
 }

+ 12 - 12
app/model/system/attachment/SystemAttachmentCategory.php

@@ -69,32 +69,32 @@ class SystemAttachmentCategory extends BaseModel
         if ($value) $query->where('type', $value);
     }
 
-	/**
+    /**
      * 关联门店ID、供应商ID搜索器
      * @param Model $query
      * @param $value
      */
     public function searchRelationIdAttr($query, $value)
     {
-		if (is_array($value)) {
-			if ($value) $query->whereIn('relation_id', $value);
-		} else {
-			if ($value !== '') $query->where('relation_id', $value);
-		}
+        if (is_array($value)) {
+            if ($value) $query->whereIn('relation_id', $value);
+        } else {
+            if ($value !== '') $query->where('relation_id', $value);
+        }
     }
 
-	/**
+    /**
      * FileType搜索器
      * @param Model $query
      * @param $value
      */
     public function searchFileTypeAttr($query, $value)
     {
-		if (is_array($value)) {
-			if ($value) $query->whereIn('file_type', $value);
-		} else {
-			if ($value !== '') $query->where('file_type', $value);
-		}
+        if (is_array($value)) {
+            if ($value) $query->whereIn('file_type', $value);
+        } else {
+            if ($value !== '') $query->where('file_type', $value);
+        }
     }
 
     /**

+ 10 - 0
app/model/system/config/SystemConfig.php

@@ -50,6 +50,16 @@ class SystemConfig extends BaseModel
         ]);
     }
 
+    public function getConfigurationAttr($value)
+    {
+        return is_string($value) ? json_decode($value, true) : $value;
+    }
+
+    public function setConfigurationAttr($value)
+    {
+        return is_array($value) ? json_encode($value) : $value;
+    }
+
     /**
      * 菜单名搜索器
      * @param Model $query

+ 9 - 9
app/model/system/config/SystemStorage.php

@@ -55,13 +55,13 @@ class SystemStorage extends BaseModel
         }
     }
 
-	/**
-	 * 状态搜索器
-	 * @param $query
-	 * @param $value
-	 */
-	public function searchStatusAttr($query, $value)
-	{
-		if ($value !== '') $query->where('status', $value);
-	}
+    /**
+     * 状态搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchStatusAttr($query, $value)
+    {
+        if ($value !== '') $query->where('status', $value);
+    }
 }

+ 3 - 2
app/model/system/config/SystemUserLevel.php

@@ -13,6 +13,7 @@ namespace app\model\system\config;
 
 use qiniu\basic\BaseModel;
 use qiniu\traits\ModelTrait;
+use think\facade\Log;
 use think\Model;
 use think\model\concern\SoftDelete;
 
@@ -40,9 +41,9 @@ class SystemUserLevel extends BaseModel
 
     protected $order = 'grade asc,id asc';
 
-    public function setAddTimeAttr()
+    protected function setAddTimeAttr($value)
     {
-        return time();
+        return $value ?: time();
     }
     /**
      * 时间获取器

+ 257 - 0
app/model/system/store/SystemStore.php

@@ -0,0 +1,257 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types=1);
+
+namespace app\model\system\store;
+
+use app\model\decoration\order\DecorationOrderReply;
+use qiniu\basic\BaseModel;
+use qiniu\traits\ModelTrait;
+use think\model\concern\SoftDelete;
+
+/**
+ * 门店模型
+ * Class SystemStore
+ * @package app\model\system\store
+ */
+class SystemStore extends BaseModel
+{
+
+    use ModelTrait;
+    use SoftDelete;
+
+
+    // 表名
+    protected $name = 'system_store';
+
+    // 表中文名
+    protected $chsName = '门店';
+
+    //主键
+    protected $pk = 'id';
+
+
+    //隐藏属性
+    protected $hidden = [
+        'delete_time'
+    ];
+
+    // 追加属性
+    protected $append = [
+        'slide_images_chs',
+        'product_status_chs',
+        'product_verify_status_chs'
+    ];
+
+    public function getProductStatusList()
+    {
+        return ['1' => '开启', '0' => '关闭'];
+    }
+
+    public function getProductVerifyStatusList()
+    {
+        return ['1' => '开启', '0' => '关闭'];
+    }
+
+
+    public function getSlideImagesChsAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['slide_images']) ? $data['slide_images'] : '');
+        return explode(',', $value);
+    }
+
+
+    protected function setAddTimeAttr($value)
+    {
+        return $value ?: time();
+    }
+
+    /**
+     * 添加时间获取器
+     * @param $value
+     * @return false|string
+     */
+    public function getAddTimeAttr($value)
+    {
+        if (!empty($value)) {
+            if (is_string($value)) {
+                return $value;
+            } elseif (is_int($value)) {
+                return date('Y-m-d H:i:s', (int)$value);
+            }
+        }
+        return '--';
+    }
+
+
+    public function getProductStatusChsAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['product_status']) ? $data['product_status'] : '');
+        $list = $this->getProductStatusList();
+        return isset($list[$value]) ? $list[$value] : '';
+    }
+
+
+    public function getProductVerifyStatusChsAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['product_verify_status']) ? $data['product_verify_status'] : '');
+        $list = $this->getProductVerifyStatusList();
+        return isset($list[$value]) ? $list[$value] : '';
+    }
+
+
+    /**
+     * id
+     * @param $value
+     */
+    public function searchIdAttr($query, $value)
+    {
+        if ($value) {
+            if (is_array($value))
+                $query->whereIn('id', $value);
+            else
+                $query->where('id', $value);
+        }
+    }
+
+    /**
+     * id
+     * @param $value
+     */
+    public function searchTypeAttr($query, $value)
+    {
+        if ($value != '') {
+            $query->where('type', $value);
+        }
+    }
+
+    protected function setSlideImagesAttr($value)
+    {
+        return is_array($value) ? implode(',', $value) : $value;
+    }
+
+
+    /**
+     * 门店名称 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchNameAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('name', 'like', "%{$value}%");
+        }
+    }
+
+
+    /**
+     * 门店名称 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchKeyWordAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('id|name|phone|introduction|manager_name', 'like', "%{$value}%");
+        }
+    }
+
+
+    /**
+     * 门店推荐图 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchSlideImagesAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where("FIND_IN_SET(" . $value . ",slide_images)");
+        }
+    }
+
+
+    /**
+     * 自主添加商品状态 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchProductStatusAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('product_status', $value);
+        }
+    }
+
+
+    /**
+     * 商品免审核 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchProductVerifyStatusAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('product_verify_status', $value);
+        }
+    }
+
+    /**
+     * 省 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchProvinceAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('province', $value);
+        }
+    }
+
+    /**
+     * 省 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchCityAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('city', $value);
+        }
+    }
+
+    /**
+     * 省 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchAreaAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('area', $value);
+        }
+    }
+
+    public function searchAddressAttr($query, $value)
+    {
+        if (!empty($value)) {
+            if (!is_array($value)) {
+                $value = explode(',', $value);
+            }
+            if (!empty($value[0])) {
+                $query->where('province', $value[0]);
+            }
+            if (!empty($value[1])) {
+                $query->whereIn('city', [$value[1], 0]);
+            }
+            if (!empty($value[2])) {
+                $query->whereIn('district', [$value[2], 0]);
+            }
+        }
+    }
+}

+ 2 - 2
app/model/user/User.php

@@ -33,7 +33,7 @@ class User extends BaseModel
     protected $name = 'user';
 
     protected $hidden = [
-        'add_ip', 'account', 'clean_time', 'last_ip', 'pwd', 'salt', 'trade_pwd', 'trade_salt', 'admin_id'
+        'add_ip', 'clean_time', 'last_ip', 'pwd', 'salt', 'trade_pwd', 'trade_salt', 'admin_id'
     ];
 
     /**
@@ -166,7 +166,7 @@ class User extends BaseModel
     {
         if (is_array($value))
             $query->whereIn('uid', $value);
-        else
+        else if ($value !== '')
             $query->where('uid', $value);
     }
 

+ 102 - 29
app/model/user/UserBank.php

@@ -1,68 +1,141 @@
 <?php
-// +----------------------------------------------------------------------
-// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
-// +----------------------------------------------------------------------
-// | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
-// +----------------------------------------------------------------------
-// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
-// +----------------------------------------------------------------------
-// | Author: CRMEB Team <admin@crmeb.com>
-// +----------------------------------------------------------------------
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types = 1);
 
 namespace app\model\user;
 
 use qiniu\basic\BaseModel;
 use qiniu\traits\ModelTrait;
-use think\model;
+use think\model\concern\SoftDelete;
 
 /**
- * Class UserAddress
+ * 收款方式模型
+ * Class UserBank
  * @package app\model\user
  */
 class UserBank extends BaseModel
 {
+
     use ModelTrait;
-    use model\concern\SoftDelete;
+    use SoftDelete;
 
-    /**
-     * 数据表主键
-     * @var string
-     */
+
+    // 表名
+    protected $name = 'user_bank';
+
+    // 表中文名
+    protected $chsName = '收款方式';
+
+    //主键
     protected $pk = 'id';
 
+
+
+    //隐藏属性
+    protected $hidden = [
+        'delete_time'
+    ];
+
+    // 追加属性
+    protected $append = [
+        'type_chs'
+    ];
+
+    public function getTypeList()
+    {
+        return ['0' => '银行卡', '1' => '支付宝', '2' => '微信'];
+    }
+
+
+    public function getTypeChsAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['type']) ? $data['type'] : '');
+        $list = $this->getTypeList();
+        return isset($list[$value]) ? $list[$value] : '';
+    }
+
+
+    protected function setAddTimeAttr($value)
+    {
+        return $value ?: time();
+    }
+
     /**
-     * 模型名称
-     * @var string
+     * 添加时间获取器
+     * @param $value
+     * @return false|string
      */
-    protected $name = 'user_bank';
+    public function getAddTimeAttr($value)
+    {
+        if (!empty($value)) {
+            if (is_string($value)) {
+                return $value;
+            } elseif (is_int($value)) {
+                return date('Y-m-d H:i:s', (int)$value);
+            }
+        }
+        return '--';
+    }
 
-    protected $hidden = ['add_time', 'delete_time'];
 
 
-    protected function setAddTimeAttr()
+
+    /**
+     * 用户ID 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchUidAttr($query, $value)
     {
-        return time();
+        if (is_array($value))
+            $query->whereIn('uid', $value);
+        else if ($value !== '')
+            $query->where('uid', $value);
     }
 
+
     /**
-     * 用户uid
+     * 提现方式 搜索器
      * @param $query
      * @param $value
      */
-    public function searchUidAttr($query, $value)
+    public function searchTypeAttr($query, $value)
     {
-        $query->where('uid', $value);
+        if ($value !== '') {
+            $query->where('type', $value);
+        }
     }
 
 
     /**
-     * 是否默认地址
-     * @param Model $query
+     * 开户行名 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchBankNameAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('bank_name', 'like', "%{$value}%");
+        }
+    }
+
+
+    /**
+     * 收款人姓名 搜索器
+     * @param $query
      * @param $value
      */
-    public function searchDefaultAttr($query, $value)
+    public function searchRealNameAttr($query, $value)
     {
-        $query->where('default', $value);
+        if ($value !== '') {
+            $query->where('real_name', 'like', "%{$value}%");
+        }
     }
 
 }

+ 179 - 0
app/model/user/UserExtract.php

@@ -0,0 +1,179 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types = 1);
+
+namespace app\model\user;
+
+use qiniu\basic\BaseModel;
+use qiniu\traits\ModelTrait;
+
+
+/**
+ * 用户提现模型
+ * Class UserExtract
+ * @package app\model\user
+ */
+class UserExtract extends BaseModel
+{
+
+    use ModelTrait;
+    
+
+
+    // 表名
+    protected $name = 'user_extract';
+
+    // 表中文名
+    protected $chsName = '用户提现';
+
+    //主键
+    protected $pk = 'id';
+
+    
+
+    //隐藏属性
+    protected $hidden = [
+    
+    ];
+
+    // 追加属性
+    protected $append = [
+        'extract_type_chs',
+	    'fail_time_chs',
+	    'status_chs'
+    ];
+
+    public function getExtractTypeList()
+    {
+        return ['0' => '银行卡', '1' => '支付宝', '2' => '微信'];
+    }
+
+    public function getStatusList()
+    {
+        return ['-1' => '未通过', '0' => '审核中', '1' => '已提现'];
+    }
+
+
+    public function getExtractTypeChsAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['extract_type']) ? $data['extract_type'] : '');
+        $list = $this->getExtractTypeList();
+        return isset($list[$value]) ? $list[$value] : '';
+    }
+
+
+    public function getFailTimeChsAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['fail_time']) ? $data['fail_time'] : '--');
+        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
+    }
+
+
+    protected function setAddTimeAttr($value)
+    {
+        return $value ?: time();
+    }
+
+    /**
+     * 添加时间获取器
+     * @param $value
+     * @return false|string
+     */
+    public function getAddTimeAttr($value)
+    {
+        if (!empty($value)) {
+            if (is_string($value)) {
+                return $value;
+            } elseif (is_int($value)) {
+                return date('Y-m-d H:i:s', (int)$value);
+            }
+        }
+        return '--';
+    }
+
+
+    public function getStatusChsAttr($value, $data)
+    {
+        $value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
+        $list = $this->getStatusList();
+        return isset($list[$value]) ? $list[$value] : '';
+    }
+
+    protected function setFailTimeAttr($value)
+    {
+        return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
+    }
+
+
+    /**
+     * 用户 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchUidAttr($query, $value)
+    {
+        if (is_array($value))
+            $query->whereIn('uid', $value);
+        else if ($value !== '')
+            $query->where('uid', $value);
+    }
+
+
+    /**
+     * 名称 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchRealNameAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('real_name', 'like', "%{$value}%");
+        }
+    }
+
+
+    /**
+     * 提现方式 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchExtractTypeAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('extract_type', $value);
+        }
+    }
+
+
+    /**
+     * 驳回时间 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchFailTimeAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->whereTime('fail_time', $value);
+        }
+    }
+
+
+    /**
+     * 状态 搜索器
+     * @param $query
+     * @param $value
+     */
+    public function searchStatusAttr($query, $value)
+    {
+        if ($value !== '') {
+            $query->where('status', $value);
+        }
+    }
+
+}

+ 44 - 0
app/services/chat/ChatGroupMemberServices.php

@@ -0,0 +1,44 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types=1);
+
+namespace app\services\chat;
+
+use qiniu\basic\BaseServices;
+use app\model\chat\ChatGroupMember;
+
+/**
+ * 群成员服务
+ * Class ChatGroupMemberServices
+ * @package app\services\chat
+ * @mixin ChatGroupMember
+ */
+class ChatGroupMemberServices extends BaseServices
+{
+
+    protected $exportHeader = [
+        'id' => 'Id',
+        'chat_group_id' => '聊天群',
+        'uid' => '用户ID',
+        'nickname' => '昵称',
+        'add_time' => '添加事件',
+        'is_manager_chs' => '是否管理员',
+        'is_hoster_chs' => '是否群主',
+    ];
+
+    /**
+     * ChatGroupMemberServices constructor.
+     * @param ChatGroupMember $model
+     */
+    public function __construct(ChatGroupMember $model)
+    {
+        $this->model = $model;
+    }
+
+}

+ 44 - 0
app/services/chat/ChatGroupServices.php

@@ -0,0 +1,44 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types=1);
+
+namespace app\services\chat;
+
+use qiniu\basic\BaseServices;
+use app\model\chat\ChatGroup;
+
+/**
+ * 聊天群服务
+ * Class ChatGroupServices
+ * @package app\services\chat
+ * @mixin ChatGroup
+ */
+class ChatGroupServices extends BaseServices
+{
+
+    protected $exportHeader = [
+        'id' => 'Id',
+        'name' => '群名称',
+        'info' => '群介绍',
+        'notice' => '群公告',
+        'main_order_id' => '关联主订单',
+        'add_time' => '创建时间',
+        'last_message_time_chs' => '最新消息时间'
+    ];
+
+    /**
+     * ChatGroupServices constructor.
+     * @param ChatGroup $model
+     */
+    public function __construct(ChatGroup $model)
+    {
+        $this->model = $model;
+    }
+
+}

+ 171 - 0
app/services/chat/ChatLogServices.php

@@ -0,0 +1,171 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types=1);
+
+namespace app\services\chat;
+
+use app\services\system\store\SystemStoreServices;
+use app\services\user\UserServices;
+use app\webscoket\SocketPush;
+use qiniu\basic\BaseServices;
+use app\model\chat\ChatLog;
+use qiniu\exceptions\ApiException;
+use think\Exception;
+
+/**
+ * 聊天记录服务
+ * Class ChatLogServices
+ * @package app\services\chat
+ * @mixin ChatLog
+ */
+class ChatLogServices extends BaseServices
+{
+
+    protected $exportHeader = [
+        'id' => 'Id',
+        'msn_type' => '消息类型',
+        'msn' => '消息内容',
+        'uid' => '发送人uid',
+        'to_uid' => '接收人uid',
+        'add_time' => '发送时间',
+        'status_chs' => '是否已读',
+        'at' => '@',
+        'group_id' => '群ID',
+        'group_see' => '群内已读记录'
+    ];
+
+    const MSN_TYPE = ['text', 'emoji', 'img', 'video', 'voice'];
+
+    private $user_type = [
+        0 => '用户',
+        1 => '设计师',
+        2 => '安装工',
+        3 => '业务员',
+    ];
+
+    public function getInfo($type, $uid)
+    {
+        switch ($type) {
+            default:
+                /** @var UserServices $service */
+                $service = app()->make(UserServices::class);
+                $info = ['type' => 'user', 'info' => $service->getUserInfo((int)$uid, 'uid,nickname as name,avatar')];
+                break;
+        }
+        return $info;
+    }
+
+    public function getUid($type, $ext_id)
+    {
+        switch ($type) {
+            default:
+                /** @var UserServices $service */
+                $id = $ext_id;
+                break;
+        }
+        return $id;
+    }
+
+    /**
+     * ChatLogServices constructor.
+     * @param ChatLog $model
+     */
+    public function __construct(ChatLog $model)
+    {
+        $this->model = $model;
+    }
+
+
+    public function createOrderGroup($store, $order)
+    {
+        /** @var ChatGroupServices $chatGroupService */
+        $chatGroupService = app()->make(ChatGroupServices::class);
+        /** @var ChatGroupMemberServices $chatMemberService */
+        $chatMemberService = app()->make(ChatGroupMemberServices::class);
+        $group = $chatGroupService->create([
+            'name' => $order['order_id'] . '群聊',
+            'main_order_id' => $order['id'],
+        ]);
+        $chatMemberService->create([
+            'uid' => $store['uid'],
+            'chat_group_id' => $group['id'],
+            'nickname' => $store['name'],
+            'is_hoster' => 1,
+            'identity' => 4,
+        ]);
+//        $chatMemberService->create([
+//            'uid' => $order['uid'],
+//            'chat_group_id' => $group['id'],
+//        ]);
+        $this->joinGroup($group['id'], $order['uid']);
+        $this->create([
+            'uid' => $order['uid'],
+            'to_uid' => 0,
+            'add_time' => time(),
+            'status' => 1,
+            'msn_type' => 'notice',
+            'group_id' => $group['id'],
+            'group_see' => $order['uid'],
+            'msn' => ($this->getInfo(0, $order['uid'])['info']['name'] ?? '') . ' 加入群聊'
+        ]);
+        $chatGroupService->update($group['id'], ['last_message_time' => time()]);
+        return $group;
+    }
+
+    public function joinGroup($group_id, $uid, $type = 0)
+    {
+        /** @var ChatGroupServices $chatGroupService */
+        $chatGroupService = app()->make(ChatGroupServices::class);
+        /** @var ChatGroupMemberServices $chatMemberService */
+        $chatMemberService = app()->make(ChatGroupMemberServices::class);
+        $uid = $this->getUid($type, $uid);
+        if ($info = $chatMemberService->search()->where('uid', $uid)->where('chat_group_id', $group_id)->find()) {
+            if ($info['identity'] != $type) {
+                if ($info['ext_identity'])
+                    $ext_identity = explode(',', $info['ext_identity']);
+                else
+                    $ext_identity = [];
+                $ext_identity[] = $type;
+                $chatMemberService->update($info['id'], ['ext_identity' => implode(',', array_unique($ext_identity))]);
+            }
+            return true;
+        }
+        try {
+            $chatMemberService->create([
+                'uid' => $uid,
+                'chat_group_id' => $group_id,
+                'identity' => $type,
+                'nickname' => $this->user_type[$type] . '-' . ($this->getInfo($type, $uid)['info']['name'] ?? '')
+            ]);
+
+            $members = $chatMemberService->getColumn(['chat_group_id' => $group_id], 'uid');
+            foreach ($members as $member) {
+                SocketPush::user()->toGroup($member, $group_id)->type('notice')
+                    ->data($this->user_type[$type] . '-' . ($this->getInfo($type, $uid)['info']['name'] ?? '') . ' 加入群聊')
+                    ->push();
+            }
+
+            $this->create([
+                'uid' => $uid,
+                'to_uid' => 0,
+                'add_time' => time(),
+                'status' => 1,
+                'msn_type' => 'notice',
+                'group_id' => $group_id,
+                'group_see' => implode(',', $members),
+                'msn' => $this->user_type[$type] . '-' . ($this->getInfo($type, $uid)['info']['name'] ?? '') . ' 加入群聊'
+            ]);
+            $chatGroupService->update($group_id, ['last_message_time' => time()]);
+            return true;
+        } catch (Exception $e) {
+            throw new ApiException($e->getMessage());
+        }
+    }
+
+}

+ 185 - 0
app/services/pay/PayNotifyServices.php

@@ -0,0 +1,185 @@
+<?php
+// +----------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +----------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +----------------------------------------------------------------------
+
+namespace app\services\pay;
+
+use app\services\decoration\DecorationServices;
+use app\services\decoration\order\DecorationOrderServices;
+
+/**
+ * 支付成功回调
+ * Class PayNotifyServices
+ * @package app\services\pay
+ */
+class PayNotifyServices
+{
+
+    /**
+     * 订单定金支付成功之后
+     * @param string|null $order_id 订单id
+     * @return bool
+     */
+    public function wechatDeposit(string $order_id = null, string $trade_no = null)
+    {
+        try {
+            /** @var DecorationServices $services */
+            $services = app()->make(DecorationServices::class);
+            /** @var DecorationOrderServices $services */
+            $orderServices = app()->make(DecorationOrderServices::class);
+            $orderInfo = $orderServices->getOne(['order_id' => $order_id]);
+            if (!$orderInfo) {
+                $orderInfo = $orderServices->getOne(['unique' => $order_id]);
+                if (!$orderInfo) return true;
+            }
+            if ($orderInfo->step > 0) return true;
+            return $services->depositPaySuccess($orderInfo->toArray(), PayServices::WEIXIN_PAY, ['deposit_trade_no' => $trade_no]);
+        } catch (\Exception $e) {
+            return false;
+        }
+    }
+
+
+    /**
+     * 支付宝支付异步回调处理事件
+     * @param string|null $order_id
+     * @param string|null $trade_no
+     * @return bool
+     */
+    public function alipayDeposit(string $order_id = null, string $trade_no = null)
+    {
+        if (!$order_id || !$trade_no) {
+            return false;
+        }
+        try {
+            /** @var DecorationServices $services */
+            $services = app()->make(DecorationServices::class);
+            /** @var DecorationOrderServices $services */
+            $orderServices = app()->make(DecorationOrderServices::class);
+            $orderInfo = $orderServices->getOne(['order_id' => $order_id]);
+            if (!$orderInfo) {
+                $orderInfo = $orderServices->getOne(['unique' => $order_id]);
+                if (!$orderInfo) return true;
+            }
+            if ($orderInfo->step > 0) return true;
+            return $services->depositPaySuccess($orderInfo->toArray(), PayServices::ALIAPY_PAY, ['deposit_trade_no' => $trade_no]);
+        } catch (\Throwable $e) {
+            return false;
+        }
+    }
+
+
+    /**
+     * 订单定金支付成功之后
+     * @param string|null $order_id 订单id
+     * @return bool
+     */
+    public function wechatMiddle(string $order_id = null, string $trade_no = null)
+    {
+        try {
+            /** @var DecorationServices $services */
+            $services = app()->make(DecorationServices::class);
+            /** @var DecorationOrderServices $services */
+            $orderServices = app()->make(DecorationOrderServices::class);
+            $orderInfo = $orderServices->getOne(['order_id' => $order_id]);
+            if (!$orderInfo) {
+                $orderInfo = $orderServices->getOne(['unique' => $order_id]);
+                if (!$orderInfo) return true;
+            }
+            if ($orderInfo->step > 0) return true;
+            return $services->middlePaySuccess($orderInfo->toArray(), PayServices::WEIXIN_PAY, ['middle_trade_no' => $trade_no]);
+        } catch (\Exception $e) {
+            return false;
+        }
+    }
+
+
+    /**
+     * 支付宝支付异步回调处理事件
+     * @param string|null $order_id
+     * @param string|null $trade_no
+     * @return bool
+     */
+    public function alipayMiddle(string $order_id = null, string $trade_no = null)
+    {
+        if (!$order_id || !$trade_no) {
+            return false;
+        }
+        try {
+            /** @var DecorationServices $services */
+            $services = app()->make(DecorationServices::class);
+            /** @var DecorationOrderServices $services */
+            $orderServices = app()->make(DecorationOrderServices::class);
+            $orderInfo = $orderServices->getOne(['order_id' => $order_id]);
+            if (!$orderInfo) {
+                $orderInfo = $orderServices->getOne(['unique' => $order_id]);
+                if (!$orderInfo) return true;
+            }
+            if ($orderInfo->step > 0) return true;
+            return $services->middlePaySuccess($orderInfo->toArray(), PayServices::ALIAPY_PAY, ['middle_trade_no' => $trade_no]);
+        } catch (\Throwable $e) {
+            return false;
+        }
+    }
+
+
+    /**
+     * 订单定金支付成功之后
+     * @param string|null $order_id 订单id
+     * @return bool
+     */
+    public function wechatFinal(string $order_id = null, string $trade_no = null)
+    {
+        try {
+            /** @var DecorationServices $services */
+            $services = app()->make(DecorationServices::class);
+            /** @var DecorationOrderServices $services */
+            $orderServices = app()->make(DecorationOrderServices::class);
+            $orderInfo = $orderServices->getOne(['order_id' => $order_id]);
+            if (!$orderInfo) {
+                $orderInfo = $orderServices->getOne(['unique' => $order_id]);
+                if (!$orderInfo) return true;
+            }
+            if ($orderInfo->step > 0) return true;
+            return $services->finalPaySuccess($orderInfo->toArray(), PayServices::WEIXIN_PAY, ['final_trade_no' => $trade_no]);
+        } catch (\Exception $e) {
+            return false;
+        }
+    }
+
+
+    /**
+     * 支付宝支付异步回调处理事件
+     * @param string|null $order_id
+     * @param string|null $trade_no
+     * @return bool
+     */
+    public function alipayFinal(string $order_id = null, string $trade_no = null)
+    {
+        if (!$order_id || !$trade_no) {
+            return false;
+        }
+        try {
+            /** @var DecorationServices $services */
+            $services = app()->make(DecorationServices::class);
+            /** @var DecorationOrderServices $services */
+            $orderServices = app()->make(DecorationOrderServices::class);
+            $orderInfo = $orderServices->getOne(['order_id' => $order_id]);
+            if (!$orderInfo) {
+                $orderInfo = $orderServices->getOne(['unique' => $order_id]);
+                if (!$orderInfo) return true;
+            }
+            if ($orderInfo->step > 0) return true;
+            return $services->finalPaySuccess($orderInfo->toArray(), PayServices::ALIAPY_PAY, ['final_trade_no' => $trade_no]);
+        } catch (\Throwable $e) {
+            return false;
+        }
+    }
+}

+ 153 - 0
app/services/pay/PayServices.php

@@ -0,0 +1,153 @@
+<?php
+// +----------------------------------------------------------------------
+// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+// +----------------------------------------------------------------------
+// | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
+// +----------------------------------------------------------------------
+// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+// +----------------------------------------------------------------------
+// | Author: CRMEB Team <admin@crmeb.com>
+// +----------------------------------------------------------------------
+declare (strict_types=1);
+
+namespace app\services\pay;
+
+use qiniu\services\AliPayService;
+use qiniu\services\wechat\Payment;
+use think\exception\ValidateException;
+
+/**
+ * 支付统一入口
+ * Class PayServices
+ * @package app\services\pay
+ */
+class PayServices
+{
+    /**
+     * 微信支付类型
+     */
+    const WEIXIN_PAY = 'weixin';
+
+    /**
+     * 余额支付
+     */
+    const YUE_PAY = 'yue';
+
+    /**
+     * 积分支付
+     */
+    const INTEGRAL_PAY = 'integral';
+
+    /**
+     * 支付宝
+     */
+    const ALIAPY_PAY = 'alipay';
+
+    /**
+     * 现金支付
+     */
+    const CASH_PAY = 'cash';
+
+    /**
+     * 支付方式
+     * @var string[]
+     */
+    const PAY_TYPE = [
+        PayServices::WEIXIN_PAY => '微信支付',
+        PayServices::YUE_PAY => '余额支付',
+        PayServices::ALIAPY_PAY => '支付宝',
+//        PayServices::CASH_PAY => '现金支付',
+//        PayServices::INTEGRAL_PAY => '积分支付',
+    ];
+
+    /**
+     * 二维码条码值
+     * @var string
+     */
+    protected $authCode;
+
+    /**
+     * 设置二维码条码值
+     * @param string $authCode
+     * @return $this
+     */
+    public function setAuthCode(string $authCode)
+    {
+        $this->authCode = $authCode;
+        return $this;
+    }
+
+    /**
+     * 发起支付
+     * @param string $payType
+     * @param string $openid
+     * @param string $orderId
+     * @param string $price
+     * @param string $successAction
+     * @param string $body
+     * @param bool $isCode
+     * @return mixed
+     */
+    public function pay(string $payType, string $openid, string $orderId, string $price, string $successAction, string $body, bool $isCode = false)
+    {
+        try {
+            $body = filter_emoji($body);
+            switch ($payType) {
+                case 'routine':
+                    //微信支付,从APP端请求过来
+                    if (request()->isApp()) {
+                        return Payment::appPay($openid, $orderId, $price, $successAction, $body);
+                    } else {
+                        //判断有没有打开小程序支付
+                        if (sys_config('pay_routine_open', 0)) {
+                            return Payment::miniPay($openid, $orderId, $price, $successAction, $body);
+                        } else {
+                            //开启了v3支付
+                            if (Payment::instance()->isV3PAy) {
+                                return Payment::instance()->application()->v3pay->miniprogPay($openid, $orderId, $price, $body, $successAction);
+                            }
+                            return Payment::jsPay($openid, $orderId, $price, $successAction, $body);
+                        }
+                    }
+                case 'weixinh5':
+                    ////开启了v3支付
+                    if (Payment::instance()->isV3PAy) {
+                        return Payment::instance()->application()->v3pay->h5Pay($orderId, $price, $body, $successAction);
+                    }
+                    //旧版v2支付
+                    return Payment::paymentOrder(null, $orderId, $price, $successAction, $body, '', 'MWEB');
+                case self::WEIXIN_PAY:
+                    //微信支付,付款码支付,付款码支付使用v2支付接口
+                    if ($this->authCode) {
+                        return Payment::microPay($this->authCode, $orderId, $price, $successAction, $body);
+                    } else {
+                        //微信支付,从APP端请求过来
+                        if (request()->isApp()) {
+                            return Payment::appPay($openid, $orderId, $price, $successAction, $body);
+                        } else {
+                            //开启了v3支付
+                            if (Payment::instance()->isV3PAy) {
+                                return Payment::instance()->application()->v3pay->jsapiPay($openid, $orderId, $price, $body, $successAction);
+                            }
+                            //使用v2旧版支付接口
+                            return Payment::jsPay($openid, $orderId, $price, $successAction, $body);
+                        }
+                    }
+                case self::ALIAPY_PAY:
+                    if ($this->authCode) {
+                        return AliPayService::instance()->microPay($this->authCode, $body, $orderId, $price, $successAction);
+                    } else {
+                        return AliPayService::instance()->create($body, $orderId, $price, $successAction, $openid, $openid, $isCode);
+                    }
+                case 'pc':
+                case 'store':
+                    //方法内部已经做了区分v2和v3
+                    return Payment::nativePay($openid, $orderId, $price, $successAction, $body);
+                default:
+                    throw new ValidateException('支付方式不存在');
+            }
+        } catch (\Throwable $e) {
+            throw new ValidateException($e->getMessage());
+        }
+    }
+}

+ 3 - 4
app/services/system/admin/SystemAdminServices.php

@@ -95,7 +95,7 @@ class SystemAdminServices extends BaseServices
         /** @var SystemMenusServices $services */
         $services = app()->make(SystemMenusServices::class);
         [$menus, $uniqueAuth] = $services->getMenusList($adminInfo['roles'], (int)$adminInfo['level']);
-        $data = SystemConfigService::more(['site_logo', 'site_logo_square','site_name']);
+        $data = SystemConfigService::more(['site_name', 'site_logo', 'site_logo_square']);
         return [
             'token' => $tokenInfo['token'],
             'expires_time' => $tokenInfo['params']['exp'],
@@ -107,10 +107,9 @@ class SystemAdminServices extends BaseServices
                 'real_name' => $adminInfo['real_name'],
                 'head_pic' => $adminInfo['head_pic'],
             ],
-            'logo' => $data['site_logo'],
             'site_name' => $data['site_name'],
+            'logo' => $data['site_logo'],
             'logo_square' => $data['site_logo_square'],
-            'prefix' => config('admin.admin_prefix')
         ];
     }
 
@@ -190,7 +189,7 @@ class SystemAdminServices extends BaseServices
     public function getAdminList(array $where)
     {
         [$page, $limit] = $this->getPageValue();
-        $list = $this->getList($where,'*', $page, $limit);
+        $list = $this->getList($where, '*', $page, $limit);
         $count = $this->getCount($where);
 
         /** @var SystemRoleServices $service */

+ 14 - 0
app/services/system/admin/SystemRoleServices.php

@@ -144,6 +144,20 @@ class SystemRoleServices extends BaseServices
         });
     }
 
+    /**
+     * 获取指定权限
+     * @param array $roles
+     * @param int $auth_type
+     * @param int $type
+     * @param string $cachePrefix
+     * @return array|bool|mixed|null
+     * @throws \Throwable
+     */
+    public function getRolesNames($roles)
+    {
+        return $this->where('id', 'in', $roles)->column('role_name');
+    }
+
     /**
      * 获取权限id
      * @param array $roles

+ 7 - 1
app/services/system/attachment/SystemAttachmentServices.php

@@ -65,7 +65,7 @@ class SystemAttachmentServices extends BaseServices
     public function getImageList(array $where)
     {
         [$page, $limit] = $this->getPageValue();
-        $list = $this->getList($where,'*', $page, $limit);
+        $list = $this->getList($where, '*', $page, $limit);
         if ($list) {
             $site_url = sys_config('site_url');
             foreach ($list as &$item) {
@@ -175,6 +175,9 @@ class SystemAttachmentServices extends BaseServices
         $data['module_type'] = $module_type;
         $data['time'] = $time ? $time : time();
         $data['pid'] = $pid;
+        if (strpos($data['att_type'], 'video') !== false) {
+            $data['file_type'] = 2;
+        }
         if (!$this->save($data)) {
             throw new ValidateException('添加附件失败');
         }
@@ -373,6 +376,9 @@ class SystemAttachmentServices extends BaseServices
     {
         $fileType = pathinfo($fileInfo['name'], PATHINFO_EXTENSION);
         if ($fileInfo && !in_array($fileType, ['xlsx', 'xls'])) {
+            if (strpos($fileInfo['type'] ?? '', 'video') !== false) {
+                $file_type = 2;
+            }
             $data['file_type'] = $file_type;
             $data['type'] = $type == 0 ? 1 : $type;
             $data['relation_id'] = $relation_id;

+ 1 - 1
app/services/system/config/SystemStorageServices.php

@@ -46,7 +46,7 @@ class SystemStorageServices extends BaseServices
         [$page, $limit] = $this->getPageValue();
         $config = $this->getStorageConfig((int)$where['type']);
         $where['access_key'] = $config['accessKey'];
-        $list = $this->getList($where, '*', $page, $limit);
+        $list = $this->getList($where,'*', $page, $limit);
         foreach ($list as &$item) {
             $item['_add_time'] = date('Y-m-d H:i:s', $item['add_time']);
             $item['_update_time'] = date('Y-m-d H:i:s', $item['update_time']);

+ 249 - 0
app/services/system/store/SystemStoreServices.php

@@ -0,0 +1,249 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types=1);
+
+namespace app\services\system\store;
+
+use app\services\system\admin\SystemAdminServices;
+use qiniu\exceptions\AdminException;
+use qiniu\basic\BaseServices;
+use app\model\system\store\SystemStore;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\DbException;
+use think\db\exception\ModelNotFoundException;
+use think\exception\ValidateException;
+
+/**
+ * 门店服务
+ * Class SystemStoreServices
+ * @package app\services\system\store
+ * @mixin SystemStore
+ */
+class SystemStoreServices extends BaseServices
+{
+
+    protected $exportHeader = [
+        'id' => 'Id',
+        'type' => '门店类型:1自营2加盟',
+        'cate_ids_chs' => '门店分类',
+        'name' => '门店名称',
+        'introduction' => '简介',
+        'phone' => '联系电话',
+        'address' => '省市区',
+        'province' => '省ID',
+        'city' => '市ID',
+        'area' => '区ID',
+        'street' => '街道ID',
+        'detailed_address' => '详细地址',
+        'logo' => '门店logo',
+        'slide_images_chs' => '门店推荐图',
+        'latitude' => '纬度',
+        'longitude' => '经度',
+        'valid_range' => '有效距离',
+        'add_time' => '添加时间',
+        'is_show' => '是否显示',
+        'product_status_chs' => '自主添加商品状态',
+        'product_verify_status_chs' => '商品免审核'
+    ];
+
+    /**
+     * SystemStoreServices constructor.
+     * @param SystemStore $model
+     */
+    public function __construct(SystemStore $model)
+    {
+        $this->model = $model;
+    }
+
+
+    /**
+     * 保存或修改门店
+     * @param int $id
+     * @param array $data
+     * @return mixed
+     * @throws DbException
+     */
+    public function saveStore(int $id, array $data)
+    {
+        return $this->transaction(function () use ($id, $data) {
+            if ($id) {
+                $is_new = 0;
+                unset($data['store_account'], $data['store_password']);
+                if ($this->update($id, $data)) {
+                    return [$id, $is_new];
+                } else {
+                    throw new AdminException('修改失败或者您没有修改什么!');
+                }
+            } else {
+                $is_new = 1;
+                $store_account = $data['store_account'] ?? '';
+                $store_password = $data['store_password'] ?? '';
+                unset($data['store_account'], $data['store_password']);
+                if ($res = $this->create($data)) {
+                    if ($store_account && $store_password) {
+                        /** @var SystemAdminServices $adminServices */
+                        $adminServices = app()->make(SystemAdminServices::class);
+                        if ($adminServices->getCount(['phone' => $data['phone']])) {
+                            throw new AdminException('该手机号已经存在');
+                        }
+                        if ($adminServices->getCount(['account' => $store_account])) {
+                            throw new AdminException('管理员账号已存在');
+                        }
+                        $staff_data['level'] = 0;
+                        $staff_data['admin_type'] = 2;
+                        $staff_data['relation_id'] = $res->id;
+                        $staff_data['real_name'] = $data['manager_name'];
+                        $staff_data['roles'] = [1];
+                        $staff_data['pwd'] = $store_password;
+                        $staff_data['conf_pwd'] = $store_password;
+                        $staff_data['account'] = $store_account;
+                        $staff_data['phone'] = $data['phone'];
+                        if (!$adminServices->create($staff_data)) {
+                            throw new AdminException('创建门店管理员失败!');
+                        }
+                    }
+                    return true;
+                } else {
+                    throw new AdminException('保存失败!');
+                }
+            }
+        });
+    }
+
+
+    /**
+     * 门店重置账号、密码、管理员手机号
+     * @param int $id
+     * @param array $data
+     * @return bool
+     * @throws DbException
+     * @throws DataNotFoundException
+     * @throws ModelNotFoundException
+     */
+    public function resetAdmin(int $id, array $data)
+    {
+        $storeInfo = $this->getStoreInfo((int)$id);
+        if (!$storeInfo) {
+            throw new ValidateException('门店数据不存在');
+        }
+        /** @var SystemAdminServices $staffServices */
+        $staffServices = app()->make(SystemAdminServices::class);
+        $staffInfo = $staffServices->getOne(['id' => (int)$data['admin_id'], 'store_id' => $id]);
+        if (!$staffInfo) {
+            throw new ValidateException('门店管理员数据不存在');
+        }
+        $staff_data = [];
+        if ($data['phone'] != $storeInfo['phone']) {//重置手机号 清空之前绑定
+            $staff_data['uid'] = 0;
+        }
+        $staff_data['account'] = $data['account'];
+        $staff_data['phone'] = $data['phone'];
+        $staff_data['store_id'] = $storeInfo['id'];
+        $staff_data['pwd'] = $this->passwordHash($data['password']);
+        $staffInfo = $staffServices->getOne(['account' => $data['account']]);
+        if ($data['admin_id'] && $staffServices->getCount(['id' => $data['admin_id']])) {
+            if ($staffInfo && $staffInfo['id'] != $data['admin_id']) {
+                throw new ValidateException('该账号已存在');
+            }
+            if (!$staffServices->update($data['admin_id'], $staff_data)) {
+                throw new ValidateException('重置门店管理员失败!');
+            }
+        } else {
+            $staff_data['level'] = 0;
+            $staff_data['roles'] = 1;
+            if ($staffInfo) {
+                throw new ValidateException('该账号已存在');
+            }
+            if (!$staffServices->create($staff_data)) {
+                throw new ValidateException('创建门店管理员失败!');
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 经纬度排序计算
+     * @param string $latitude
+     * @param string $longitude
+     * @param bool $type
+     * @return string
+     */
+    public function distance(string $latitude, string $longitude, bool $type = false)
+    {
+        if ($type) {
+            return "(round(6378137 * 2 * asin(sqrt(pow(sin(((latitude * pi()) / 180 - ({$latitude} * pi()) / 180) / 2), 2) + cos(({$latitude} * pi()) / 180) * cos((latitude * pi()) / 180) * pow(sin(((longitude * pi()) / 180 - ({$longitude} * pi()) / 180) / 2), 2)))))";
+        } else {
+            return "(round(6378137 * 2 * asin(sqrt(pow(sin(((latitude * pi()) / 180 - ({$latitude} * pi()) / 180) / 2), 2) + cos(({$latitude} * pi()) / 180) * cos((latitude * pi()) / 180) * pow(sin(((longitude * pi()) / 180 - ({$longitude} * pi()) / 180) / 2), 2))))) AS distance";
+        }
+    }
+
+
+    /**
+     * 获取门店
+     * @param array $where
+     * @param array $field
+     * @param string $latitude
+     * @param string $longitude
+     * @param array $with
+     * @param int $store_id
+     * @return array
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function getStoreList(array $where, array $field = ['*'], string $latitude = '', string $longitude = '', array $with = [], $store_id = 0)
+    {
+        [$page, $limit] = $this->getPageValue();
+        $order = 0;
+        if ($longitude && $latitude) {
+            $order = 1;
+        }
+        $list = [];
+        $count = 0;
+        //移动端定位选择门店
+        if ($store_id) {
+            $where['id'] = isset($where['id']) && $where['id'] ? array_merge($where['id'], [$store_id]) : [$store_id];
+        }
+        if (isset($where['id'])) {
+            $where['id'] = array_unique(array_diff($where['id'], [0]));
+        }
+        $storeList = $this->search($where)->when($with, function ($query) use ($with) {
+            $query->with($with);
+        })->when($latitude && $longitude, function ($query) use ($longitude, $latitude, $order) {
+            $query->field(['*', $this->distance($latitude, $longitude)]);
+        })->when($page && $limit, function ($query) use ($page, $limit) {
+            $query->page($page, $limit);
+        })->when(isset($order), function ($query) use ($order) {
+            if ($order == 1) {
+                $query->order('distance ASC');
+            } else {
+                $query->order('id desc');
+            }
+        })->field($field)->select()->toArray();
+        if ($storeList) {
+            foreach ($storeList as &$item) {
+                if (isset($item['distance'])) {
+                    $item['range'] = bcdiv($item['distance'], '1000', 1);
+                } else {
+                    $item['range'] = 0;
+                }
+                if ($item['is_show'] == 1) {
+                    $item['status_name'] = '营业中';
+                } else {
+                    $item['status_name'] = '已停业';
+                }
+                $list[] = $item;
+            }
+            $count = $this->getCount($where);
+        }
+
+        return compact('list', 'count');
+    }
+
+}

+ 2 - 2
app/services/user/LoginServices.php

@@ -54,7 +54,7 @@ class LoginServices extends BaseServices
      * @throws DbException
      * @throws ModelNotFoundException
      */
-    public function login($account, $login_type, $password, int $spread_uid = 0)
+    public function login($account, $login_type, $password, $spread_uid = 0)
     {
         if ($login_type != 'phone') $login_type = 'account';
         $user = $this->getOne([$login_type => $account], 'uid,pwd,status,salt');
@@ -155,7 +155,7 @@ class LoginServices extends BaseServices
      */
     public function verify($phone, $type, $time, $ip)
     {
-        if ($this->getOne(['phone' => $phone]) && $type == 'register') {
+        if ($this->getOne(['phone' => $phone]) && ($type == 'register' || $type == 'change_new')) {
             throw new ValidateException('手机号已注册');
         }
         $default = Config::get('sms.default', 'qiniu');

+ 10 - 4
app/services/user/UserAddressServices.php

@@ -171,21 +171,27 @@ class UserAddressServices extends BaseServices
      */
     public function editAddress(int $uid, array $addressInfo)
     {
-        if ($addressInfo['type'] == 1 && !$addressInfo['id']) {
+        if ($addressInfo['type'] == 1) {
+            $province = $addressInfo['address']['province'];
             $city = $addressInfo['address']['city'];
             /** @var CityAreaServices $systemCity */
             $systemCity = app()->make(CityAreaServices::class);
-            $cityInfo = $systemCity->getOne([['name', '=', $city], ['parent_id', '<>', 0]]);
+
+            $province = $systemCity->search()->where([['name', '=', $province], ['parent_id', '=', 0]])->find();
+            if (!$province || !$province['code']) {
+                throw new ValidateException('收货地址格式错误!修改后请重新导入!');
+            }
+            $cityInfo = $systemCity->search()->where([['name', '=', $city], ['parent_id', '=', $province['id']]])->find();
             if ($cityInfo && $cityInfo['code']) {
                 $addressInfo['address']['city_id'] = $cityInfo['code'];
             } else {
-                $cityInfo = $systemCity->getOne([['name', 'like', "%$city%"], ['parent_id', '<>', 0]]);
+                $cityInfo = $systemCity->search()->where([['name', 'like', "%$city%"], ['parent_id', '=', $province['id']]])->find();
                 if (!$cityInfo) {
                     throw new ValidateException('收货地址格式错误!修改后请重新导入!');
                 }
                 $addressInfo['address']['city_id'] = $cityInfo['code'];
             }
-            $addressInfo['province_id'] = $systemCity->getOne(['id' => $cityInfo['pid']])['code'] ?? '';
+            $addressInfo['province_id'] = $province['code'];
         }
         if (!isset($addressInfo['address']['city_id']) || $addressInfo['address']['city_id'] == 0) throw new ValidateException('添加收货地址失败!');
         $addressInfo['province'] = $addressInfo['address']['province'] ?? '';

+ 58 - 0
app/services/user/UserBankServices.php

@@ -0,0 +1,58 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types=1);
+
+namespace app\services\user;
+
+use qiniu\basic\BaseServices;
+use app\model\user\UserBank;
+
+/**
+ * 收款方式服务
+ * Class UserBankServices
+ * @package app\services\user
+ * @mixin UserBank
+ */
+class UserBankServices extends BaseServices
+{
+
+    protected $exportHeader = [
+        'id' => 'Id',
+        'uid' => '用户ID',
+        'type_chs' => '提现方式',
+        'bank' => '银行名',
+        'bank_name' => '开户行名',
+        'bank_code' => '卡号',
+        'real_name' => '收款人姓名',
+        'phone' => '手机号码',
+        'account' => '支付宝/微信号',
+        'qrcode' => '收款码',
+        'default' => '是否默认',
+        'add_time' => '添加时间'
+    ];
+
+    /**
+     * UserBankServices constructor.
+     * @param UserBank $model
+     */
+    public function __construct(UserBank $model)
+    {
+        $this->model = $model;
+    }
+
+    public function getBankList($uid, $where = [])
+    {
+        [$page, $limit] = $this->getPageValue();
+        $where['uid'] = $uid;
+        $list = $this->getList($where, '*', $page, $limit);
+        $count = $this->getCount($where);
+        return compact('list', 'count');
+    }
+
+}

+ 69 - 2
app/services/user/UserBillServices.php

@@ -118,6 +118,69 @@ class UserBillServices extends BaseServices
         return compact('list', 'count');
     }
 
+    /**
+     * 获取资金列表
+     * @param array $where
+     * @param string $field
+     * @param int $limit
+     * @return array
+     * @throws \think\db\exception\DbException
+     */
+    public function getUserBillList($category, array $where, string $field = '*', int $limit = 0)
+    {
+        $where_data = ['category' => $category];
+        if (isset($where['uid']) && $where['uid'] != '') {
+            $where_data['uid'] = $where['uid'];
+        }
+        if ($where['start_time'] != '' && $where['end_time'] != '') {
+            $where_data['time'] = str_replace('-', '/', $where['start_time']) . ' - ' . str_replace('-', '/', $where['end_time']);
+        }
+        if (isset($where['type']) && $where['type'] != '') {
+            $where_data['type'] = $where['type'];
+        }
+        if (isset($where['nickname']) && $where['nickname'] != '') {
+            $where_data['like'] = $where['nickname'];
+        }
+        if (isset($where['pm']) && $where['pm'] != '') {
+            $where_data['pm'] = $where['pm'];
+        }
+        if ($limit) {
+            [$page] = $this->getPageValue();
+        } else {
+            [$page, $limit] = $this->getPageValue();
+        }
+        $data = $this->getList($where_data, $field, $page, $limit, [
+            'user' => function ($query) {
+                $query->field('uid,nickname');
+            }
+        ]);
+        foreach ($data as &$item) {
+            $item['nickname'] = $item['user']['nickname'] ?? '';
+            $item['_add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
+            unset($item['user']);
+        }
+        $count = $this->getCount($where_data);
+        return compact('data', 'count');
+    }
+
+
+    /**
+     * 某个用户佣金总和
+     * @param int $uid
+     * @param string $time
+     * @param int $pm
+     * @return float
+     */
+    public function getUserBillSum(int $uid, $category, string $time = '', int $pm = 1)
+    {
+        $where = ['uid' => $uid];
+        $where['pm'] = $pm;
+        $where['status'] = 1;
+        $where['category'] = $category;
+        if ($time) $where['time'] = $time;
+        return $this->getSum($where, 'number');
+    }
+
 
     /**
      * 写入用户记录
@@ -165,7 +228,7 @@ class UserBillServices extends BaseServices
                     $userService->bcDec($uid, $data['category'], $data['number'], 'uid');
                 }
             }
-            return $this->save($data);
+            return $this->create($data);
         }
         return true;
     }
@@ -210,13 +273,17 @@ class UserBillServices extends BaseServices
             throw new ValidateException('数据不存在');
         }
         if ($to_uid == $uid) throw new ValidateException('不能自己转给自己');
-        $extractPrice = $user[$category];
+        if (!isset($this->categorys[$category])) throw new ValidateException('代币不存在');
+        $extractPrice = $user[$category] ?? 0;
         if ($num > $extractPrice) {
             throw new ValidateException('转账' . $this->categorys[$category] . '不足' . $num);
         }
         if ($num <= 0) {
             throw new ValidateException('转账' . $this->categorys[$category] . '大于0');
         }
+        if (!isset($this->incomeData['trade_out_' . $category]) || !isset($this->incomeData['trade_in_' . $category])) {
+            throw new ValidateException('暂不支持转账');
+        }
         return $this->transaction(function () use ($num, $user, $to_user, $userService, $category) {
             $this->income('trade_out_' . $category, $user['uid'], ['mark' => '转账给' . $to_user['nickname'] . '(' . $to_user['uid'] . ')', 'number' => $num], $to_user['uid']);
             $this->income('trade_in_' . $category, $to_user['uid'], ['mark' => '转账自' . $user['nickname'] . '(' . $user['uid'] . ')', 'number' => $num], $user['uid']);

+ 19 - 5
app/services/user/UserBrokerageServices.php

@@ -59,6 +59,20 @@ class UserBrokerageServices extends BaseServices
             'status' => 1,
             'pm' => 0
         ],
+        'extract' => [
+            'title' => '佣金提现',
+            'type' => 'extract',
+            'mark' => '{%mark%},佣金提现{%number%}元',
+            'status' => 1,
+            'pm' => 0
+        ],
+        'extract_fail' => [
+            'title' => '提现失败',
+            'type' => 'extract_fail',
+            'mark' => '提现失败,退回佣金{%num%}元',
+            'status' => 1,
+            'pm' => 1
+        ],
     ];
 
     /**
@@ -141,7 +155,7 @@ class UserBrokerageServices extends BaseServices
      * @throws \think\db\exception\DbException
      * @throws \think\db\exception\ModelNotFoundException
      */
-    public function income(string $type, int $uid, $number, $link_id = 0)
+    public function income(string $type, int $uid, $number, $link_id = 0, $mark = '')
     {
         $data = $this->incomeData[$type] ?? null;
         if (!$data) {
@@ -157,10 +171,10 @@ class UserBrokerageServices extends BaseServices
             $value = array_values($number);
             $data['number'] = $number['number'] ?? 0;
             $data['frozen_time'] = $number['frozen_time'] ?? 0;
-            $data['mark'] = str_replace($key, $value, $data['mark']);
+            $data['mark'] = $mark ?: str_replace($key, $value, $data['mark']);
         } else {
             $data['number'] = $number;
-            $data['mark'] = str_replace(['{%number%}'], $number, $data['mark']);
+            $data['mark'] = $mark ?: str_replace(['{%number%}'], $number, $data['mark']);
         }
         /** @var UserServices $userService */
         $userService = app()->make(UserServices::class);
@@ -178,7 +192,7 @@ class UserBrokerageServices extends BaseServices
                     $userService->bcDec($uid, 'brokerage_price', $data['number'], 'uid');
                 }
             }
-            return $this->save($data);
+            return $this->create($data);
         }
         return true;
     }
@@ -239,7 +253,7 @@ class UserBrokerageServices extends BaseServices
         ]);
         foreach ($data as &$item) {
             $item['nickname'] = $item['user']['nickname'] ?? '';
-            $item['_add_time'] = $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
+            $item['_add_time'] = is_int($item['add_time']) && $item['add_time'] ? date('Y-m-d H:i:s', $item['add_time']) : '';
             unset($item['user']);
         }
         $count = $this->getCount($where_data);

+ 198 - 0
app/services/user/UserExtractServices.php

@@ -0,0 +1,198 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+declare (strict_types=1);
+
+namespace app\services\user;
+
+use qiniu\basic\BaseServices;
+use app\model\user\UserExtract;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\DbException;
+use think\db\exception\ModelNotFoundException;
+use think\exception\ValidateException;
+
+/**
+ * 用户提现服务
+ * Class UserExtractServices
+ * @package app\services\user
+ * @mixin UserExtract
+ */
+class UserExtractServices extends BaseServices
+{
+
+    protected $exportHeader = [
+        'id' => 'Id',
+        'uid' => '用户',
+        'real_name' => '名称',
+        'phone' => '联系电话',
+        'extract_type_chs' => '提现方式',
+        'bank_code' => '银行卡',
+        'bank_address' => '开户地址',
+        'alipay_code' => '支付宝账号',
+        'extract_price' => '提现金额',
+        'extract_fee' => '手续费金额',
+        'balance' => '提现后余额',
+        'mark' => '备注',
+        'fail_msg' => '驳回原因',
+        'fail_time_chs' => '驳回时间',
+        'add_time' => '添加时间',
+        'status_chs' => '状态',
+        'wechat' => '微信号',
+        'qrcode_url' => '二维码链接'
+    ];
+
+    /**
+     * UserExtractServices constructor.
+     * @param UserExtract $model
+     */
+    public function __construct(UserExtract $model)
+    {
+        $this->model = $model;
+    }
+
+
+    /**
+     * 提现计算
+     * @param int $uid
+     * @return array
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function compute(int $uid)
+    {
+        /** @var UserServices $userService */
+        $userService = app()->make(UserServices::class);
+        $user = $userService->getUserInfo($uid);
+        if (!$user) {
+            throw new ValidateException('数据不存在');
+        }
+        /** @var UserBrokerageServices $userBrokerageServices */
+        $userBrokerageServices = app()->make(UserBrokerageServices::class);
+        /** @var UserBankServices $userBankServices */
+        $userBankServices = app()->make(UserBankServices::class);
+        $data['broken_commission'] = $userBrokerageServices->getUserFrozenPrice($uid);
+        if ($data['broken_commission'] < 0)
+            $data['broken_commission'] = '0';
+        $data['brokerage_price'] = $user['brokerage_price'];
+        //可提现佣金
+        $data['commissionCount'] = bcsub((string)$data['brokerage_price'], (string)$data['broken_commission'], 2);
+        $data['bankSwitch'] = sys_config('user_extract_bank_status', 0);
+        $data['wechatSwitch'] = sys_config('user_extract_wechat_status', 0);
+        $data['alipaySwitch'] = sys_config('user_extract_alipay_status', 0);
+        $data['minPrice'] = sys_config('user_extract_min_price');//提现最低金额
+        $data['maxPrice'] = sys_config('user_extract_max_price');//提现最高金额
+        $data['withdraw_fee'] = sys_config('withdraw_fee');//提现手续费
+        $data['default_bank'] = $userBankServices->getOne(['uid' => $uid, 'default' => 1]);
+        return $data;
+    }
+
+
+    /**
+     * 提现申请
+     * @param $bankInfo
+     * @param $money
+     * @return bool
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function cash($bankInfo, $money)
+    {
+        /** @var UserServices $userService */
+        $userService = app()->make(UserServices::class);
+        $user = $userService->getUserInfo($bankInfo['uid']);
+        $uid = $user['uid'];
+        if (!$user) {
+            throw new ValidateException('数据不存在');
+        }
+        if ($money <= 0) {
+            throw new ValidateException('提现金额大于0');
+        }
+        $userBrokerageServices = app()->make(UserBrokerageServices::class);
+        $broken_commission = $userBrokerageServices->getUserFrozenPrice($user['uid']);
+        if ($broken_commission < 0)
+            $broken_commission = '0';
+        $brokerage_price = $user['brokerage_price'];
+        //可提现佣金
+        $commissionCount = bcsub((string)$brokerage_price, (string)$broken_commission, 2);
+        if ($money > $commissionCount) {
+            throw new ValidateException('可提现佣金不足');
+        }
+
+        $userExtractMinPrice = sys_config('user_extract_min_price');
+        if ($money < $userExtractMinPrice) {
+            throw new ValidateException('提现金额不能小于' . $userExtractMinPrice . '元');
+        }
+        $userExtractMaxPrice = sys_config('user_extract_max_price');
+        if ($money > $userExtractMaxPrice) {
+            throw new ValidateException('提现金额不能大于' . $userExtractMaxPrice . '元');
+        }
+
+        $extract_fee = bcmul((string)$money, bcdiv(sys_config('withdraw_fee'), '100', 4), 2);
+
+        $insertData = [
+            'uid' => $user['uid'],
+            'type' => $bankInfo['type'],
+            'extract_price' => bcsub((string)$money, (string)$extract_fee, 2),
+            'extract_fee' => $extract_fee,
+            'balance' => bcsub((string)$user['brokerage_price'], (string)$money, 2),
+            'status' => 0,
+            'real_name' => $bankInfo['real_name'],
+            'phone' => $bankInfo['phone']
+        ];
+        if ($bankInfo['type'] == 0) {
+            $insertData['bank_code'] = $bankInfo['bank_code'];
+            $insertData['bank_address'] = $bankInfo['bank'] . ' ' . $bankInfo['bank_name'];
+            $mark = '使用银联卡' . $insertData['bank_code'];
+        } else if ($bankInfo['type'] == 1) {
+            $insertData['alipay_code'] = $bankInfo['account'];
+            $insertData['qrcode_url'] = $bankInfo['qrcode'];
+            $mark = '使用支付宝';
+        } else {
+            $insertData['wechat'] = $bankInfo['account'];
+            $insertData['qrcode_url'] = $bankInfo['qrcode'];
+            $mark = '使用微信';
+        }
+        /** @var UserBrokerageServices $userBrokerageServices */
+        $userBrokerageServices = app()->make(UserBrokerageServices::class);
+        return $this->transaction(function () use ($insertData, $money, $uid, $userService, $user, $userBrokerageServices, $mark) {
+            if (!$res = $this->create($insertData)) {
+                throw new ValidateException('提现失败');
+            }
+            $res = $res && $userBrokerageServices->income('extract', $uid, ['mark' => $mark, 'number' => $money], $res['id']);
+            //保存佣金记录
+            return $res;
+        });
+    }
+
+
+    /**
+     * 获取提现列表
+     * @param array $where
+     * @param string $field
+     * @return array
+     * @throws DbException
+     */
+    public function getUserExtractList(array $where, string $field = '*')
+    {
+        [$page, $limit] = $this->getPageValue();
+        $list = $this->getList($where, $field, $page, $limit, [
+            'user' => function ($query) {
+                $query->field('uid,nickname,real_name');
+            }]);
+        foreach ($list as &$item) {
+            $item['nickname'] = $item['user']['nickname'] ?? '';
+            $item['user_real_name'] = $item['user']['real_name'] ?? '';
+        }
+        $count = $this->getCount($where);
+        return compact('list', 'count');
+    }
+
+}

+ 0 - 1
app/services/user/UserLevelServices.php

@@ -17,7 +17,6 @@ use app\services\system\config\SystemUserLevelTaskServices;
 use qiniu\basic\BaseServices;
 use app\model\user\UserLevel;
 use qiniu\exceptions\AdminException;
-use qiniu\services\SystemConfigService;
 use think\db\exception\DataNotFoundException;
 use think\db\exception\DbException;
 use think\db\exception\ModelNotFoundException;

+ 28 - 2
app/services/user/UserMoneyServices.php

@@ -80,6 +80,32 @@ class UserMoneyServices extends BaseServices
         $this->model = $model;
     }
 
+    /**
+     * 某个用户佣金总和
+     * @param int $uid
+     * @param string $time
+     * @param int $pm
+     * @return float
+     */
+    public function getUserMoneySum(int $uid, string $time = '', int $pm = 1)
+    {
+        $where = ['uid' => $uid];
+        $where['pm'] = $pm;
+        $where['status'] = 1;
+        if ($time) $where['time'] = $time;
+        return $this->getMoneySum($where);
+    }
+
+    /**
+     * 获取某个条件总数
+     * @param array $where
+     * @return float
+     */
+    public function getMoneySum(array $where)
+    {
+        return $this->search($where)->sum('number');
+    }
+
 
     /**
      * 获取资金列表
@@ -131,7 +157,7 @@ class UserMoneyServices extends BaseServices
      * @param int $uid
      * @param int|string|array $number
      * @param int|string $link_id
-     * @return bool
+     * @return bool|\qiniu\basic\BaseModel|\think\Model
      * @throws DbException
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\ModelNotFoundException
@@ -173,7 +199,7 @@ class UserMoneyServices extends BaseServices
                     $userService->bcDec($uid, 'now_money', $data['number'], 'uid');
                 }
             }
-            return $this->save($data);
+            return $this->create($data);
         }
         return true;
     }

+ 2 - 886
app/services/user/UserServices.php

@@ -61,7 +61,7 @@ class UserServices extends BaseServices
      * @throws DbException
      * @throws ModelNotFoundException
      */
-    public function getUserInfo(int $uid, $field = '*')
+    public function getUserInfo($uid, $field = '*')
     {
         if (is_string($field)) $field = explode(',', $field);
         return $this->get($uid, $field);
@@ -448,896 +448,12 @@ class UserServices extends BaseServices
         return $info;
     }
 
-    /**
-     * 个人中心
-     * @param array $user
-     */
-    public function personalHome(array $user, $tokenData)
-    {
-        $uid = (int)$user['uid'];
-        event('user.login', [$uid, app('request')->ip()]);
-        /** @var StoreCouponUserServices $storeCoupon */
-        $storeCoupon = app()->make(StoreCouponUserServices::class);
-        /** @var UserMoneyServices $userMoneyServices */
-        $userMoneyServices = app()->make(UserMoneyServices::class);
-        /** @var UserExtractServices $userExtract */
-        $userExtract = app()->make(UserExtractServices::class);
-        /** @var StoreOrderServices $storeOrder */
-        $storeOrder = app()->make(StoreOrderServices::class);
-        /** @var UserLevelServices $userLevel */
-        $userLevel = app()->make(UserLevelServices::class);
-        /** @var StoreServiceServices $storeService */
-        $storeService = app()->make(StoreServiceServices::class);
-        /** @var WechatUserServices $wechatUser */
-        $wechatUser = app()->make(WechatUserServices::class);
-        /** @var UserRelationServices $productRelation */
-        $productRelation = app()->make(UserRelationServices::class);
-        /** @var SystemMessageServices $systemMessageServices */
-        $systemMessageServices = app()->make(SystemMessageServices::class);
-        /** @var DiyServices $diyServices */
-        $diyServices = app()->make(DiyServices::class);
-        /** @var AgentLevelServices $agentLevelServices */
-        $agentLevelServices = app()->make(AgentLevelServices::class);
-        /** @var StoreProductLogServices $storeProductLogServices */
-        $storeProductLogServices = app()->make(StoreProductLogServices::class);
-        //是否存在核销码
-        if (!$user['bar_code']) {
-            $bar_code = $this->getBarCode();
-            $this->dao->update($uid, ['bar_code' => $bar_code], 'uid');
-            $user['bar_code'] = $bar_code;
-        }
-        //获取配置参数
-        $configData = SystemConfigService::more([
-            'member_card_status',
-            'brokerage_func_status',
-            'store_brokerage_statu',
-            'store_brokerage_price',
-            'member_func_status',
-            'recharge_switch',
-            'extract_time',
-            'balance_func_status',
-            'invoice_func_status',
-            'special_invoice_status',
-            'user_extract_bank_status',
-            'user_extract_wechat_status',
-            'user_extract_alipay_status',
-            'level_activate_status'
-        ]);
-        //看付费会员是否开启
-        $user['is_open_member'] = $user['svip_open'] = !!($configData['member_card_status'] ?? 0);
-        $user['agent_level_name'] = '';
-        //分销等级信息
-        if ($user['agent_level']) {
-            $levelInfo = $agentLevelServices->getLevelInfo((int)$user['agent_level'], 'id,name');
-            $user['agent_level_name'] = $levelInfo && $levelInfo['name'] ? $levelInfo['name'] : '';
-        }
-        $wechatUserInfo = $wechatUser->getOne(['uid' => $uid, 'user_type' => $tokenData['type']]);
-        $user['is_complete'] = $wechatUserInfo['is_complete'] ?? 0;
-        $user['couponCount'] = $storeCoupon->getUserValidCouponCount((int)$uid);
-        $user['like'] = $productRelation->getUserCount($uid, 0, 'like');
-        $collectCategory = sys_config('video_func_status', 1) ? '' : 'product';
-        $user['collectCount'] = $productRelation->getUserCount($uid, 0, 'collect', $collectCategory);
-        $user['orderStatusNum'] = $storeOrder->getOrderData($uid);
-        $user['notice'] = 0;
-        $user['recharge'] = $userMoneyServices->getRechargeSum($uid);//累计充值
-        $user['orderStatusSum'] = (float)$userMoneyServices->sum(['uid' => $uid, 'pm' => 0, 'status' => 1], 'number', true);
-        $user['extractTotalPrice'] = $userExtract->getExtractSum(['uid' => $uid, 'status' => 1]);//累计提现
-        $user['extractPrice'] = $user['brokerage_price'];//可提现
-        $user['statu'] = (int)($configData['store_brokerage_statu'] ?? 0);
-        $orderStatusSum = (float)$storeOrder->sum(['pid' => 0, 'paid' => 1, 'refund_status' => [0, 3], 'uid' => $user['uid'], 'is_del' => 0], 'pay_price', true);//累计有效消费
-        $user['spread_status'] = ($configData['brokerage_func_status'] ?? 1) && $this->checkUserPromoter($user['uid'], $user, $orderStatusSum);
-        if (!$user['is_promoter'] && $user['spread_status']) {
-            $this->dao->update($uid, ['is_promoter' => 1], 'uid');
-            $user['is_promoter'] = 1;
-        }
-        if ($user['statu'] == 3) {
-            $storeBrokeragePrice = $configData['store_brokerage_price'] ?? 0;
-            $user['promoter_price'] = bcsub((string)$storeBrokeragePrice, (string)$user['orderStatusSum'], 2);
-        }
-        /** @var UserBrokerageServices $userBrokerageServices */
-        $userBrokerageServices = app()->make(UserBrokerageServices::class);
-        $user['broken_commission'] = $userBrokerageServices->getUserFrozenPrice($uid);
-        if ($user['broken_commission'] < 0)
-            $user['broken_commission'] = 0;
-        $user['commissionCount'] = bcsub($user['brokerage_price'], $user['broken_commission'], 2);
-        if ($user['commissionCount'] < 0)
-            $user['commissionCount'] = 0;
-        //用户等级信息
-        $userLevelInfo = $userLevel->homeGetUserLevel((int)$user['uid'], $user);
-        $user = array_merge($user, $userLevelInfo);
-        $user['yesterDay'] = $userBrokerageServices->getUsersBokerageSum(['uid' => $uid, 'pm' => 1], 'yesterday');
-        $user['recharge_switch'] = (int)($configData['recharge_switch'] ?? 0);//充值开关
-        $user['adminid'] = $storeService->checkoutIsService(['uid' => $uid, 'status' => 1, 'customer' => 1]);
-        $user['broken_day'] = (int)($configData['extract_time'] ?? 0);//佣金冻结时间
-        $user['balance_func_status'] = (int)($configData['balance_func_status'] ?? 0);
-        $user['invioce_func'] = !!($configData['invoice_func_status'] ?? 0);
-        $user['special_invoice'] = $user['invioce_func'] && ($configData['special_invoice_status'] ?? 0);
-        $user['pay_vip_status'] = $user['is_ever_level'] || ($user['is_money_level'] && $user['overdue_time'] > time());
-        $user['member_style'] = (int)$diyServices->getColorChange('member');
-        if ($user['is_ever_level']) {
-            $user['vip_status'] = 1;//永久会员
-        } else {
-            if (!$user['is_money_level'] && $user['overdue_time'] && $user['overdue_time'] < time()) {
-                $user['vip_status'] = -1;//开通过已过期
-            } else if (!$user['overdue_time'] && !$user['is_money_level']) {
-                $user['vip_status'] = 2;//没有开通过
-            } else if ($user['is_money_level'] && $user['overdue_time'] && $user['overdue_time'] > time()) {
-                $user['vip_status'] = 3;//开通了,没有到期
-            }
-        }
-        /** @var StoreServiceRecordServices $servicesRecord */
-        $servicesRecord = app()->make(StoreServiceRecordServices::class);
-        $service_num = $servicesRecord->sum(['user_id' => $uid], 'mssage_num');
-        $message = $systemMessageServices->count(['uid' => $uid, 'look' => 0, 'is_del' => 0]);
-        $user['service_num'] = (int)bcadd((string)$service_num, (string)$message);
-        $user['is_agent_level'] = ($configData['brokerage_func_status'] ?? 1) && $agentLevelServices->count(['status' => 1, 'is_del' => 0]);
-        $user['visit_num'] = $storeProductLogServices->getDistinctCount(['uid' => $uid, 'type' => 'visit'], 'product_id');
-        $user['user_extract_bank_status'] = (int)($configData['user_extract_bank_status'] ?? 1);
-        $user['user_extract_wechat_status'] = (int)($configData['user_extract_wechat_status'] ?? 1);
-        $user['user_extract_alipay_status'] = (int)($configData['user_extract_alipay_status'] ?? 1);
-        //是否享受新人专享
-        /** @var StoreNewcomerServices $newcomerServices */
-        $newcomerServices = app()->make(StoreNewcomerServices::class);
-        $user['newcomer_status'] = $newcomerServices->checkUserNewcomer($uid);
-        $user['level_activate_status'] = $configData['level_activate_status'];
-        $user['member_func_status'] = $configData['member_func_status'];
-        $extendInfo = SystemConfigService::get('user_extend_info', []);
-        $user['register_extend_info'] = [];
-        if (!$user['level_activate_status']) {//不需要激活,用户激活状态默认为1
-            $user['level_status'] = 1;
-        }
-        if ($extendInfo) {
-            foreach ($extendInfo as $item) {
-                if (isset($item['use']) && $item['use'] && isset($item['user_show']) && $item['user_show']) $user['register_extend_info'][] = $item;
-            }
-        }
-        if (isset($user['extend_info']) && $user['extend_info']) {
-            $default = $this->defaultExtendInfo;
-            $params = array_column($default, 'param');
-            $sex = $this->rSex;
-            foreach ($user['extend_info'] as &$info) {
-                if (isset($info['param']) && in_array($info['param'], $params)) {
-                    if ($info['param'] == 'sex') {
-                        $info['value'] = $sex[$user['sex']] ?? 0;
-                    } elseif ($info['param'] == 'birthday') {
-                        $info['value'] = ($user['birthday'] ?? '') ? date('Y-m-d', $user['birthday']) : '';
-                    } elseif ($info['param'] == 'address') {
-                        $info['value'] = $user['addres'] ?? '';
-                    } else {
-                        $info['value'] = $user[$info['param']] ?? '';
-                    }
-                }
-            }
-        }
-//        /** @var UserAwardIntegralServices $award_integral_service */
-//        $award_integral_service = app()->make(UserAwardIntegralServices::class);
-//        $award_lack = $award_integral_service->getLake();
-//        $integral_price = $award_integral_service->getPrice();
-//        $static_integral = $award_integral_service->getIntegralSum(['status' => 0, 'type' => 0, 'uid' => $user['uid']]);
-//        $action_integral = $award_integral_service->getIntegralSum(['status' => 0, 'type' => 1, 'uid' => $user['uid']]);
-//        $sum_integral = $award_integral_service->getIntegralSum(['status' => 0]);
-        $hidden_integral = sys_config('hidden_integral', 0);
-        $user['is_default_avatar'] = $user['avatar'] == sys_config('h5_avatar') ? 1 : 0;
-//        $user['achievement'] = $award_integral_service->getAchievement($user['uid']);
-
-        /** @var AwardIntegralServices $award_integral_service */
-        $award_integral_service = app()->make(AwardIntegralServices::class);
-        $user['achievement'] = $award_integral_service->getAchievement($user['uid']);
-        $all_integral = $award_integral_service->sum(['uid' => $user['uid']], 'num');
-        $sent_integral = $award_integral_service->sum(['uid' => $user['uid']], 'sent_num');
-        $stand_integral = (float)bcsub($all_integral, $sent_integral, 2);
-        $extractable_integral = $award_integral_service->sum(['uid' => $user['uid']], 'extract_num');
-        $extracted_integral = $award_integral_service->sum(['uid' => $user['uid']], 'extracted_num');
-        $shop_integral_trade_commission = sys_config('shop_integral_trade_commission');//微信提现到账方式
-        $shop_integral_trade_switch = sys_config('shop_integral_trade_switch');//微信提现到账方式
-        return array_merge($user, compact('shop_integral_trade_commission', 'shop_integral_trade_switch', 'hidden_integral', 'all_integral', 'sent_integral', 'stand_integral', 'extractable_integral', 'extracted_integral'));
-    }
-
-    /**
-     * 用户资金统计
-     * @param int $uid `
-     */
-    public function balance(int $uid)
-    {
-        $userInfo = $this->getUserInfo($uid);
-        if (!$userInfo) {
-            throw new ValidateException('数据不存在');
-        }
-        /** @var UserMoneyServices $userMoneyServices */
-        $userMoneyServices = app()->make(UserMoneyServices::class);
-        /** @var StoreOrderServices $storeOrder */
-        $storeOrder = app()->make(StoreOrderServices::class);
-        $user['now_money'] = $userInfo['now_money'];//当前总资金
-        $user['recharge'] = $userMoneyServices->getRechargeSum($uid);//累计充值
-        $user['orderStatusSum'] = $storeOrder->sum(['pid' => 0, 'uid' => $uid, 'paid' => 1, 'is_del' => 0, 'refund_status' => [0, 3]], 'pay_price', true);//累计消费
-        return $user;
-    }
-
-    /**
-     * 用户修改信息
-     * @param Request $request
-     * @return mixed
-     */
-    public function eidtNickname(int $uid, array $data)
-    {
-        if (!$this->userExist($uid)) {
-            throw new ValidateException('用户不存在');
-        }
-        if (!$this->dao->update($uid, $data, 'uid')) {
-            throw new ValidateException('修改失败');
-        }
-        return true;
-    }
-
-    /**
-     * 获取推广人排行
-     * @param $data 查询条件
-     * @return array
-     * @throws DataNotFoundException
-     * @throws ModelNotFoundException
-     * @throws \think\exception\DbException
-     */
-    public function getRankList(array $data)
-    {
-        $startTime = $endTime = 0;
-        switch ($data['type']) {
-            case 'week':
-                $startTime = strtotime('this week Monday');
-                break;
-            case 'month':
-                $startTime = strtotime('first day of ' . date('F Y'));
-                break;
-        }
-        $endTime = time();
-        [$page, $limit] = $this->getPageValue();
-        $field = 'spread_uid,count(uid) AS count,spread_time';
-        /** @var UserSpreadServices $userSpreadServices */
-        $userSpreadServices = app()->make(UserSpreadServices::class);
-        $list = $userSpreadServices->getAgentRankList([$startTime, $endTime], $field, $page, $limit);
-        $rank = 0;
-        foreach ($list as $key => $item) {
-            if ($item['spread_uid'] == $data['uid']) $rank = $key + 1;
-        }
-        $week = $userSpreadServices->count(['spread_uid' => $data['uid'], 'time' => [strtotime('this week Monday'), time()], 'timeKey' => 'spread_time']);
-        $month = $userSpreadServices->count(['spread_uid' => $data['uid'], 'time' => [strtotime('last month'), time()], 'timeKey' => 'spread_time']);
-        $start = date('Y-m-d H:i', $startTime);
-        $end = date('Y-m-d H:i', time());
-        return compact('list', 'rank', 'week', 'month', 'start', 'end');
-    }
-
-    /**
-     * 静默绑定推广人
-     * @param Request $request
-     * @return mixed
-     */
-    public function spread(int $uid, int $spreadUid, $code)
-    {
-        $userInfo = $this->getUserInfo($uid);
-        if (!$userInfo) {
-            throw new ValidateException('数据不存在');
-        }
-        if ($code && !$spreadUid) {
-            /** @var QrcodeServices $qrCode */
-            $qrCode = app()->make(QrcodeServices::class);
-            if ($info = $qrCode->getOne(['id' => $code, 'status' => 1])) {
-                $spreadUid = $info['third_id'];
-            }
-        }
-        //记录好友关系
-        if ($spreadUid && $uid && $spreadUid != $uid) {
-            /** @var UserFriendsServices $serviceFriend */
-            $serviceFriend = app()->make(UserFriendsServices::class);
-            $serviceFriend->saveFriend($uid, $spreadUid);
-        }
-        $data = [];
-        //永久绑定
-        $store_brokergae_binding_status = sys_config('store_brokerage_binding_status', 1);
-        $spread_uid = isset($user['code']) && $user['code'] && $user['code'] != $userInfo->uid ? $user['code'] : ($userInfo['spread_uid'] ?? 0);
-        if ($userInfo->spread_uid && $store_brokergae_binding_status == 1) {
-            $data['login_type'] = $user['login_type'] ?? $userInfo->login_type;
-        } else {
-            //绑定分销关系 = 所有用户
-            if (sys_config('brokerage_bindind', 1) == 1) {
-                //分销绑定类型为时间段且过期 ||临时
-                $store_brokerage_binding_time = sys_config('store_brokerage_binding_time', 30);
-                if (!$userInfo['spread_uid'] || $store_brokergae_binding_status == 3 || ($store_brokergae_binding_status == 2 && ($userInfo['spread_time'] + $store_brokerage_binding_time * 24 * 3600) < time())) {
-                    $spreadUid = $spread_uid;
-                    if ($spreadUid && $userInfo->uid == $this->dao->value(['uid' => $spreadUid], 'spread_uid')) {
-                        $spreadUid = 0;
-                    }
-                    if ($spreadUid && $this->dao->get((int)$spreadUid)) {
-                        $data['spread_uid'] = $spreadUid;
-                        $data['spread_time'] = time();
-                    }
-                }
-            }
-        }
-        if ($data && !$this->dao->update($userInfo['uid'], $data, 'uid')) {
-            throw new ValidateException('修改信息失败');
-        }
-        if (isset($data['spread_uid']) && $data['spread_uid']) {
-            /** @var UserBillServices $userBill */
-            $userBill = app()->make(UserBillServices::class);
-            //邀请新用户增加经验
-            $userBill->inviteUserIncExp((int)$spreadUid);
-        }
-        return true;
-    }
-
-    /**
-     * 添加访问记录
-     * @param Request $request
-     * @return mixed
-     */
-    public function setVisit(array $data)
-    {
-        $userInfo = $this->getUserInfo($data['uid']);
-        if (!$userInfo) {
-            throw new ValidateException('数据不存在');
-        }
-        if (isset($data['ip']) && $data['ip']) {
-            $addressArr = $this->addressHandle($this->convertIp($data['ip']));
-            $data['province'] = $addressArr['province'] ?? '';
-        }
-        $data['channel_type'] = $userInfo['user_type'];
-        $data['add_time'] = time();
-        /** @var UserVisitServices $userVisit */
-        $userVisit = app()->make(UserVisitServices::class);
-        if ($userVisit->save($data)) {
-            return true;
-        } else {
-            throw new ValidateException('添加访问记录失败');
-        }
-    }
-
-    /**
-     * 获取活动状态
-     * @return mixed
-     */
-    public function activity()
-    {
-        /** @var StoreBargainServices $storeBragain */
-        $storeBragain = app()->make(StoreBargainServices::class);
-        /** @var StoreCombinationServices $storeCombinaion */
-        $storeCombinaion = app()->make(StoreCombinationServices::class);
-        /** @var StoreSeckillServices $storeSeckill */
-        $storeSeckill = app()->make(StoreSeckillServices::class);
-        $data['is_bargin'] = (bool)$storeBragain->validBargain();
-        $data['is_pink'] = (bool)$storeCombinaion->validCombination();
-        $data['is_seckill'] = (bool)$storeSeckill->getSeckillCount();
-        return $data;
-    }
-
-    /**
-     * 获取用户下级推广人
-     * @param int $uid 当前用户
-     * @param int $grade 等级  0  一级 1 二级
-     * @param string $orderBy 排序
-     * @param string $keyword
-     * @return array|bool
-     */
-    public function getUserSpreadGrade(int $uid = 0, $grade = 0, $orderBy = '', $keyword = '', $time = [])
-    {
-        $user = $this->getUserInfo($uid);
-        if (!$user) {
-            throw new ValidateException('数据不存在');
-        }
-        $spread_one_ids = $this->getUserSpredadUids($uid, 1);
-        $spread_two_ids = $this->getUserSpredadUids($uid, 2);
-        $data = [
-            'total' => count($spread_one_ids),
-            'totalLevel' => count($spread_two_ids),
-            'list' => []
-        ];
-        /** @var UserStoreOrderServices $userStoreOrder */
-        $userStoreOrder = app()->make(UserStoreOrderServices::class);
-        $list = [];
-        $where = ['pid' => 0, 'type' => 0, 'paid' => 1, 'refund_status' => [0, 3], 'is_del' => 0, 'is_system_del' => 0];
-        if ($grade == 0) {
-            if ($spread_one_ids) $list = $userStoreOrder->getUserSpreadCountList($spread_one_ids, $orderBy, $keyword, $time);
-            $where = $where + ['spread_uid' => $uid];
-        } else {
-            if ($spread_two_ids) $list = $userStoreOrder->getUserSpreadCountList($spread_two_ids, $orderBy, $keyword, $time);
-            $where = $where + ['spread_two_uid' => $uid];
-        }
-        foreach ($list as &$item) {
-            if (isset($item['spread_time']) && $item['spread_time']) {
-                $item['time'] = date('Y/m/d', $item['spread_time']);
-            }
-        }
-        $data['list'] = $list;
-        $data['brokerage_level'] = (int)sys_config('brokerage_level', 2);
-        $data['count'] = 0;
-        $data['price'] = 0;
-        if ($list) {
-            $uids = array_column($list, 'uid');
-            $data['count'] = count($uids);
-            /** @var StoreOrderServices $storeOrder */
-            $storeOrder = app()->make(StoreOrderServices::class);
-            $data['price'] = $storeOrder->sum($where, $grade == 0 ? 'one_brokerage' : 'two_brokerage');
-        }
-        return $data;
-    }
-
-    /**
-     * 获取推广人uids
-     * @param int $uid
-     * @param bool $one
-     * @return array
-     */
-    public function getUserSpredadUids(int $uid, int $type = 0)
-    {
-        $uids = $this->dao->getColumn(['spread_uid' => $uid], 'uid');
-        if ($type === 1) {
-            return $uids;
-        }
-        if ($uids) {
-            $uidsTwo = $this->dao->getColumn([['spread_uid', 'in', $uids]], 'uid');
-            if ($type === 2) {
-                return $uidsTwo;
-            }
-            if ($uidsTwo) {
-                $uids = array_merge($uids, $uidsTwo);
-            }
-        }
-        return $uids;
-    }
-
-    /**
-     * 检测用户是否是推广员
-     * @param int $uid
-     * @param array $user
-     * @param float $sumPrice
-     * @return bool
-     */
-    public function checkUserPromoter(int $uid, $user = [], float $sumPrice = 0.00)
-    {
-        if (!$uid) {
-            return false;
-        }
-        if (!$user) {
-            $user = $this->getUserInfo($uid);
-        }
-        if (!$user) {
-            return false;
-        }
-        //分销是否开启
-        if (!sys_config('brokerage_func_status')) {
-            return false;
-        }
-        //用户分校推广资格是否开启4.0.32
-        if (isset($user['spread_open']) && !$user['spread_open']) {
-            return false;
-        }
-        $store_brokerage_statu = sys_config('store_brokerage_statu');
-        if ($user['is_promoter'] || $store_brokerage_statu == 2) {
-            return true;
-        }
-        if ($store_brokerage_statu == 3) {
-            if (!$sumPrice) {
-                /** @var StoreOrderServices $storeOrder */
-                $storeOrder = app()->make(StoreOrderServices::class);
-                $sumPrice = $storeOrder->sum(['pid' => 0, 'uid' => $uid, 'paid' => 1, 'is_del' => 0, 'refund_status' => [0, 3]], 'pay_price');//累计消费
-            }
-            $store_brokerage_price = sys_config('store_brokerage_price');
-            if ($sumPrice >= $store_brokerage_price) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * 同步微信粉丝用户(后台接口)
-     * @return bool
-     */
-    public function syncWechatUsers()
-    {
-        $key = md5('sync_wechat_users');
-        //一天点击一次
-        if (CacheService::get($key)) {
-            return true;
-        }
-        $next_openid = null;
-        do {
-            $result = OfficialAccount::userService()->list($next_openid);
-            $userOpenids = $result['data'];
-            //拆分大数组
-            $opemidArr = array_chunk($userOpenids, 100);
-            foreach ($opemidArr as $openids) {
-                //加入同步|更新用户队列
-                UserJob::dispatch([$openids]);
-            }
-            $next_openid = $result['next_openid'];
-        } while ($next_openid != null);
-        CacheService::set($key, 1, 3600 * 24);
-        return true;
-    }
-
-    /**
-     * 导入微信粉丝用户
-     * @param array $openids
-     * @return bool
-     */
-    public function importUser(array $noBeOpenids)
-    {
-        if (!$noBeOpenids) {
-            return true;
-        }
-        $dataAll = $data = [];
-        $time = time();
-        foreach ($noBeOpenids as $openid) {
-            try {
-                $info = OfficialAccount::userService()->get($openid);
-                $info = is_object($info) ? $info->toArray() : $info;
-            } catch (\Throwable $e) {
-                $info = [];
-            }
-            if (!$info) continue;
-            if (($info['subscribe'] ?? 1) == 1) {
-                $data['nickname'] = $info['nickname'] ?? '';
-                $data['headimgurl'] = $info['headimgurl'] ?? '';
-                $userInfoData = $this->setUserInfo($data);
-                if (!$userInfoData) {
-                    throw new AdminException('用户信息储存失败!');
-                }
-                $data['uid'] = $userInfoData['uid'];
-                $data['subscribe'] = $info['subscribe'];
-                $data['unionid'] = $info['unionid'] ?? '';
-                $data['openid'] = $info['openid'] ?? '';
-                $data['sex'] = $info['sex'] ?? 0;
-                $data['language'] = $info['language'] ?? '';
-                $data['city'] = $info['city'] ?? '';
-                $data['province'] = $info['province'] ?? '';
-                $data['country'] = $info['country'] ?? '';
-                $data['subscribe_time'] = $info['subscribe_time'] ?? '';
-                $data['groupid'] = $info['groupid'] ?? 0;
-                $data['remark'] = $info['remark'] ?? '';
-                $data['tagid_list'] = isset($info['tagid_list']) && $info['tagid_list'] ? implode(',', $info['tagid_list']) : '';
-                $data['add_time'] = $time;
-                $data['is_complete'] = 1;
-                $dataAll[] = $data;
-            }
-        }
-        if ($dataAll) {
-            /** @var WechatUserServices $wechatUser */
-            $wechatUser = app()->make(WechatUserServices::class);
-            if (!$wechatUser->saveAll($dataAll)) {
-                throw new ValidateException('保存用户信息失败');
-            }
-        }
-        return true;
-    }
-
-    /**
-     * 修改会员的时间及是否会员状态
-     * @param int $vip_day 会员天数
-     * @param array $user_id 用户id
-     * @param int $is_money_level 会员来源途径
-     * @param bool $member_type 会员卡类型
-     * @return mixed
-     * @throws DataNotFoundException
-     * @throws DbException
-     * @throws ModelNotFoundException
-     */
-    public function setMemberOverdueTime($vip_day, int $user_id, int $is_money_level, $member_type = false)
-    {
-        if ($vip_day == 0) throw new ValidateException('天数不能为0');
-        $user_info = $this->getUserInfo($user_id);
-        if (!$user_info) throw new ValidateException('用户数据不存在');
-        if (!$member_type) $member_type = "month";
-        if ($member_type == 'ever') {
-            $overdue_time = 0;
-            $is_ever_level = 1;
-        } else {
-            if ($user_info['is_money_level'] == 0) {
-                $overdue_time = bcadd(bcmul($vip_day, 86400, 0), time(), 0);
-            } else {
-                $overdue_time = bcadd(bcmul($vip_day, 86400, 0), $user_info['overdue_time'], 0);
-            }
-            $is_ever_level = 0;
-        }
-        $setData['overdue_time'] = $overdue_time;
-        $setData['is_ever_level'] = $is_ever_level;
-        $setData['is_money_level'] = $is_money_level ? $is_money_level : 0;
-        // if ($user_info['level'] == 0) $setData['level'] = 1;
-        return $this->dao->update(['uid' => $user_id], $setData);
-    }
-
-    /**
-     * 清空到期svip(分批加入队列)
-     * @return bool
-     */
-    public function offUserSvip()
-    {
-        $users = $this->dao->getColumn([['is_ever_level', '=', 0], ['is_money_level', '>', 0], ['overdue_time', '<', time()]], 'uid');
-        if ($users) {
-            //拆分大数组
-            $uidsArr = array_chunk($users, 100);
-            foreach ($uidsArr as $uids) {
-                //加入同步|更新用户队列
-                UserSvipJob::dispatch([$uids]);
-            }
-        }
-        return true;
-    }
-
-    /**
-     * 会员过期改变状态,变为普通会员
-     * @param $uid
-     * @param null $userInfo
-     * @return bool
-     * @throws DataNotFoundException
-     * @throws DbException
-     * @throws ModelNotFoundException
-     */
-    public function offMemberLevel($uid, $userInfo = null)
-    {
-        if (!$uid) return false;
-        $userInfo = $userInfo ?: $this->dao->get($uid);
-        if (!$userInfo) return false;
-        if ($userInfo['is_ever_level'] == 0 && $userInfo['is_money_level'] > 0 && $userInfo['overdue_time'] < time()) {
-            $this->dao->update(['uid' => $uid], ['is_money_level' => 0]);
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * @param array $where
-     * @return array
-     * @throws DataNotFoundException
-     * @throws DbException
-     * @throws ModelNotFoundException
-     */
-    public function getUserInfoList(array $where, $field = "*")
-    {
-        return $this->dao->getUserInfoList($where, $field);
-    }
-
-    /**
-     * 保存用户上级推广人
-     * @param int $uid
-     * @param int $spread_uid
-     * @return bool
-     */
-    public function saveUserSpreadUid(int $uid, int $spread_uid)
-    {
-        if (!$uid || !$spread_uid) {
-            return false;
-        }
-        if ($uid == $spread_uid) {
-            throw new ValidateException('上级推广人不能为自己');
-        }
-        $userInfo = $this->getUserInfo($uid);
-        if (!$userInfo) {
-            throw new ValidateException('用户不存在');
-        }
-        //上级已经是这个uid
-        if ($userInfo['spread_uid'] == $spread_uid) {
-            return true;
-        }
-        $spreadInfo = $this->getUserInfo($spread_uid);
-        if (!$spreadInfo) {
-            throw new ValidateException('上级用户不存在');
-        }
-        if ($spreadInfo['spread_uid'] == $uid) {
-            throw new ValidateException('上级推广人不能为自己下级');
-        }
-        $data = ['spread_uid' => $spread_uid, 'spread_time' => time()];
-        $this->dao->update($uid, $data);
-        //记录推广绑定关系
-        UserSpreadJob::dispatch([$uid, $spread_uid]);
-        //记录好友关系
-        UserFriendsJob::dispatch([$uid, $spread_uid]);
-        return true;
-    }
-
-    /**
-     * 增加推广用户佣金
-     * @param int $uid
-     * @param int $spread_uid
-     * @param array $userInfo
-     * @param array $spread_user
-     * @return bool|mixed
-     * @throws DataNotFoundException
-     * @throws DbException
-     * @throws ModelNotFoundException
-     */
-    public function addBrokeragePrice(int $uid, int $spread_uid, array $userInfo = [], array $spread_user = [])
-    {
-        if (!$uid || !$spread_uid) {
-            return false;
-        }
-        //商城分销功能是否开启 0关闭1开启
-        if (!sys_config('brokerage_func_status')) return true;
-        //获取设置推广佣金单价
-        $brokerage_price = sys_config('uni_brokerage_price', 0);
-        //推广佣金是否开启
-        if (!sys_config('brokerage_user_status', 0)) {
-            return true;
-        }
-        //获取推广佣金当日限额
-        $day_brokerage_price_upper = sys_config('day_brokerage_price_upper', 0);
-        if (!floatval($brokerage_price) || !floatval($day_brokerage_price_upper)) {
-            return true;
-        }
-        if (!$userInfo) {
-            $userInfo = $this->getUserInfo($uid);
-        }
-        if (!$userInfo) {
-            return false;
-        }
-        if (!$spread_user) {
-            $spread_user = $this->dao->getOne(['uid' => $spread_uid, 'status' => 1]);
-        }
-        if (!$spread_user) {
-            return false;
-        }
-        if (!$this->checkUserPromoter($spread_uid, $spread_user)) {
-            return false;
-        }
-        /** @var UserBrokerageServices $userBrokerageServices */
-        $userBrokerageServices = app()->make(UserBrokerageServices::class);
-        // -1不限制
-        if ($day_brokerage_price_upper != -1) {
-            if ($day_brokerage_price_upper <= 0) {
-                return true;
-            } else {
-                //获取上级用户今日获取推广用户佣金
-                $spread_day_brokerage = $userBrokerageServices->getUserBillBrokerageSum($spread_uid, ['brokerage_user'], 'today');
-                //超过上限
-                if (($spread_day_brokerage + $brokerage_price) > $day_brokerage_price_upper) {
-                    return true;
-                }
-            }
-        }
-        $spreadPrice = $spread_user['brokerage_price'];
-        // 上级推广员返佣之后的金额
-        $balance = bcadd($spreadPrice, $brokerage_price, 2);
-        return $this->transaction(function () use ($uid, $spread_uid, $brokerage_price, $userInfo, $balance, $userBrokerageServices) {
-            // 添加返佣记录
-            $res1 = $userBrokerageServices->income('get_user_brokerage', $spread_uid, [
-                'nickname' => $userInfo['nickname'],
-                'number' => floatval($brokerage_price)
-            ], $balance, $uid);
-            // 添加用户余额
-            $res2 = $this->dao->bcInc($spread_uid, 'brokerage_price', $brokerage_price, 'uid');
-            //给上级发送获得佣金的模板消息
-            /** @var StoreOrderTakeServices $storeOrderTakeServices */
-            $storeOrderTakeServices = app()->make(StoreOrderTakeServices::class);
-            $storeOrderTakeServices->sendBackOrderBrokerage([], $spread_uid, $brokerage_price, 'user');
-            return $res1 && $res2;
-        });
-    }
-
-    /**
-     * 获取上级uid
-     * @param int $uid
-     * @param array $userInfo
-     * @param bool $is_spread
-     * @return int|mixed
-     */
-    public function getSpreadUid(int $uid, $userInfo = [], $is_spread = true)
-    {
-        if (!$uid) {
-            return 0;
-        }
-        //商城分销功能是否开启 0关闭1开启
-        if (!sys_config('brokerage_func_status')) return -1;
-        if (!$userInfo) {
-            $userInfo = $this->getUserCacheInfo($uid);
-        }
-        if (!$userInfo) {
-            return 0;
-        }
-        //上级的上级不需要检测自购
-        if ($is_spread) {
-            //开启自购
-            $is_self_brokerage = sys_config('is_self_brokerage', 0);
-            if ($is_self_brokerage && $is_spread) {
-                return $uid;
-            }
-        }
-        //绑定类型
-        $store_brokergae_binding_status = sys_config('store_brokerage_binding_status', 1);
-        if ($store_brokergae_binding_status == 1 || $store_brokergae_binding_status == 3) {
-            return $userInfo['spread_uid'];
-        }
-        //分销绑定类型为时间段且没过期
-        $store_brokerage_binding_time = sys_config('store_brokerage_binding_time', 30);
-        if ($store_brokergae_binding_status == 2 && ($userInfo['spread_time'] + $store_brokerage_binding_time * 24 * 3600) > time()) {
-            return $userInfo['spread_uid'];
-        }
-        return -1;
-    }
-
-    /**
-     * 用户付款code
-     * @param int $uid
-     * @return bool|mixed|null
-     */
-    public function getRandCode(int $uid)
-    {
-        $key = 'user_rand_code' . $uid;
-        return CacheService::redisHandler()->remember($key, function () {
-            return substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 9), 1))), 0, 3) . str_pad((string)mt_rand(1, 999), 3, '0', STR_PAD_LEFT);
-        }, 600);
-    }
-
-    /**
-     * 获取barcode
-     * @return bool|int|mixed|null
-     */
-    public function getBarCode()
-    {
-        mt_srand();
-        $code = substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 9), 1))), 0, 4) . str_pad((string)mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
-        if (!$this->dao->count(['bar_code' => $code])) {
-            return $code;
-        } else {
-            return $this->getBarCode();
-        }
-    }
-
-    /**
-     * 获取用户推广用户列表
-     * @param $uid
-     * @param $type
-     * @return array
-     * @throws DataNotFoundException
-     * @throws DbException
-     * @throws ModelNotFoundException
-     */
-    public function agentUserList($uid, $type)
-    {
-        $where['spread_uid'] = $uid;
-        if ($type == 1) {
-            $where['pay_count'] = -1;
-        }
-        [$page, $limit] = $this->getPageValue();
-        $list = $this->dao->getList($where, 'uid,nickname,avatar,FROM_UNIXTIME(spread_time, \'%Y.%m.%d %H:%m\') as spread_time', $page, $limit);
-        $count = $this->dao->count($where);
-        return compact('list', 'count');
-    }
-
-    /**
-     * 个人中心
-     * @param $uid
-     * @return array|mixed
-     */
-    public function bankInfo($uid)
-    {
-        $userService = app()->make(UserServices::class);
-        $user = $userService->getUserInfo($uid);
-        if (!$user) {
-            throw new ValidateException('数据不存在');
-        }
-        if (!$user['enterprise_professional_facilitator_id']) {
-            return [];
-        }
-        return WithdrawService::init()::contractInfo($user['enterprise_professional_facilitator_id']);
-    }
-
-
-    public function cidUser($rname, $cid, $uid)
-    {
-        //找出出生年月日
-        $time = substr($cid, 6, 4) . '-' . substr($cid, 10, 2) . '-' . substr($cid, 12, 2);
-        $brithday = strtotime($time);
-        $rust = $this->update($uid, ['real_name' => $rname, 'card_id' => $cid, 'is_auth' => 1, 'off' => '', 'birthday' => $brithday], 'uid');
-
-        if ($rust)
-            return true;
-        else
-            return false;
-    }
-
 
     /**
      * TODO 获取推广人数 一级
      * @param int $uid
      * @return bool|int|string
+     * @throws DbException
      */
     public function getSpreadCount($uid = 0)
     {

+ 44 - 44
app/services/wechat/MessageServices.php

@@ -167,40 +167,40 @@ class MessageServices extends BaseServices
                     $response = $e->getMessage();
                 }
                 break;
-			case 'wechatqrcode'://渠道码
-				/** @var WechatQrcodeServices $wechatQrcodeService */
-				$wechatQrcodeService = app()->make(WechatQrcodeServices::class);
-				/** @var WechatUserServices $wechatUser */
-				$wechatUser = app()->make(WechatUserServices::class);
-				/** @var UserServices $userService */
-				$userService = app()->make(UserServices::class);
-				/** @var LoginServices $loginService */
-				$loginService = app()->make(LoginServices::class);
-				try {
-					//wechatqrcode类型的二维码数据中,third_id为渠道码的id
-					$qrcodeInfo = $wechatQrcodeService->qrcodeInfo($qrInfo['third_id']);
-					$spreadUid = $qrcodeInfo['uid'];
-					$spreadInfo = $userService->get($spreadUid);
-					$is_new = $wechatUser->saveUser($openid);
-					$uid = $wechatUser->getFieldValue($openid, 'openid', 'uid', ['user_type', '<>', 'h5']);
-					$userInfo = $userService->get($uid);
+            case 'wechatqrcode'://渠道码
+                /** @var WechatQrcodeServices $wechatQrcodeService */
+                $wechatQrcodeService = app()->make(WechatQrcodeServices::class);
+                /** @var WechatUserServices $wechatUser */
+                $wechatUser = app()->make(WechatUserServices::class);
+                /** @var UserServices $userService */
+                $userService = app()->make(UserServices::class);
+                /** @var LoginServices $loginService */
+                $loginService = app()->make(LoginServices::class);
+                try {
+                    //wechatqrcode类型的二维码数据中,third_id为渠道码的id
+                    $qrcodeInfo = $wechatQrcodeService->qrcodeInfo($qrInfo['third_id']);
+                    $spreadUid = $qrcodeInfo['uid'];
+                    $spreadInfo = $userService->get($spreadUid);
+                    $is_new = $wechatUser->saveUser($openid);
+                    $uid = $wechatUser->getFieldValue($openid, 'openid', 'uid', ['user_type', '<>', 'h5']);
+                    $userInfo = $userService->get($uid);
 
-					if ($qrcodeInfo['status'] == 0 || $qrcodeInfo['is_del'] == 1 || ($qrcodeInfo['end_time'] < time() && $qrcodeInfo['end_time'] > 0)) {
-						$response = '二维码已失效';
-					} else if ($spreadUid == $uid) {
-						$response = '自己不能推荐自己';
-					} else if (!$userInfo) {
-						$response = '用户不存在';
-					} else if (!$spreadInfo) {
-						$response = '上级用户不存在';
-					} else if ($loginService->updateUserInfo(['code' => $spreadUid], $userInfo, $is_new)) {
-						//写入扫码记录,返回内容
-						$response = $wechatQrcodeService->wechatQrcodeRecord($qrcodeInfo, $userInfo, $spreadInfo, 1);
-					}
-				} catch (\Exception $e) {
-					$response = $e->getMessage();
-				}
-				break;
+                    if ($qrcodeInfo['status'] == 0 || $qrcodeInfo['is_del'] == 1 || ($qrcodeInfo['end_time'] < time() && $qrcodeInfo['end_time'] > 0)) {
+                        $response = '二维码已失效';
+                    } else if ($spreadUid == $uid) {
+                        $response = '自己不能推荐自己';
+                    } else if (!$userInfo) {
+                        $response = '用户不存在';
+                    } else if (!$spreadInfo) {
+                        $response = '上级用户不存在';
+                    } else if ($loginService->updateUserInfo(['code' => $spreadUid], $userInfo, $is_new)) {
+                        //写入扫码记录,返回内容
+                        $response = $wechatQrcodeService->wechatQrcodeRecord($qrcodeInfo, $userInfo, $spreadInfo, 1);
+                    }
+                } catch (\Exception $e) {
+                    $response = $e->getMessage();
+                }
+                break;
         }
         return $response;
     }
@@ -250,7 +250,7 @@ class MessageServices extends BaseServices
         /** @var LoginServices $loginService */
         $loginService = app()->make(LoginServices::class);
 
-		$qrInfo = [];
+        $qrInfo = [];
         $response = $wechatReplyService->reply('subscribe', $message['FromUserName']);
         if ($message['EventKey'] && ($qrInfo = $qrcodeService->getQrcode($message['Ticket'], 'ticket'))) {
             $qrcodeService->scanQrcode($message['Ticket'], 'ticket');
@@ -335,16 +335,16 @@ class MessageServices extends BaseServices
                 $response = $this->wechatEvent($qrInfo, $message['FromUserName']);
             }
         }
-		//是否开启
-		if (sys_config('create_wechat_user', 1)) {
-			try {
-				/** @var WechatUserServices $wechatUserSerives */
-				$wechatUserSerives = app()->make(WechatUserServices::class);
-				$wechatUserSerives->saveUser($message['FromUserName'], $spread_uid);
-			} catch (\Throwable $e) {
-				Log::error('关注公众号生成用户失败,原因:' . $e->getMessage() . $e->getFile() . $e->getLine());
-			}
-		}
+        //是否开启
+        if (sys_config('create_wechat_user', 1)) {
+            try {
+                /** @var WechatUserServices $wechatUserSerives */
+                $wechatUserSerives = app()->make(WechatUserServices::class);
+                $wechatUserSerives->saveUser($message['FromUserName'], $spread_uid);
+            } catch (\Throwable $e) {
+                Log::error('关注公众号生成用户失败,原因:' . $e->getMessage() . $e->getFile() . $e->getLine());
+            }
+        }
         return $response;
     }
 

+ 1 - 0
app/services/wechat/RoutineServices.php

@@ -12,6 +12,7 @@ declare (strict_types=1);
 
 namespace app\services\wechat;
 
+use app\services\wechat\WechatUserServices;
 use app\services\wechat\WechatUserServices;
 use qiniu\basic\BaseServices;
 use app\model\wechat\WechatUser;

+ 5 - 3
app/services/wechat/WechatUserServices.php

@@ -12,6 +12,9 @@ declare (strict_types=1);
 
 namespace app\services\wechat;
 
+use app\services\user\LoginServices;
+use app\services\user\UserServices;
+use app\services\user\UserSpreadServices;
 use qiniu\basic\BaseServices;
 use app\model\wechat\WechatUser;
 use qiniu\exceptions\AdminException;
@@ -63,15 +66,14 @@ class WechatUserServices extends BaseServices
     /**
      * 用uid获得 微信openid
      * @param int $uid
-     * @param string $userType
      * @return mixed
      * @throws DataNotFoundException
      * @throws DbException
      * @throws ModelNotFoundException
      */
-    public function uidToOpenid(int $uid, string $userType = 'wechat')
+    public function uidToOpenid(int $uid)
     {
-        return $this->getOne(['uid' => $uid, 'user_type' => $userType])['openid'] ?? null;
+        return $this->getOne(['uid' => $uid])['openid'] ?? null;
     }
 
 

+ 72 - 0
app/validate/admin/system/store/SystemStoreValidate.php

@@ -0,0 +1,72 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+namespace app\validate\admin\system\store;
+
+use think\Validate;
+
+/**
+ * 门店验证器
+ * Class SystemStoreValidate
+ * @package app\validate\admin\system\store
+ */
+class SystemStoreValidate extends Validate
+{
+    /**
+     * 验证规则
+     * @var array
+     */
+    protected $rule = [
+        'name' => 'require',
+        'introduction' => 'require',
+        'phone' => ['require', 'mobile'],
+        'address' => 'require',
+        'detailed_address' => 'require',
+        'longitude' => 'require',
+        'latitude' => 'require',
+        'store_account' => ['require', 'length:4,64'],
+        'true_password' => ['require', 'length:4,64'],
+        'store_password' => ['require', 'length:4,64'],
+
+    ];
+    /**
+     * 定义错误信息
+     * 格式:'字段名.规则名'    =>    '错误信息'
+     *
+     * @var array
+     */
+    protected $message = [
+        'name.require' => '请填写门店名称',
+        'introduction.require' => '请填写门店简介',
+        'phone.require' => '请填写门店电话',
+        'phone.mobile' => '手机号格式不正确',
+        'address.require' => '请选择地址',
+        'detailed_address.require' => '请填写详细地址',
+        'longitude.require' => '请选择经纬度',
+        'latitude.require' => '请选择经纬度',
+        'store_account.require' => '请填写门店管理员账号',
+        'store_account.length' => '门店管理员账号长度4-64位字符',
+        'true_password.require' => '请填写门店管理员确认密码',
+        'true_password.length' => '门店管理员确认密码长度4-64位字符',
+        'store_password.require' => '请填写门店管理员密码',
+        'store_password.length' => '门店管理员密码长度4-64位字符',
+        'uid.require' => '请选择关联用户',
+    ];
+
+    protected $scene = [
+        'reset' => ['store_account', 'true_password', 'store_password'],
+        'save' => ['name', 'phone', 'address', 'detailed_address', 'longitude', 'latitude', 'store_account', 'store_password', 'uid'],
+        'update' => ['name', 'phone', 'address', 'detailed_address', 'longitude', 'latitude', 'uid'],
+    ];
+
+
+    public function allScene()
+    {
+        return array_keys($this->scene);
+    }
+}

+ 52 - 0
app/validate/admin/user/UserBankValidate.php

@@ -0,0 +1,52 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+namespace app\validate\admin\user;
+
+use think\Validate;
+
+/**
+ * 收款方式验证器
+ * Class UserBankValidate
+ * @package app\validate\admin\user
+ */
+class UserBankValidate extends Validate
+{
+    /**
+     * 验证规则
+     * @var array
+     */
+    protected $rule = [
+        'uid' => 'require|number',
+        'type' => 'require|in:0,1,2',
+        'phone' => 'mobile',
+        'default' => 'number'
+    ];
+
+    /**
+     * 错误信息
+     * @var array
+     */
+    protected $message = [
+        'uid.require' => '用户ID是必需的',
+        'uid.number' => '用户ID必须是整数',
+        'type.require' => '提现方式是必需的',
+        'type.in' => '请选择正确的提现方式',
+        'phone.mobile' => '手机号码不是有效的手机号码',
+        'default.number' => '是否默认必须是整数'
+    ];
+
+    protected $scene = [];
+
+
+
+    public function allScene()
+    {
+        return array_keys($this->scene);
+    }
+}

+ 62 - 0
app/validate/admin/user/UserExtractValidate.php

@@ -0,0 +1,62 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @Powered by Kirin
+ * @Version 1.0.0
+ * @Qiniu.TaiZhou.Co
+ */
+
+namespace app\validate\admin\user;
+
+use think\Validate;
+
+/**
+ * 用户提现验证器
+ * Class UserExtractValidate
+ * @package app\validate\admin\user
+ */
+class UserExtractValidate extends Validate
+{
+    /**
+     * 验证规则
+     * @var array
+     */
+    protected $rule = [
+        'uid' => 'number|egt:0',
+        'real_name' => 'require',
+        'extract_type' => 'in:0,1,2',
+        'extract_price' => 'float|egt:0',
+        'extract_fee' => 'float|egt:0',
+        'balance' => 'float|egt:0',
+        'mark' => 'require',
+        'status' => 'in:-1,0,1',
+    ];
+
+    /**
+     * 错误信息
+     * @var array
+     */
+    protected $message = [
+        'uid.number' => '用户必须是整数',
+        'uid.egt' => '用户大于等于0',
+        'real_name.require' => '名称是必需的',
+        'extract_type.in' => '请选择正确的提现方式',
+        'extract_price.float' => '提现金额必须是数字',
+        'extract_price.egt' => '提现金额大于等于0',
+        'extract_fee.float' => '手续费金额必须是数字',
+        'extract_fee.egt' => '手续费金额大于等于0',
+        'balance.float' => '提现后余额必须是数字',
+        'balance.egt' => '提现后余额大于等于0',
+        'mark.require' => '备注是必需的',
+        'status.in' => '请选择正确的状态',
+    ];
+
+    protected $scene = [];
+
+
+
+    public function allScene()
+    {
+        return array_keys($this->scene);
+    }
+}

+ 1 - 1
app/validate/api/LoginValidate.php

@@ -36,7 +36,7 @@ class LoginValidate extends Validate
         'account.alphaDash' => '账号应为数字、字母',
         'account.length' => '账号长度6-64位字符',
         'pwd.require' => '请输入密码',
-		'pwd.length' => '密码长度6-64位字符',
+        'pwd.length' => '密码长度6-64位字符',
     ];
 
     protected $scene = [

+ 2 - 2
app/validate/api/user/RegisterValidates.php

@@ -25,7 +25,7 @@ class RegisterValidates extends Validate
     protected $rule = [
         'phone' => 'require|regex:phone',
         'captcha' => 'require|length:6',
-        'password' => 'require|check_password',
+        'password' => 'require|regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{6,18}$/',
     ];
 
     protected $message = [
@@ -34,7 +34,7 @@ class RegisterValidates extends Validate
         'captcha.require' => '验证码必须填写',
         'captcha.length' => '验证码长度不正确',
         'password.require' => '密码必须填写',
-        'password.check_password' => '至少6位,最多18位,包含大小写字母、数字和特殊字符',
+        'password.regex' => '密码至少6位,最多18位,包含大小写字母、数字和特殊字符',
     ];
 
 

+ 7 - 210
app/webscoket/BaseHandler.php

@@ -56,7 +56,7 @@ abstract class BaseHandler
     /**
      * 事件入口
      * @param $event
-     * @return |null
+     * @return null |null
      */
     public function handle($event)
     {
@@ -66,7 +66,7 @@ abstract class BaseHandler
         $this->fd = array_shift($result);
         $this->formType = array_shift($result);
         if (method_exists($this, $method)) {
-            if (($method == 'login' || $method == 'kefu_login') && is_string($result[0])) {
+            if ($method == 'login' && is_string($result[0])) {
                 $result[0] = ['token' => $result[0]];
             }
             return $this->{$method}(...$result);
@@ -80,212 +80,15 @@ abstract class BaseHandler
      * 聊天事件
      * @param array $data
      * @param Response $response
-     * @return bool|\think\response\Json|null
-     * @throws \think\db\exception\DataNotFoundException
-     * @throws \think\db\exception\DbException
-     * @throws \think\db\exception\ModelNotFoundException
      */
-    public function chat(array $data = [], Response $response)
-    {
-        $user = $this->room->get($this->fd);
-        if (!$user) {
-            return $response->fail('聊天用户已下线');
-        }
-        $to_uid = $data['to_uid'] ?? 0;
-        $msn_type = $data['type'] ?? 0;
-        $msn = $data['msn'] ?? '';
-        $formType = $this->formType ?? null;
-        //是否为游客
-        $isTourist = $data['is_tourist'] ?? 0;
-        $tourist_uid = $data['tourist_uid'] ?? 0;
-        $isTourist = $isTourist && $tourist_uid;
-        $tourist_avatar = $data['tourist_avatar'] ?? '';
-        $uid = $isTourist ? $tourist_uid : $user['uid'];
-        if (!$to_uid) {
-            return $response->message('err_tip', ['msg' => '用户已下线']);
-        }
-        if ($to_uid == $uid) {
-            return $response->message('err_tip', ['msg' => '不能和自己聊天']);
-        }
-
-        /** @var StoreServiceLogServices $logServices */
-        $logServices = app()->make(StoreServiceLogServices::class);
-        if (!in_array($msn_type, StoreServiceLogServices::MSN_TYPE)) {
-            return $response->message('err_tip', ['msg' => '格式错误']);
-        }
-        $msn = trim(strip_tags(str_replace(["\n", "\t", "\r", "&nbsp;"], '', htmlspecialchars_decode($msn))));
-        $data = compact('to_uid', 'msn_type', 'msn', 'uid');
-        $data['add_time'] = time();
-        $data['is_tourist'] = $data['is_tourist'] ?? 0;
-
-        //获取收消息人的所有fd信息
-        $toUserFd = $this->manager->userFd($user['type'] == 2 ? 1 : 2, $to_uid);
-        $toUser = ['to_uid' => -1];
-        $fremaData = [];
-        foreach ($toUserFd as $value) {
-            if ($frem = $this->room->get($value)) {
-                $fremaData[] = $frem;
-                //如果当收消息人在和当前发消息人对话中
-                if ($frem['to_uid'] == $user['uid']) {
-                    $toUser = $frem;
-                }
-            }
-        }
-        //是否在线
-        //是否和当前用户对话
-        $online = $toUserFd && $toUser && $toUser['to_uid'] !== -1;
-
-        $data['type'] = $online ? 1 : 0;
-        $data = $logServices->save($data);
-        $data = $data->toArray();
-        $data['_add_time'] = $data['add_time'];
-        $data['add_time'] = strtotime($data['add_time']);
-        $_userInfo = [];
-        if (!$isTourist) {
-            /** @var StoreServiceServices $userService */
-            $userService = app()->make(StoreServiceServices::class);
-            $_userInfo = $userService->get(['uid' => $data['uid']], ['nickname', 'avatar']);
-            if (!$_userInfo) {
-                /** @var UserServices $userService */
-                $userService = app()->make(UserServices::class);
-                $_userInfo = $userService->getUserInfo($data['uid'], 'nickname,avatar');
-            }
-        }
-        if ($isTourist || !$_userInfo) {
-            $avatar = sys_config('tourist_avatar');
-            $_userInfo['avatar'] = $tourist_avatar ? $tourist_avatar : Arr::getArrayRandKey(is_array($avatar) ? $avatar : []);
-            $_userInfo['nickname'] = '游客' . $uid;
-
-        }
-        $data['nickname'] = $_userInfo['nickname'];
-        $data['avatar'] = $_userInfo['avatar'];
-
-        //商品消息类型
-        $data['productInfo'] = [];
-        if ($msn_type == StoreServiceLogServices::MSN_TYPE_GOODS && $msn) {
-            /** @var StoreProductServices $productServices */
-            $productServices = app()->make(StoreProductServices::class);
-            $productInfo = $productServices->getProductInfo((int)$msn, 'store_name,IFNULL(sales,0) + IFNULL(ficti,0) as sales,image,slider_image,price,vip_price,ot_price,stock,id');
-            $data['productInfo'] = $productInfo ? $productInfo->toArray() : [];
-        }
-        //订单消息类型
-        $data['orderInfo'] = [];
-        if ($msn_type == StoreServiceLogServices::MSN_TYPE_ORDER && $msn) {
-            /** @var StoreOrderServices $orderServices */
-            $orderServices = app()->make(StoreOrderServices::class);
-            $order = $orderServices->getUserOrderDetail($msn, $uid);
-            if ($order) {
-                $order = $orderServices->tidyOrder($order->toArray(), true, true);
-                $order['add_time_y'] = date('Y-m-d', $order['add_time']);
-                $order['add_time_h'] = date('H:i:s', $order['add_time']);
-                $data['orderInfo'] = $order;
-            }
-        }
-        if ($msn_type == StoreServiceLogServices::MSN_TYPE_REFUND_ORDER && $msn) {
-            /** @var StoreOrderRefundServices $orderRefundServices */
-            $orderRefundServices = app()->make(StoreOrderRefundServices::class);
-            $order = $orderRefundServices->refundDetail($msn);
-            if ($order) {
-                $order['add_time_y'] = date('Y-m-d', $order['add_time']);
-                $order['add_time_h'] = date('H:i:s', $order['add_time']);
-                $data['orderInfo'] = $order;
-            }
-        }
-
-        //用户向客服发送消息,判断当前客服是否在登录中
-        /** @var StoreServiceRecordServices $serviceRecored */
-        $serviceRecored = app()->make(StoreServiceRecordServices::class);
-        $unMessagesCount = $logServices->getMessageNum(['uid' => $uid, 'to_uid' => $to_uid, 'type' => 0, 'is_tourist' => $isTourist ? 1 : 0]);
-        //记录当前用户和他人聊天记录
-        $data['recored'] = $serviceRecored->saveRecord($uid, $to_uid, $msn, $formType ?? 0, $msn_type, $unMessagesCount, $isTourist, $data['nickname'], $data['avatar']);
-        //是否在线
-        if ($online) {
-            $this->manager->pushing($toUserFd, $response->message('reply', $data)->getData());
-        } else {
-            //用户在线,可是没有和当前用户进行聊天,给当前用户发送未读条数
-            if ($toUserFd && $toUser && isset($toUser['to_uid']) && $toUser['to_uid'] != $uid) {
-                $data['recored']['nickname'] = $_userInfo['nickname'];
-                $data['recored']['avatar'] = $_userInfo['avatar'];
-
-                $this->manager->pushing($toUserFd, $response->message('mssage_num', [
-                    'uid' => $uid,
-                    'num' => $unMessagesCount,
-                    'recored' => $data['recored']
-                ])->getData());
-
-            }
-            if (!$isTourist) {
-                //用户不在线
-                /** @var WechatUserServices $wechatUserServices */
-                $wechatUserServices = app()->make(WechatUserServices::class);
-                $userInfo = $wechatUserServices->getOne(['uid' => $to_uid, 'user_type' => 'wechat'], 'nickname,subscribe,openid,headimgurl');
-                if ($userInfo && $userInfo['subscribe'] && $userInfo['openid']) {
-                    $description = '您有新的消息,请注意查收!';
-                    if ($formType !== null) {
-                        $head = '客服接待消息提醒';
-                        $url = sys_config('site_url') . '/kefu/mobile_chat?toUid=' . $uid . '&nickname=' . $_userInfo['nickname'];
-                    } else {
-                        $head = '客服回复消息提醒';
-                        $url = sys_config('site_url') . '/pages/extension/customer_list/chat?uid=' . $uid;
-                    }
-                    $message = Messages::newsMessage($head, $description, $url, $_userInfo['avatar']);
-                    $userInfo = $userInfo->toArray();
-                    try {
-                        OfficialAccount::staffService()->message($message)->to($userInfo['openid'])->send();
-                    } catch (\Exception $e) {
-
-                        if ($msn_type == 3) {
-                            $msn = '[图片]';
-                        } elseif ($msn_type == 4) {
-                            $msn = '[语音]';
-                        } elseif ($msn_type == 5) {
-                            $msn = '[商品]';
-                        } elseif ($msn_type == 6) {
-                            $msn = '[订单]';
-                        } elseif ($msn_type == 7) {
-                            $msn = '[退款订单]';
-                        }
-
-//                        $res = WechatTemplateJob::dispatchDo('sendServiceNoticeNew', [$userInfo['openid'], [
-//                            'first' => $head,
-//                            'keyword1' => $formType !== null ? '客服接待' : '客服回复',
-//                            'keyword2' => '回复中',
-//                            'keyword3' => date('Y-m-d H:i:s', time()),
-//                            'remark' => '消息内容:' . $msn . ';点击查看更多消息!'
-//                        ], $url]);
-//                        if (!$res) Log::error($userInfo['nickname'] . '发送失败' . $e->getMessage());
-                    }
-                }
-            }
-        }
-        return $response->message('chat', $data);
-    }
+    abstract public function chat(array $data, Response $response);
 
     /**
      * 切换用户聊天
      * @param array $data
      * @param Response $response
-     * @return \think\response\Json
      */
-    public function to_chat(array $data = [], Response $response)
-    {
-        $toUid = $data['id'] ?? 0;
-        $res = $this->room->get($this->fd);
-        if ($res && $toUid) {
-            $uid = $res['uid'];
-            $this->manager->updateTableField((int)$res['type'], (int)$uid, (int)$toUid);
-            //不是游客进入记录
-            if (!$res['tourist']) {
-                /** @var StoreServiceRecordServices $service */
-                $service = app()->make(StoreServiceRecordServices::class);
-                $service->update(['user_id' => $uid, 'to_uid' => $toUid], ['mssage_num' => 0]);
-                /** @var StoreServiceLogServices $logServices */
-                $logServices = app()->make(StoreServiceLogServices::class);
-                $logServices->update(['uid' => $toUid, 'to_uid' => $uid], ['type' => 1]);
-            }
-            return $response->message('mssage_num', ['uid' => $toUid, 'num' => 0, 'recored' => (object)[]]);
-        }
-    }
+    abstract public function to_chat(array $data, Response $response);
 
     /**
      * 测试原样返回
@@ -293,7 +96,7 @@ abstract class BaseHandler
      * @param Response $response
      * @return bool|\think\response\Json|null
      */
-    public function test(array $data = [], Response $response)
+    public function test(array $data, Response $response)
     {
         return $response->success($data);
     }
@@ -303,17 +106,11 @@ abstract class BaseHandler
      * @param array $data
      * @param Response $response
      */
-    public function close(array $data = [], Response $response)
+    public function close(array $data, Response $response)
     {
         $uid = $data['uid'] ?? 0;
         if ($uid) {
-            /** @var StoreServiceRecordServices $service */
-            $service = app()->make(StoreServiceRecordServices::class);
-            $service->updateRecord(['to_uid' => $uid], ['online' => 0]);
-            $this->manager->pushing($this->manager->userFd(Manager::KEFU_TYPE_NUM), $response->message('online', [
-                'online' => 0,
-                'uid' => $uid
-            ]), $this->fd);
+
         }
     }
 }

+ 18 - 4
app/webscoket/Manager.php

@@ -56,15 +56,14 @@ class Manager extends Handler
      */
     protected $nowRoom;
 
-    const USER_TYPE = ['admin', 'user', 'kefu'];
+    const USER_TYPE = ['user', 'system'];
 
 
     /**
      * Manager constructor.
-     * @param Websocket $websocket
-     * @param Config $config
-     * @param Room $room
      * @param Event $event
+     * @param Config $config
+     * @param Websocket $websocket
      * @param Response $response
      * @param \app\webscoket\Room $nowRoom
      */
@@ -259,4 +258,19 @@ class Manager extends Handler
         }
         parent::onClose();
     }
+
+    public function checkGroupUser($uid, $group_id)
+    {
+        $on = [];
+        $toUserFd = $this->userFd(0, $uid);
+        foreach ($toUserFd as $value) {
+            if ($frem = $this->nowRoom->get($value)) {
+                //如果当收消息人在和当前发消息人对话中
+                if (($frem['to_group'] ?? 0) == $group_id) {
+                    $on[] = $value;
+                }
+            }
+        }
+        return $on;
+    }
 }

+ 2 - 4
app/webscoket/Room.php

@@ -89,15 +89,13 @@ class Room
      * @param string $key fd
      * @param int $uid 用户uid
      * @param int $to_uid 当前聊天人的uid
-     * @param int $tourist 是否为游客
      * @return mixed
      */
     public function add(string $key, int $uid, int $to_uid = 0)
     {
         $nowkey = $this->tableFdPrefix . $key;
-        $data = ['fd' => $key, 'type' => $this->type ?: 'user', 'uid' => $uid, 'to_uid' => $to_uid];
-        $res = $this->getTable()->set($nowkey, $data);
-        return $res;
+        $data = ['fd' => $key, 'type' => $this->type ?: 'user', 'uid' => $uid, 'to_uid' => $to_uid, 'to_group' => 0];
+        return $this->getTable()->set($nowkey, $data);
     }
 
     /**

+ 88 - 0
app/webscoket/SocketPush.php

@@ -0,0 +1,88 @@
+<?php
+/**
+ * @Created by PhpStorm
+ * @author: Kirin
+ * @day: 2025/2/11
+ * @time: 14:14
+ */
+
+namespace app\webscoket;
+
+
+use think\response\Json;
+
+class SocketPush
+{
+    private $manager;
+    private $response;
+
+    private $fd = [];
+
+    protected $userType = 0;
+    protected $type = 'tips';
+    protected $data = [];
+
+    public function __construct(Manager $manager, Response $response, $userType = 0)
+    {
+        $this->manager = $manager;
+        $this->response = $response;
+        $this->setUserType($userType);
+    }
+
+    public static function initialize()
+    {
+        return new self(app()->make(Manager::class), app()->make(Response::class));
+    }
+
+
+    public static function user()
+    {
+        return new self(app()->make(Manager::class), app()->make(Response::class), 'user');
+    }
+
+    public static function system()
+    {
+        return new self(app()->make(Manager::class), app()->make(Response::class), 'system');
+    }
+
+    public function setUserType($type)
+    {
+        if (!in_array($type, $this->manager::USER_TYPE)) {
+            throw new \Exception('用户类型错误');
+        }
+        $this->userType = array_search($type, $this->manager::USER_TYPE);
+        return $this;
+    }
+
+    public function type($type)
+    {
+        $this->type = $type;
+        return $this;
+    }
+
+    public function data($data)
+    {
+        $this->data = $data;
+        return $this;
+    }
+
+    public function to($uid)
+    {
+        $this->fd = $this->manager::userFd($this->userType, $uid);
+        return $this;
+    }
+
+    public function push()
+    {
+        if (!$this->fd) {
+            return false;
+        }
+        return $this->manager->send($this->fd, $this->response->message($this->type, $this->data));
+    }
+
+    public function toGroup($uid, $group_id)
+    {
+        $this->fd = $this->manager->checkGroupUser($uid, $group_id);
+        return $this;
+    }
+}

+ 252 - 21
app/webscoket/handler/UserHandler.php

@@ -13,12 +13,18 @@
 
 namespace app\webscoket\handler;
 
-use app\services\message\service\StoreServiceRecordServices;
+use app\services\chat\ChatGroupMemberServices;
+use app\services\chat\ChatGroupServices;
+use app\services\chat\ChatLogServices;
 use app\services\user\UserAuthServices;
 use app\webscoket\BaseHandler;
-use app\webscoket\Manager;
 use app\webscoket\Response;
-use crmeb\exceptions\AuthException;
+use Psr\SimpleCache\InvalidArgumentException;
+use qiniu\exceptions\AuthException;
+use think\db\exception\DataNotFoundException;
+use think\db\exception\DbException;
+use think\db\exception\ModelNotFoundException;
+use think\response\Json;
 
 /**
  * Class UserHandler
@@ -28,18 +34,14 @@ class UserHandler extends BaseHandler
 {
 
     /**
-	 * 用户登陆
-	 * @param array $data
-	 * @param Response $response
-	 * @return bool|mixed|\think\response\Json|null
-	 */
+     * 用户登陆
+     * @param array $data
+     * @param Response $response
+     * @return Json
+     * @throws InvalidArgumentException
+     */
     public function login(array $data, Response $response)
     {
-        // 游客登陆
-        if (isset($data['tourist']) && $data['tourist']) {
-            return $response->success();
-        }
-
         if (!isset($data['token']) || !$token = $data['token']) {
             return $response->fail('授权失败!');
         }
@@ -53,16 +55,245 @@ class UserHandler extends BaseHandler
         }
 
         $user = $authInfo['user'];
-        /** @var StoreServiceRecordServices $service */
-        $service = app()->make(StoreServiceRecordServices::class);
-        $service->updateRecord(['to_uid' => $user->uid], ['online' => 1, 'type' => $data['form_type'] ?? 1]);
-        //给所有在线客服人员发送当前用户上线消息
-        $this->manager->pushing($this->manager->userFd(Manager::KEFU_TYPE_NUM), $response->message('user_online', [
-            'uid' => $user->uid,
-            'online' => 1
-        ])->getData(), $this->fd);
 
         return $response->success('login', $user->toArray());
     }
 
+    /**
+     * 聊天事件
+     * @param array $data
+     * @param Response $response
+     * @return Json
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function chat(array $data, Response $response)
+    {
+        $user = $this->room->get($this->fd);
+        if (!$user) {
+            return $response->fail('聊天用户已下线');
+        }
+        $to_uid = $data['to_uid'] ?? 0;
+        $msn_type = $data['type'] ?? 'text';
+        $msn = $data['msn'] ?? '';
+        $uid = $user['uid'];
+        if (!$to_uid) {
+            return $response->message('err_tip', ['msg' => '请选择聊天对象']);
+        }
+        if ($to_uid == $uid) {
+            return $response->message('err_tip', ['msg' => '不能和自己聊天']);
+        }
+
+        /** @var ChatLogServices $logServices */
+        $logServices = app()->make(ChatLogServices::class);
+        if (!in_array($msn_type, ChatLogServices::MSN_TYPE)) {
+            return $response->message('err_tip', ['msg' => '格式错误']);
+        }
+        $msn = trim(strip_tags(str_replace(["\n", "\t", "\r", "&nbsp;"], '', htmlspecialchars_decode($msn))));
+        $data = compact('to_uid', 'msn_type', 'msn', 'uid');
+        $data['add_time'] = time();
+
+        //获取收消息人的所有fd信息
+        $toUserFd = $this->manager->userFd(0, $to_uid);
+        $toUser = ['to_uid' => -1];
+        $fremaData = [];
+        $on = [];
+        foreach ($toUserFd as $value) {
+            if ($frem = $this->room->get($value)) {
+                $fremaData[] = $frem;
+                //如果当收消息人在和当前发消息人对话中
+                if ($frem['to_uid'] == $user['uid']) {
+                    $toUser = $frem;
+                    $on = $value;
+                }
+            }
+
+        }
+        //是否在线
+        //是否和当前用户对话
+        $online = $toUserFd && $toUser && $toUser['to_uid'] !== -1;
+
+        $data['status'] = $online ? 1 : 0;
+        $data = $logServices->create($data);
+        $data = $data->toArray();
+        $data['_add_time'] = $data['add_time'];
+        $data['add_time'] = strtotime($data['add_time']);
+
+        $_userInfo = $logServices->getInfo(0, $uid);
+        //是否在线
+        $unMessagesCount = $logServices->getCount(['uid' => $uid, 'to_uid' => $to_uid, 'status' => 0]);
+        if ($online) {
+            $this->manager->pushing($on, $response->message('reply', $data)->getData());
+        } else {
+            //用户在线,可是没有和当前用户进行聊天,给当前用户发送未读条数
+            if ($toUserFd && $toUser) {
+                $data['record']['nickname'] = $_userInfo['info']['name'] ?? '';
+                $data['record']['avatar'] = $_userInfo['info']['avatar'] ?? $_userInfo['info']['logo'] ?? '';
+                $data['record']['type'] = $_userInfo['type'];
+
+                $this->manager->pushing($toUserFd, $response->message('message_num', [
+                    'uid' => $uid,
+                    'num' => $unMessagesCount,
+                    'record' => $data['record']
+                ])->getData());
+
+            }
+        }
+        return $response->message('chat', $data);
+    }
+
+    /**
+     * 聊天事件
+     * @param array $data
+     * @param Response $response
+     * @return Json
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function group_chat(array $data, Response $response)
+    {
+        $user = $this->room->get($this->fd);
+        if (!$user) {
+            return $response->fail('聊天用户已下线');
+        }
+        $at = $data['at'] ?? 0;
+        $group_id = $data['group_id'] ?? 0;
+        $msn_type = $data['type'] ?? 'text';
+        $msn = $data['msn'] ?? '';
+        $uid = $user['uid'];
+        if (!$group_id) {
+            return $response->message('err_tip', ['msg' => '请选择聊天群聊']);
+        }
+        /** @var ChatGroupMemberServices $memberService */
+        $memberService = app()->make(ChatGroupMemberServices::class);
+        if (!$user = $memberService->search()->where('uid', $uid)->where('chat_group_id', $group_id)->find()) {
+            return $response->message('err_tip', ['msg' => '未在群内']);
+        }
+        $members = $memberService->search(['chat_group_id' => $group_id])->where('uid', '<>', $uid)->select();
+        /** @var ChatGroupServices $groupServices */
+        $groupServices = app()->make(ChatGroupServices::class);
+        $group = $groupServices->search()->where('id', $group_id)->find();
+        if (!$group) return $response->message('err_tip', ['msg' => '群不存在']);
+        /** @var ChatLogServices $logServices */
+        $logServices = app()->make(ChatLogServices::class);
+        if (!in_array($msn_type, ChatLogServices::MSN_TYPE)) {
+            return $response->message('err_tip', ['msg' => '格式错误']);
+        }
+        $msn = trim(strip_tags(str_replace(["\n", "\t", "\r", "&nbsp;"], '', htmlspecialchars_decode($msn))));
+        $data = compact('group_id', 'msn_type', 'msn', 'uid', 'at');
+        $data['add_time'] = time();
+        $online = [$uid];
+        $on = [];
+        //获取收消息人的所有fd信息
+        foreach ($members as $v) {
+            $toUserFd = $this->manager->userFd(0, $v['uid']);
+            $fremaData = [];
+            foreach ($toUserFd as $value) {
+                if ($frem = $this->room->get($value)) {
+                    $fremaData[] = $frem;
+                    //如果当收消息人在和当前发消息人对话中
+                    if (($frem['to_group'] ?? 0) == $group_id) {
+                        $online[] = $v['uid'];
+                        $on[] = $value;
+                    }
+                }
+            }
+        }
+        $data['group_see'] = implode(',', array_unique($online));
+        $data['status'] = 1;
+        $data = $logServices->create($data);
+        $data = $data->toArray();
+        $data['_add_time'] = $data['add_time'];
+        $data['add_time'] = strtotime($data['add_time']);
+        $_userInfo = $logServices->getInfo($user['identity'], $uid);
+        $data['record']['nickname'] = $user['nickname'] ?: ($_userInfo['info']['name'] ?? '');
+        $data['record']['avatar'] = $_userInfo['info']['avatar'] ?? $_userInfo['info']['logo'] ?? '';
+        $data['record']['type'] = $_userInfo['type'];
+        $data['record']['identity'] = $user['identity'];
+        $data['record']['ext_identity'] = $user['ext_identity'];
+        $this->manager->pushing($on, $response->message('group_reply', $data)->getData());
+        $record = $data['record'];
+        foreach ($members as $v) {
+            if (!in_array($v['uid'], $online)) {
+                $toUserFd = $this->manager->userFd(0, $v['uid']);
+                if ($toUserFd) {
+                    $unMessagesCount = $logServices->search()->where('group_id', $group_id)
+                        ->where('!find_in_set(' . $v['uid'] . ',group_see)')->where('add_time', '>=', $v['add_time'])
+                        ->count();
+                    $this->manager->pushing($toUserFd, $response->message('group_message_num', [
+                        'uid' => $uid,
+                        'group_id' => $group_id,
+                        'group_name' => $group['name'],
+                        'num' => $unMessagesCount,
+                        'record' => $record
+                    ])->getData());
+                }
+            }
+        }
+        return $response->message('group_chat', $data);
+    }
+
+
+    /**
+     * 切换用户聊天
+     * @param array $data
+     * @param Response $response
+     * @return Json
+     * @throws DataNotFoundException
+     * @throws DbException
+     * @throws ModelNotFoundException
+     */
+    public function to_chat(array $data, Response $response)
+    {
+        $toUid = $data['id'] ?? 0;
+        $toGroup = $data['to_group'] ?? 0;
+        $toUserType = $data['to_user_type'] ?? 0;
+        $userType = $data['user_type'] ?? 0;
+        $res = $this->room->get($this->fd);
+        if ($res && $toUid) {
+            $uid = $res['uid'];
+            $this->manager->updateTableField((int)$res['type'], (int)$uid, 0, 'to_group');
+            $this->manager->updateTableField((int)$res['type'], (int)$uid, (int)$toUid);
+            $this->manager->updateTableField((int)$res['type'], (int)$uid, (int)$toUserType, 'to_user_type');
+            $this->manager->updateTableField((int)$res['type'], (int)$uid, (int)$userType, 'user_type');
+            /** @var ChatLogServices $logServices */
+            $logServices = app()->make(ChatLogServices::class);
+            $logServices->update(['uid' => $toUid, 'to_uid' => $uid, 'to_uid_type' => $toUserType, 'uid_type' => $userType], ['status' => 1]);
+            return $response->message('message_num', ['uid' => $toUid, 'to_user_type' => $toUserType, 'user_type' => $userType, 'num' => 0, 'recored' => (object)[]]);
+        } else if ($res && $toGroup) {
+            $uid = $res['uid'];
+            /** @var ChatGroupMemberServices $memberService */
+            $memberService = app()->make(ChatGroupMemberServices::class);
+            if (!$user = $memberService->search()->where('uid', $uid)->where('chat_group_id', $toGroup)->find()) {
+                return $response->message('err_tip', ['msg' => '未在群内']);
+            }
+            $this->manager->updateTableField((int)$res['type'], (int)$uid, (int)0);
+            $this->manager->updateTableField((int)$res['type'], (int)$uid, (int)$toGroup, 'to_group');
+//            //debug
+//            {
+//                $toUserFd = $this->manager->userFd(0, $uid);
+//                foreach ($toUserFd as $value){
+//                    if ($frem = $this->room->get($value)) {
+//                        Log::debug($uid.'|'.json_encode($frem));
+//                    }
+//                }
+//            }
+            /** @var ChatLogServices $logServices */
+            $logServices = app()->make(ChatLogServices::class);
+            /** @var ChatGroupServices $groupServices */
+            $groupServices = app()->make(ChatGroupServices::class);
+            $group = $groupServices->search()->where('id', $toGroup)->find();
+            if (!$group) return $response->message('err_tip', ['msg' => '群不存在']);
+            $logServices->search()->where('group_id', $toGroup)
+                ->where('!find_in_set(' . $uid . ',group_see)')
+                ->exp('group_see', 'CONCAT(group_see,",' . $uid . '")')
+                ->update();
+            return $response->message('group_message_num', ['uid' => $toUid, 'to_group' => $toGroup, 'num' => 0, 'record' => (object)[]]);
+        } else {
+            return $response->message('err_tip', ['msg' => '请登录']);
+        }
+    }
+
 }

+ 6 - 1
composer.json

@@ -67,7 +67,12 @@
     }
   },
   "config": {
-    "preferred-install": "dist"
+    "preferred-install": "dist",
+    "allow-plugins": {
+      "easywechat-composer/easywechat-composer": true,
+      "yurunsoft/composer-include-files": true,
+      "yurunsoft/guzzle-swoole": true
+    }
   },
   "scripts": {
     "post-autoload-dump": [

+ 2 - 8
composer.lock

@@ -626,13 +626,7 @@
                 "type": "zip",
                 "url": "https://api.github.com/repos/alipay/alipay-easysdk/zipball/c6008839a22a5fca08e9f8536730f7abfed522d5",
                 "reference": "c6008839a22a5fca08e9f8536730f7abfed522d5",
-                "shasum": "",
-                "mirrors": [
-                    {
-                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
-                        "preferred": true
-                    }
-                ]
+                "shasum": ""
             },
             "require": {
                 "alibabacloud/tea": "^3.1",
@@ -6803,5 +6797,5 @@
         "ext-openssl": "*"
     },
     "platform-dev": [],
-    "plugin-api-version": "2.0.0"
+    "plugin-api-version": "2.6.0"
 }

+ 1 - 1
config/cookie.php

@@ -20,7 +20,7 @@ return [
 
     'header'    => [
         'Access-Control-Allow-Origin'       => '*',
-        'Access-Control-Allow-Headers'      => 'Client-Userid,Authori-zation,Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With, Form-type',
+        'Access-Control-Allow-Headers'      => 'Client-Userid,Authori-zation,Authorization,Qn-Location, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With, Form-type',
         'Access-Control-Allow-Methods'      => 'GET,POST,PATCH,PUT,DELETE,OPTIONS,DELETE',
         'Access-Control-Max-Age'            =>  '1728000',
         'Access-Control-Allow-Credentials'  => 'true',

+ 11 - 12
config/database.php

@@ -59,17 +59,16 @@ return [
         ],
 
         // 更多的数据库配置信息
-
-        //数据分页配置
-        'page' => [
-            //页码key
-            'pageKey' => 'page',
-            //每页截取key
-            'limitKey' => 'limit',
-            //每页截取最大值
-            'limitMax' => 100,
-            //默认条数
-            'defaultLimit' => 10,
-        ]
     ],
+    //数据分页配置
+    'page' => [
+        //页码key
+        'pageKey' => 'page',
+        //每页截取key
+        'limitKey' => 'limit',
+        //每页截取最大值
+        'limitMax' => 100,
+        //默认条数
+        'defaultLimit' => 10,
+    ]
 ];

+ 13 - 1
config/swoole.php

@@ -1,6 +1,7 @@
 <?php
 
 use app\webscoket\Manager;
+use Swoole\Table;
 
 return [
     'http' => [
@@ -83,7 +84,18 @@ return [
             'max_wait_time' => 5,
         ],
     ],
-    'tables' => [],
+    'tables' => [//高性能内存数据库
+        'user' => [
+            'size' => 20480,
+            'columns' => [
+                ['name' => 'fd', 'type' => Table::TYPE_STRING, 'size' => 50],
+                ['name' => 'type', 'type' => Table::TYPE_INT],
+                ['name' => 'uid', 'type' => Table::TYPE_INT],
+                ['name' => 'to_uid', 'type' => Table::TYPE_STRING, 'size' => 50],
+                ['name' => 'to_group', 'type' => Table::TYPE_INT, 'size' => 50],
+            ]
+        ]
+    ],
     //每个worker里需要预加载以共用的实例
     'concretes' => [],
     //重置器

File diff suppressed because it is too large
+ 228 - 676
database.sql


+ 0 - 32
eb_store_product_description.sql

@@ -1,32 +0,0 @@
-/*
- Navicat Premium Data Transfer
-
- Source Server         : 幸福家【新】
- Source Server Type    : MySQL
- Source Server Version : 50744
- Source Host           : localhost:3306
- Source Schema         : nanjinglongzhu_c
-
- Target Server Type    : MySQL
- Target Server Version : 50744
- File Encoding         : 65001
-
- Date: 03/01/2025 14:55:10
-*/
-
-SET NAMES utf8mb4;
-SET FOREIGN_KEY_CHECKS = 0;
-
--- ----------------------------
--- Table structure for eb_store_product_description
--- ----------------------------
-DROP TABLE IF EXISTS `eb_store_product_description`;
-CREATE TABLE `eb_store_product_description`  (
-  `product_id` int(11) NOT NULL DEFAULT 0 COMMENT '商品ID',
-  `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '商品详情',
-  `type` tinyint(1) NOT NULL DEFAULT 0 COMMENT '商品类型',
-  INDEX `product_id`(`product_id`, `type`) USING BTREE,
-  INDEX `type`(`type`, `product_id`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '商品详情表' ROW_FORMAT = Dynamic;
-
-SET FOREIGN_KEY_CHECKS = 1;

+ 2 - 2
qiniu/basic/BaseController.php

@@ -31,8 +31,8 @@ abstract class BaseController
         return app('json')->fail($msg, $data);
     }
 
-    public function status($code = 200, $msg = 'ok', ?array $data = null)
+    public function status($status, $msg = 'ok', ?array $data = null)
     {
-        return app('json')->make($code, $msg, $data);
+        return app('json')->status($status, $msg, $data);
     }
 }

+ 4 - 4
qiniu/services/AliPayService.php

@@ -129,7 +129,7 @@ class AliPayService
         if ($this->config['encryptKey']) {
             $options->encryptKey = $this->config['encryptKey'];
         }
-		Tea::config(['verify' => false]);
+        Tea::config(['verify' => false]);
 
 
         return $options;
@@ -252,7 +252,7 @@ class AliPayService
                         $notify->trade_no = $notify->out_trade_no;
                         $notify->out_trade_no = substr($notify->out_trade_no, $count + 1);
                     }
-                    return (new Hook(PayNotifyServices::class, 'aliyun'))->listen($notify->attach, $notify->out_trade_no, $notify->trade_no);
+                    return (new Hook(PayNotifyServices::class, 'alipay'))->listen($notify->attach, $notify->out_trade_no, $notify->trade_no);
                 }
                 return false;
             }
@@ -266,8 +266,8 @@ class AliPayService
      */
     public function notify(callable $notifyFn)
     {
-		$paramInfo = app()->request->param();
-		unset($paramInfo['type']);
+        $paramInfo = app()->request->param();
+        unset($paramInfo['type']);
         //商户订单号
         $postOrder['out_trade_no'] = $paramInfo['out_trade_no'] ?? '';
         //支付宝交易号

+ 1 - 1
qiniu/services/upload/storage/Cos.php

@@ -13,8 +13,8 @@ namespace qiniu\services\upload\storage;
 use qiniu\basic\BaseUpload;
 use qiniu\exceptions\UploadException;
 use GuzzleHttp\Psr7\Utils;
-use think\exception\ValidateException;
 use qiniu\services\upload\extend\cos\Sts;
+use think\exception\ValidateException;
 use qiniu\services\upload\extend\cos\Client as CosClient;
 
 /**

+ 36 - 36
qiniu/services/upload/storage/Local.php

@@ -127,17 +127,17 @@ class Local extends BaseUpload
                 return $this->setError($e->getMessage());
             }
         }
-        if(!$this->checkImage($fileHandle)) {
-            $stream = fopen($fileHandle->getPathname(), 'r');
-            $content = (fread($stream, filesize($fileHandle->getPathname())));
-            if (is_resource($stream)) {
-                fclose($stream);
-            }
-            if (preg_match('/think|php|log|phar|Socket|Channel|Flysystem|Psr6Cache|Cached|Request|debug|Psr6Cachepool|eval/i', $content)) {
-                return $this->setError('文件内容不合法');
-            }
-        }
-        $fileType = pathinfo($fileHandle->getOriginalName(), PATHINFO_EXTENSION);
+//        if(!$this->checkImage($fileHandle)) {
+//            $stream = fopen($fileHandle->getPathname(), 'r');
+//            $content = (fread($stream, filesize($fileHandle->getPathname())));
+//            if (is_resource($stream)) {
+//                fclose($stream);
+//            }
+//            if (preg_match('/think|php|log|phar|Socket|Channel|Flysystem|Psr6Cache|Cached|Request|debug|Psr6Cachepool|eval/i', $content)) {
+//                return $this->setError('文件内容不合法');
+//            }
+//        }
+		$fileType = pathinfo($fileHandle->getOriginalName(), PATHINFO_EXTENSION);
 
         $fileName = Filesystem::putFileAs($this->path, $fileHandle, in_array($fileType, ['ico']) ? $fileHandle->getOriginalName() : strtolower($fileHandle->hashName()));
 
@@ -242,12 +242,12 @@ class Local extends BaseUpload
                             $savePath = $this->createSaveFilePath($filePath, $this->thumbWaterPath, [$height => $config[$height], $width => $config[$width]]);
                             //防止重复生成
                             if (!file_exists(root_path() . 'public' . $savePath)) {
-                                if ($this->authThumb) {//生成
-                                    $Image = Image::open(app()->getRootPath() . 'public' . $filePath);
-                                    $Image->thumb($config[$width], $config[$height])->save(root_path() . 'public' . $savePath);
-                                } else {
-                                    $savePath = $filePath;
-                                }
+								if ($this->authThumb) {//生成
+									$Image = Image::open(app()->getRootPath() . 'public' . $filePath);
+                                	$Image->thumb($config[$width], $config[$height])->save(root_path() . 'public' . $savePath);
+								} else {
+									$savePath = $filePath;
+								}
                             }
                             $key = 'filePath' . ucfirst($v);
                             $data[$v] = $this->fileInfo->$key = $savePath;
@@ -330,12 +330,12 @@ class Local extends BaseUpload
         }
         try {
             if (!file_exists(root_path() . 'public' . $waterPath)) {
-                if ($this->authThumb) {//生成
-                    $Image = Image::open(app()->getRootPath() . 'public' . $filePath);
-                    $Image->water(app()->getRootPath() . 'public' . $watermark_image, $waterConfig['watermark_position'] ?: 1, $waterConfig['watermark_opacity'])->save(root_path() . 'public' . $waterPath);
-                } else {
-                    $waterPath = $filePath;
-                }
+				if ($this->authThumb) {//生成
+					$Image = Image::open(app()->getRootPath() . 'public' . $filePath);
+					$Image->water(app()->getRootPath() . 'public' . $watermark_image, $waterConfig['watermark_position'] ?: 1, $waterConfig['watermark_opacity'])->save(root_path() . 'public' . $waterPath);
+				} else {
+					$waterPath = $filePath;
+				}
             }
         } catch (\Throwable $e) {
             throw new ValidateException($e->getMessage());
@@ -364,19 +364,19 @@ class Local extends BaseUpload
         }
         try {
             if (!file_exists(root_path() . 'public' . $waterPath)) {
-                if ($this->authThumb) {//生成
-                    $Image = Image::open(app()->getRootPath() . 'public' . $filePath);
-                    if (strlen($waterConfig['watermark_text_color']) < 7) {
-                        $waterConfig['watermark_text_color'] = substr($waterConfig['watermark_text_color'], 1);
-                        $waterConfig['watermark_text_color'] = '#' . $waterConfig['watermark_text_color'] . $waterConfig['watermark_text_color'];
-                    }
-                    if (strlen($waterConfig['watermark_text_color']) > 7) {
-                        $waterConfig['watermark_text_color'] = substr($waterConfig['watermark_text_color'], 0, 7);
-                    }
-                    $Image->text($waterConfig['watermark_text'], $waterConfig['watermark_text_font'], $waterConfig['watermark_text_size'], $waterConfig['watermark_text_color'], $waterConfig['watermark_position'], [$waterConfig['watermark_x'], $waterConfig['watermark_y'], $waterConfig['watermark_text_angle']])->save(root_path() . 'public' . $waterPath);
-                } else {
-                    $waterPath = $filePath;
-                }
+				if ($this->authThumb) {//生成
+					$Image = Image::open(app()->getRootPath() . 'public' . $filePath);
+					if (strlen($waterConfig['watermark_text_color']) < 7) {
+						$waterConfig['watermark_text_color'] = substr($waterConfig['watermark_text_color'], 1);
+						$waterConfig['watermark_text_color'] = '#' . $waterConfig['watermark_text_color'] . $waterConfig['watermark_text_color'];
+					}
+					if (strlen($waterConfig['watermark_text_color']) > 7) {
+						$waterConfig['watermark_text_color'] = substr($waterConfig['watermark_text_color'], 0, 7);
+					}
+					$Image->text($waterConfig['watermark_text'], $waterConfig['watermark_text_font'], $waterConfig['watermark_text_size'], $waterConfig['watermark_text_color'], $waterConfig['watermark_position'], [$waterConfig['watermark_x'], $waterConfig['watermark_y'], $waterConfig['watermark_text_angle']])->save(root_path() . 'public' . $waterPath);
+				} else {
+					$waterPath = $filePath;
+				}
             }
         } catch (\Throwable $e) {
             throw new ValidateException($e->getMessage() . $e->getLine());

+ 31 - 5
route/admin.php

@@ -13,6 +13,8 @@ use app\http\middleware\admin\AdminLogMiddleware;
 use app\http\middleware\AllowOriginMiddleware;
 use app\http\middleware\StationOpenMiddleware;
 use think\facade\Route;
+use think\facade\Config;
+use think\Response;
 
 Route::group('adminapi', function () {
     //无需登录
@@ -31,6 +33,8 @@ Route::group('adminapi', function () {
         Route::get('login/info', 'Login/info')->option(['real_name' => '登录信息']);
         //管理员退出登陆
         Route::get('logout', 'Login/logout')->name('SystemAdminLogout')->option(['real_name' => '退出登陆']);
+        //
+        Route::get('sys_config', 'Common/getConfig')->name('getConfig')->option(['real_name' => '获取配置']);
     });
     Route::group(function () {
         //需登录,但不需要权限
@@ -61,12 +65,12 @@ Route::group('adminapi', function () {
             Route::group('finance', function () {
 
             });
-
-
+            //系统日志
             Route::group('log', function () {
                 Route::get('', 'system.SystemLogs/index')->option(['real_name' => '系统日志列表']);
                 Route::get('/:id', 'system.SystemLogs/detail')->option(['real_name' => '系统日志详情']);
             });
+            //菜单
             Route::group('menus', function () {
                 //修改权限规格显示状态
                 Route::put('show/:id', 'system.SystemMenus/show')->name('SystemMenusShow')->option(['real_name' => '修改权限规格显示状态']);
@@ -97,7 +101,10 @@ Route::group('adminapi', function () {
             Route::put('user_level/set_value', 'system.config.SystemUserLevel/setValue')->option(['real_name' => '用户等级快速修改']);
             //等级任务模板
             Route::get('user_level/task_base', 'system.config.SystemUserLevel/getTaskBase')->option(['real_name' => '等级任务模板']);
-
+            //门店显示
+            Route::put('store/set_show/:id/:is_show', 'system.store.SystemStore/set_show')->option(['real_name' => '门店显示/隐藏']);
+            //门店重置管理员
+            Route::put('store/reset/:id', 'system.store.SystemStore/resetAdmin')->option(['real_name' => '门店重置管理员']);
             //附件管理
             Route::group('file', function () {
                 //图片附件列表
@@ -137,8 +144,6 @@ Route::group('adminapi', function () {
             Route::post('replace_site_url', 'system.SystemClearData/replaceSiteUrl')->option(['real_name' => '替换域名']);
             //短信发送记录
             Route::get('sms_record', 'system.SmsRecord/index')->option(['real_name' => '短信发送记录']);
-
-
             //用户分组资源路由
             Route::resource('user', 'user.User')
                 ->only(['index', 'read', 'save', 'update', 'delete'])
@@ -217,6 +222,27 @@ Route::group('adminapi', function () {
                     'update' => '修改系统配置',
                     'delete' => '删除系统配置'
                 ]]);
+            //门店资源路由
+            Route::resource('store', 'system.store.SystemStore')
+                ->only(['index', 'read', 'save', 'update', 'delete'])
+                ->option(['real_name' => [
+                    'index' => '门店列表',
+                    'read' => '门店详情',
+                    'save' => '保存门店',
+                    'update' => '修改门店',
+                    'delete' => '删除门店'
+                ]]);
         })->middleware(AdminCheckRoleMiddleware::class);
     })->middleware(AdminAuthTokenMiddleware::class)->middleware(AdminLogMiddleware::class);
+    /**
+     * miss 路由
+     */
+    Route::miss(function () {
+        if (app()->request->isOptions()) {
+            $header = Config::get('cookie.header');
+            $header['Access-Control-Allow-Origin'] = app()->request->header('origin');
+            return Response::create('ok')->code(200)->header($header);
+        } else
+            return Response::create()->code(404);
+    });
 })->prefix('admin.')->middleware(AllowOriginMiddleware::class);

+ 93 - 21
route/api.php

@@ -10,17 +10,23 @@ use app\http\middleware\AllowOriginMiddleware;
 use app\http\middleware\api\AuthTokenMiddleware;
 use app\http\middleware\api\BlockerMiddleware;
 use app\http\middleware\api\LocationMiddleware;
-use app\http\middleware\api\MemberTypeMiddleware;
+use app\http\middleware\api\TradeMiddleware;
 use app\http\middleware\StationOpenMiddleware;
 use think\facade\Route;
+use think\facade\Config;
+use think\Response;
 
 Route::group('api', function () {
     //城市列表
     Route::get('city', 'Pub/city');
     //城市列表
     Route::get('cityList', 'Pub/cityList');
+    //门店列表
+    Route::get('stores', 'Pub/store_list');
     //APP版本号
     Route::get('version', 'Pub/version');
+    //测试
+    Route::any('test', 'Pub/test');
     //登陆相关
     Route::group(function () {
         //账号密码登录
@@ -47,7 +53,9 @@ Route::group('api', function () {
         //可登可不登的接口
         Route::group('', function () {
             //公共类
-            Route::get('index', 'Pub/index')->name('index');//首页
+            //首页
+            Route::get('index', 'Pub/index')->name('index');
+
         })->middleware(AuthTokenMiddleware::class, false);
 
         //用户接口
@@ -58,32 +66,96 @@ Route::group('api', function () {
             Route::post('trade_pwd/reset', 'Login/reset_trade_pwd')->middleware(BlockerMiddleware::class)->name('resetTradePwd');
             //上传图片
             Route::post('upload', 'Pub/upload_image')->middleware(BlockerMiddleware::class)->name('uploadImage');
-            //修改账号
-            Route::put('account', 'user.User/setAccount')->name('setAccount')->middleware(BlockerMiddleware::class)->name('setAccount');
-            //用户相关
-            Route::group('user', function () {
-                //用户信息
-                Route::get('info', 'user.User/info')->name('userInfo');
-                //转账
 
-                //资金流
 
-                //推广
+            Route::group('chat', function () {
+                //聊天
+                Route::get('', 'chat.Chat/index')->name('chatIndex');
+                //聊天记录
+                Route::get('chatLog', 'chat.Chat/chatLog')->name('chatLog');
+                //群聊记录
+                Route::get('groupLog/:group_id', 'chat.Chat/groupChatLog')->name('groupChatLog');
+                //群聊
+                Route::get('group', 'chat.ChatGroup/group')->name('groupList');
+                //群聊详情
+                Route::get('group/:id', 'chat.ChatGroup/groupInfo')->name('groupInfo');
+                //群聊成员
+                Route::get('group/members/:id', 'chat.ChatGroup/groupMembers')->name('groupMembers');
+                //修改群昵称
+                Route::post('group/mark/:id', 'chat.ChatGroup/setMark')->name('groupMark');
+                //修改群信息
+                Route::post('group/:id', 'chat.ChatGroup/editGroup')->name('editGroup')->middleware(BlockerMiddleware::class);
+                //设置公告
+                Route::post('group/notice/:id', 'chat.ChatGroup/setNotice')->name('groupNotice');
             });
-        })->middleware(AuthTokenMiddleware::class);
-        //装修工接口
-        Route::group('', function () {
 
-        })->middleware(AuthTokenMiddleware::class)->middleware(MemberTypeMiddleware::class, 'worker');
-        //设计师接口
-        Route::group('', function () {
+            //用户类  地址
+            Route::group('address', function () {
+                Route::get('detail/:id', 'user.UserAddress/address')->name('address');//获取单个地址
+                Route::get('list', 'user.UserAddress/address_list')->name('addressList');//地址列表
+                Route::post('default/set', 'user.UserAddress/address_default_set')->name('addressDefaultSet');//设置默认地址
+                Route::get('default', 'user.UserAddress/address_default')->name('addressDefault');//获取默认地址
+                Route::post('edit', 'user.UserAddress/address_edit')->name('addressEdit');//修改 添加 地址
+                Route::delete('del/:id', 'user.UserAddress/address_del')->name('addressDel');//删除地址
+            });
 
-        })->middleware(AuthTokenMiddleware::class)->middleware(MemberTypeMiddleware::class, 'designer');
-        //业务员接口
-        Route::group('', function () {
+            //用户类 提现
+            Route::group('extract', function () {
+                Route::get('bank/:id', 'user.UserExtract/bankInfo')->name('bankInfo');//获取单个收款方式
+                Route::post('bank/[:id]', 'user.UserExtract/saveBank')->name('saveBank')->middleware(BlockerMiddleware::class);//修改 添加 收款方式
+                Route::get('bank', 'user.UserExtract/bankList')->name('bankList');//收款方式列表
+                Route::post('bank/default/:id', 'user.UserExtract/setDefault')->name('bankDefaultSet')->middleware(BlockerMiddleware::class);//设为默认
+                Route::delete('bank/:id', 'user.UserExtract/delete')->name('bankDelete')->middleware(BlockerMiddleware::class);//删除收款方式
 
-        })->middleware(AuthTokenMiddleware::class)->middleware(MemberTypeMiddleware::class, 'salesperson');
+                Route::get('compute', 'user.UserExtract/compute')->name('compute');//提现默认数据
+                Route::post('cash', 'user.UserExtract/cash')->name('cash')->middleware(BlockerMiddleware::class)->middleware(TradeMiddleware::class);//申请提现
+                Route::get('cash', 'user.UserExtract/extractList')->name('extractList');//提现列表
+            });
+
+            //用户相关
+            Route::group('user', function () {
+                //用户信息
+                Route::get('info', 'user.User/info')->name('userInfo');
+                //推荐信息
+                Route::get('spread', 'user.UserSpread/getSpreadInfo')->name('getSpreadInfo');
+                //设置推荐
+                Route::post('spread', 'user.UserSpread/setSpread')->name('setSpread')->middleware(BlockerMiddleware::class);
+                //推广下级列表
+                Route::get('spread/list', 'user.UserSpread/getSpreadUsers')->name('getSpreadUsers');
+                //修改账号
+                Route::put('account', 'user.User/setAccount')->name('setAccount')->middleware(BlockerMiddleware::class);
+                //修改用户信息
+                Route::put('edit', 'user.User/edit')->name('edit')->middleware(BlockerMiddleware::class);
+                //修改手机号
+                Route::put('mobile', 'user.User/changeMobile')->name('changeMobile')->middleware(BlockerMiddleware::class);
+            });
+            Route::group('finance', function () {
+                //余额流水
+                Route::get('money', 'user.UserFinance/getMoneyInfo')->name('getMoneyInfo');
+                //佣金流水
+                Route::get('brokerage', 'user.UserFinance/getBrokerageInfo')->name('getBrokerageInfo');
+                //代币流水
+                Route::get('bill/:category', 'user.UserFinance/getBillInfo')->name('getBillInfo');
+                //余额转账
+                Route::post('money/trade', 'user.UserFinance/tradeMoney')->name('tradeMoney')->middleware(BlockerMiddleware::class)->middleware(TradeMiddleware::class);
+                //佣金转账
+                Route::post('brokerage/trade', 'user.UserFinance/tradeBrokerage')->name('tradeBrokerage')->middleware(BlockerMiddleware::class)->middleware(TradeMiddleware::class);
+                //代币转帐
+                Route::post('other/trade', 'user.UserFinance/tradeOther')->name('tradeOther')->middleware(BlockerMiddleware::class)->middleware(TradeMiddleware::class);
+            });
+        })->middleware(AuthTokenMiddleware::class);
     })->middleware(LocationMiddleware::class);
+    /**
+     * miss 路由
+     */
+    Route::miss(function () {
+        if (app()->request->isOptions()) {
+            $header = Config::get('cookie.header');
+            $header['Access-Control-Allow-Origin'] = app()->request->header('origin');
+            return Response::create('ok')->code(200)->header($header);
+        } else
+            return Response::create()->code(404);
+    });
 })
     ->prefix('api.')
     ->middleware(AllowOriginMiddleware::class)

+ 18 - 0
vendor/autoload.php

@@ -2,6 +2,24 @@
 
 // autoload.php @generated by Composer
 
+if (PHP_VERSION_ID < 50600) {
+    if (!headers_sent()) {
+        header('HTTP/1.1 500 Internal Server Error');
+    }
+    $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+    if (!ini_get('display_errors')) {
+        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+            fwrite(STDERR, $err);
+        } elseif (!headers_sent()) {
+            echo $err;
+        }
+    }
+    trigger_error(
+        $err,
+        E_USER_ERROR
+    );
+}
+
 require_once __DIR__ . '/composer/autoload_real.php';
 
 return ComposerAutoloaderInit0ef01221f70f4fb275871418332d8a66::getLoader();

+ 134 - 34
vendor/composer/ClassLoader.php

@@ -42,30 +42,76 @@ namespace Composer\Autoload;
  */
 class ClassLoader
 {
+    /** @var \Closure(string):void */
+    private static $includeFile;
+
+    /** @var string|null */
     private $vendorDir;
 
     // PSR-4
+    /**
+     * @var array<string, array<string, int>>
+     */
     private $prefixLengthsPsr4 = array();
+    /**
+     * @var array<string, list<string>>
+     */
     private $prefixDirsPsr4 = array();
+    /**
+     * @var list<string>
+     */
     private $fallbackDirsPsr4 = array();
 
     // PSR-0
+    /**
+     * List of PSR-0 prefixes
+     *
+     * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
+     *
+     * @var array<string, array<string, list<string>>>
+     */
     private $prefixesPsr0 = array();
+    /**
+     * @var list<string>
+     */
     private $fallbackDirsPsr0 = array();
 
+    /** @var bool */
     private $useIncludePath = false;
+
+    /**
+     * @var array<string, string>
+     */
     private $classMap = array();
+
+    /** @var bool */
     private $classMapAuthoritative = false;
+
+    /**
+     * @var array<string, bool>
+     */
     private $missingClasses = array();
+
+    /** @var string|null */
     private $apcuPrefix;
 
+    /**
+     * @var array<string, self>
+     */
     private static $registeredLoaders = array();
 
+    /**
+     * @param string|null $vendorDir
+     */
     public function __construct($vendorDir = null)
     {
         $this->vendorDir = $vendorDir;
+        self::initializeIncludeClosure();
     }
 
+    /**
+     * @return array<string, list<string>>
+     */
     public function getPrefixes()
     {
         if (!empty($this->prefixesPsr0)) {
@@ -75,28 +121,42 @@ class ClassLoader
         return array();
     }
 
+    /**
+     * @return array<string, list<string>>
+     */
     public function getPrefixesPsr4()
     {
         return $this->prefixDirsPsr4;
     }
 
+    /**
+     * @return list<string>
+     */
     public function getFallbackDirs()
     {
         return $this->fallbackDirsPsr0;
     }
 
+    /**
+     * @return list<string>
+     */
     public function getFallbackDirsPsr4()
     {
         return $this->fallbackDirsPsr4;
     }
 
+    /**
+     * @return array<string, string> Array of classname => path
+     */
     public function getClassMap()
     {
         return $this->classMap;
     }
 
     /**
-     * @param array $classMap Class to filename map
+     * @param array<string, string> $classMap Class to filename map
+     *
+     * @return void
      */
     public function addClassMap(array $classMap)
     {
@@ -111,22 +171,25 @@ class ClassLoader
      * Registers a set of PSR-0 directories for a given prefix, either
      * appending or prepending to the ones previously set for this prefix.
      *
-     * @param string       $prefix  The prefix
-     * @param array|string $paths   The PSR-0 root directories
-     * @param bool         $prepend Whether to prepend the directories
+     * @param string              $prefix  The prefix
+     * @param list<string>|string $paths   The PSR-0 root directories
+     * @param bool                $prepend Whether to prepend the directories
+     *
+     * @return void
      */
     public function add($prefix, $paths, $prepend = false)
     {
+        $paths = (array) $paths;
         if (!$prefix) {
             if ($prepend) {
                 $this->fallbackDirsPsr0 = array_merge(
-                    (array) $paths,
+                    $paths,
                     $this->fallbackDirsPsr0
                 );
             } else {
                 $this->fallbackDirsPsr0 = array_merge(
                     $this->fallbackDirsPsr0,
-                    (array) $paths
+                    $paths
                 );
             }
 
@@ -135,19 +198,19 @@ class ClassLoader
 
         $first = $prefix[0];
         if (!isset($this->prefixesPsr0[$first][$prefix])) {
-            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+            $this->prefixesPsr0[$first][$prefix] = $paths;
 
             return;
         }
         if ($prepend) {
             $this->prefixesPsr0[$first][$prefix] = array_merge(
-                (array) $paths,
+                $paths,
                 $this->prefixesPsr0[$first][$prefix]
             );
         } else {
             $this->prefixesPsr0[$first][$prefix] = array_merge(
                 $this->prefixesPsr0[$first][$prefix],
-                (array) $paths
+                $paths
             );
         }
     }
@@ -156,25 +219,28 @@ class ClassLoader
      * Registers a set of PSR-4 directories for a given namespace, either
      * appending or prepending to the ones previously set for this namespace.
      *
-     * @param string       $prefix  The prefix/namespace, with trailing '\\'
-     * @param array|string $paths   The PSR-4 base directories
-     * @param bool         $prepend Whether to prepend the directories
+     * @param string              $prefix  The prefix/namespace, with trailing '\\'
+     * @param list<string>|string $paths   The PSR-4 base directories
+     * @param bool                $prepend Whether to prepend the directories
      *
      * @throws \InvalidArgumentException
+     *
+     * @return void
      */
     public function addPsr4($prefix, $paths, $prepend = false)
     {
+        $paths = (array) $paths;
         if (!$prefix) {
             // Register directories for the root namespace.
             if ($prepend) {
                 $this->fallbackDirsPsr4 = array_merge(
-                    (array) $paths,
+                    $paths,
                     $this->fallbackDirsPsr4
                 );
             } else {
                 $this->fallbackDirsPsr4 = array_merge(
                     $this->fallbackDirsPsr4,
-                    (array) $paths
+                    $paths
                 );
             }
         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@@ -184,18 +250,18 @@ class ClassLoader
                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
             }
             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
-            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+            $this->prefixDirsPsr4[$prefix] = $paths;
         } elseif ($prepend) {
             // Prepend directories for an already registered namespace.
             $this->prefixDirsPsr4[$prefix] = array_merge(
-                (array) $paths,
+                $paths,
                 $this->prefixDirsPsr4[$prefix]
             );
         } else {
             // Append directories for an already registered namespace.
             $this->prefixDirsPsr4[$prefix] = array_merge(
                 $this->prefixDirsPsr4[$prefix],
-                (array) $paths
+                $paths
             );
         }
     }
@@ -204,8 +270,10 @@ class ClassLoader
      * Registers a set of PSR-0 directories for a given prefix,
      * replacing any others previously set for this prefix.
      *
-     * @param string       $prefix The prefix
-     * @param array|string $paths  The PSR-0 base directories
+     * @param string              $prefix The prefix
+     * @param list<string>|string $paths  The PSR-0 base directories
+     *
+     * @return void
      */
     public function set($prefix, $paths)
     {
@@ -220,10 +288,12 @@ class ClassLoader
      * Registers a set of PSR-4 directories for a given namespace,
      * replacing any others previously set for this namespace.
      *
-     * @param string       $prefix The prefix/namespace, with trailing '\\'
-     * @param array|string $paths  The PSR-4 base directories
+     * @param string              $prefix The prefix/namespace, with trailing '\\'
+     * @param list<string>|string $paths  The PSR-4 base directories
      *
      * @throws \InvalidArgumentException
+     *
+     * @return void
      */
     public function setPsr4($prefix, $paths)
     {
@@ -243,6 +313,8 @@ class ClassLoader
      * Turns on searching the include path for class files.
      *
      * @param bool $useIncludePath
+     *
+     * @return void
      */
     public function setUseIncludePath($useIncludePath)
     {
@@ -265,6 +337,8 @@ class ClassLoader
      * that have not been registered with the class map.
      *
      * @param bool $classMapAuthoritative
+     *
+     * @return void
      */
     public function setClassMapAuthoritative($classMapAuthoritative)
     {
@@ -285,6 +359,8 @@ class ClassLoader
      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
      *
      * @param string|null $apcuPrefix
+     *
+     * @return void
      */
     public function setApcuPrefix($apcuPrefix)
     {
@@ -305,6 +381,8 @@ class ClassLoader
      * Registers this instance as an autoloader.
      *
      * @param bool $prepend Whether to prepend the autoloader or not
+     *
+     * @return void
      */
     public function register($prepend = false)
     {
@@ -324,6 +402,8 @@ class ClassLoader
 
     /**
      * Unregisters this instance as an autoloader.
+     *
+     * @return void
      */
     public function unregister()
     {
@@ -338,15 +418,18 @@ class ClassLoader
      * Loads the given class or interface.
      *
      * @param  string    $class The name of the class
-     * @return bool|null True if loaded, null otherwise
+     * @return true|null True if loaded, null otherwise
      */
     public function loadClass($class)
     {
         if ($file = $this->findFile($class)) {
-            includeFile($file);
+            $includeFile = self::$includeFile;
+            $includeFile($file);
 
             return true;
         }
+
+        return null;
     }
 
     /**
@@ -392,15 +475,20 @@ class ClassLoader
     }
 
     /**
-     * Returns the currently registered loaders indexed by their corresponding vendor directories.
+     * Returns the currently registered loaders keyed by their corresponding vendor directories.
      *
-     * @return self[]
+     * @return array<string, self>
      */
     public static function getRegisteredLoaders()
     {
         return self::$registeredLoaders;
     }
 
+    /**
+     * @param  string       $class
+     * @param  string       $ext
+     * @return string|false
+     */
     private function findFileWithExtension($class, $ext)
     {
         // PSR-4 lookup
@@ -466,14 +554,26 @@ class ClassLoader
 
         return false;
     }
-}
 
-/**
- * Scope isolated include.
- *
- * Prevents access to $this/self from included files.
- */
-function includeFile($file)
-{
-    include $file;
+    /**
+     * @return void
+     */
+    private static function initializeIncludeClosure()
+    {
+        if (self::$includeFile !== null) {
+            return;
+        }
+
+        /**
+         * Scope isolated include.
+         *
+         * Prevents access to $this/self from included files.
+         *
+         * @param  string $file
+         * @return void
+         */
+        self::$includeFile = \Closure::bind(static function($file) {
+            include $file;
+        }, null, null);
+    }
 }

+ 348 - 1250
vendor/composer/InstalledVersions.php

@@ -1,1261 +1,359 @@
 <?php
 
-
-
-
-
-
-
-
-
-
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
 
 namespace Composer;
 
 use Composer\Autoload\ClassLoader;
 use Composer\Semver\VersionParser;
 
-
-
-
-
-
-
-
+/**
+ * This class is copied in every Composer installed project and available to all
+ *
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
+ *
+ * To require its presence, you can require `composer-runtime-api ^2.0`
+ *
+ * @final
+ */
 class InstalledVersions
 {
-private static $installed = array (
-  'root' => 
-  array (
-    'pretty_version' => 'dev-master',
-    'version' => 'dev-master',
-    'aliases' => 
-    array (
-    ),
-    'reference' => 'b4d08155eb79c5471dc034238c7896deaeaff6a5',
-    'name' => 'topthink/think',
-  ),
-  'versions' => 
-  array (
-    'adbario/php-dot-notation' => 
-    array (
-      'pretty_version' => '2.5.0',
-      'version' => '2.5.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae',
-    ),
-    'alibabacloud/credentials' => 
-    array (
-      'pretty_version' => '1.2.0',
-      'version' => '1.2.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'ebcda2e628180b4df235b46a86e1d014c561f5d9',
-    ),
-    'alibabacloud/darabonba-openapi' => 
-    array (
-      'pretty_version' => '0.2.13',
-      'version' => '0.2.13.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '0213396384e2c064eefd614f3dd53636a63f987f',
-    ),
-    'alibabacloud/dysmsapi-20170525' => 
-    array (
-      'pretty_version' => '3.1.0',
-      'version' => '3.1.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5f779cf8d6d8807b9835bff8d058dbab6d59bbf1',
-    ),
-    'alibabacloud/endpoint-util' => 
-    array (
-      'pretty_version' => '0.1.1',
-      'version' => '0.1.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'f3fe88a25d8df4faa3b0ae14ff202a9cc094e6c5',
-    ),
-    'alibabacloud/gateway-spi' => 
-    array (
-      'pretty_version' => '1.0.0',
-      'version' => '1.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '7440f77750c329d8ab252db1d1d967314ccd1fcb',
-    ),
-    'alibabacloud/openapi-util' => 
-    array (
-      'pretty_version' => '0.2.1',
-      'version' => '0.2.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'f31f7bcd835e08ca24b6b8ba33637eb4eceb093a',
-    ),
-    'alibabacloud/tea' => 
-    array (
-      'pretty_version' => '3.2.1',
-      'version' => '3.2.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '1619cb96c158384f72b873e1f85de8b299c9c367',
-    ),
-    'alibabacloud/tea-fileform' => 
-    array (
-      'pretty_version' => '0.3.4',
-      'version' => '0.3.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '4bf0c75a045c8115aa8cb1a394bd08d8bb833181',
-    ),
-    'alibabacloud/tea-utils' => 
-    array (
-      'pretty_version' => '0.2.21',
-      'version' => '0.2.21.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5039e45714c6456186d267f5d81a4b260a652495',
-    ),
-    'alibabacloud/tea-xml' => 
-    array (
-      'pretty_version' => '0.2.4',
-      'version' => '0.2.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '3e0c000bf536224eebbac913c371bef174c0a16a',
-    ),
-    'alipaysdk/easysdk' => 
-    array (
-      'pretty_version' => '2.2.3',
-      'version' => '2.2.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'c6008839a22a5fca08e9f8536730f7abfed522d5',
-    ),
-    'aliyuncs/oss-sdk-php' => 
-    array (
-      'pretty_version' => 'v2.7.2',
-      'version' => '2.7.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5',
-    ),
-    'async-aws/core' => 
-    array (
-      'pretty_version' => '1.21.0',
-      'version' => '1.21.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'eb23cc59515d8d529163313bbf9e02f666e515ef',
-    ),
-    'bacon/bacon-qr-code' => 
-    array (
-      'pretty_version' => '2.0.8',
-      'version' => '2.0.8.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '8674e51bb65af933a5ffaf1c308a660387c35c22',
-    ),
-    'carbonphp/carbon-doctrine-types' => 
-    array (
-      'pretty_version' => '2.1.0',
-      'version' => '2.1.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '99f76ffa36cce3b70a4a6abce41dba15ca2e84cb',
-    ),
-    'dasprid/enum' => 
-    array (
-      'pretty_version' => '1.0.5',
-      'version' => '1.0.5.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '6faf451159fb8ba4126b925ed2d78acfce0dc016',
-    ),
-    'easywechat-composer/easywechat-composer' => 
-    array (
-      'pretty_version' => '1.4.1',
-      'version' => '1.4.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '3fc6a7ab6d3853c0f4e2922539b56cc37ef361cd',
-    ),
-    'endroid/qr-code' => 
-    array (
-      'pretty_version' => '4.6.1',
-      'version' => '4.6.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a75c913b0e4d6ad275e49a2c1de1cacffc6c2184',
-    ),
-    'ezyang/htmlpurifier' => 
-    array (
-      'pretty_version' => 'v4.18.0',
-      'version' => '4.18.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'cb56001e54359df7ae76dc522d08845dc741621b',
-    ),
-    'fastknife/ajcaptcha' => 
-    array (
-      'pretty_version' => 'v1.2.2',
-      'version' => '1.2.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '87c122b6cd950fd98702e929685e5e7c0c517ddc',
-    ),
-    'firebase/php-jwt' => 
-    array (
-      'pretty_version' => 'v6.10.0',
-      'version' => '6.10.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a49db6f0a5033aef5143295342f1c95521b075ff',
-    ),
-    'guzzlehttp/command' => 
-    array (
-      'pretty_version' => '1.3.1',
-      'version' => '1.3.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '0eebc653784f4902b3272e826fe8e88743d14e77',
-    ),
-    'guzzlehttp/guzzle' => 
-    array (
-      'pretty_version' => '7.9.2',
-      'version' => '7.9.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd281ed313b989f213357e3be1a179f02196ac99b',
-    ),
-    'guzzlehttp/guzzle-services' => 
-    array (
-      'pretty_version' => '1.4.1',
-      'version' => '1.4.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'bcab7c0d61672b606510a6fe5af3039d04968c0f',
-    ),
-    'guzzlehttp/promises' => 
-    array (
-      'pretty_version' => '2.0.3',
-      'version' => '2.0.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8',
-    ),
-    'guzzlehttp/psr7' => 
-    array (
-      'pretty_version' => '2.7.0',
-      'version' => '2.7.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a70f5c95fb43bc83f07c9c948baa0dc1829bf201',
-    ),
-    'guzzlehttp/ringphp' => 
-    array (
-      'pretty_version' => '1.1.1',
-      'version' => '1.1.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5e2a174052995663dd68e6b5ad838afd47dd615b',
-    ),
-    'guzzlehttp/streams' => 
-    array (
-      'pretty_version' => '3.0.0',
-      'version' => '3.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5',
-    ),
-    'guzzlehttp/uri-template' => 
-    array (
-      'pretty_version' => 'v1.0.3',
-      'version' => '1.0.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'ecea8feef63bd4fef1f037ecb288386999ecc11c',
-    ),
-    'intervention/image' => 
-    array (
-      'pretty_version' => '2.7.2',
-      'version' => '2.7.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '04be355f8d6734c826045d02a1079ad658322dad',
-    ),
-    'joypack/tencent-map' => 
-    array (
-      'pretty_version' => '1.0.0',
-      'version' => '1.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '97c0269086d53dbecb9c3c6e1d2717645d7940a8',
-    ),
-    'league/flysystem' => 
-    array (
-      'pretty_version' => '1.1.10',
-      'version' => '1.1.10.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '3239285c825c152bcc315fe0e87d6b55f5972ed1',
-    ),
-    'league/flysystem-cached-adapter' => 
-    array (
-      'pretty_version' => '1.1.0',
-      'version' => '1.1.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd1925efb2207ac4be3ad0c40b8277175f99ffaff',
-    ),
-    'league/mime-type-detection' => 
-    array (
-      'pretty_version' => '1.15.0',
-      'version' => '1.15.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301',
-    ),
-    'lizhichao/one-sm' => 
-    array (
-      'pretty_version' => '1.10',
-      'version' => '1.10.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '687a012a44a5bfd4d9143a0234e1060543be455a',
-    ),
-    'maennchen/zipstream-php' => 
-    array (
-      'pretty_version' => '2.2.6',
-      'version' => '2.2.6.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '30ad6f93cf3efe4192bc7a4c9cad11ff8f4f237f',
-    ),
-    'markbaker/complex' => 
-    array (
-      'pretty_version' => '3.0.2',
-      'version' => '3.0.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '95c56caa1cf5c766ad6d65b6344b807c1e8405b9',
-    ),
-    'markbaker/matrix' => 
-    array (
-      'pretty_version' => '3.0.1',
-      'version' => '3.0.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '728434227fe21be27ff6d86621a1b13107a2562c',
-    ),
-    'monolog/monolog' => 
-    array (
-      'pretty_version' => '2.10.0',
-      'version' => '2.10.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5cf826f2991858b54d5c3809bee745560a1042a7',
-    ),
-    'myclabs/php-enum' => 
-    array (
-      'pretty_version' => '1.8.4',
-      'version' => '1.8.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a867478eae49c9f59ece437ae7f9506bfaa27483',
-    ),
-    'nesbot/carbon' => 
-    array (
-      'pretty_version' => '2.72.5',
-      'version' => '2.72.5.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'afd46589c216118ecd48ff2b95d77596af1e57ed',
-    ),
-    'nette/php-generator' => 
-    array (
-      'pretty_version' => 'v3.6.9',
-      'version' => '3.6.9.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd31782f7bd2ae84ad06f863391ec3fb77ca4d0a6',
-    ),
-    'nette/utils' => 
-    array (
-      'pretty_version' => 'v3.2.10',
-      'version' => '3.2.10.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a4175c62652f2300c8017fb7e640f9ccb11648d2',
-    ),
-    'open-smf/connection-pool' => 
-    array (
-      'pretty_version' => 'v1.0.16',
-      'version' => '1.0.16.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'f70e47dbf56f1869d3207e15825cf38810b865e0',
-    ),
-    'overtrue/socialite' => 
-    array (
-      'pretty_version' => '3.5.4',
-      'version' => '3.5.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '6bd4f0230bcaec5ccfd64a10581a9063233b5a48',
-    ),
-    'overtrue/wechat' => 
-    array (
-      'pretty_version' => '5.30.0',
-      'version' => '5.30.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '245d1e821bc5a4609625c3244b111f570692cfc2',
-    ),
-    'php-http/async-client-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '*',
-      ),
-    ),
-    'php-http/client-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '*',
-      ),
-    ),
-    'phpoffice/phpspreadsheet' => 
-    array (
-      'pretty_version' => '1.29.4',
-      'version' => '1.29.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '7ca7e325dca3adb6a598385aab81f527b8d6c75d',
-    ),
-    'pimple/pimple' => 
-    array (
-      'pretty_version' => 'v3.5.0',
-      'version' => '3.5.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a94b3a4db7fb774b3d78dad2315ddc07629e1bed',
-    ),
-    'psr/cache' => 
-    array (
-      'pretty_version' => '1.0.1',
-      'version' => '1.0.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
-    ),
-    'psr/cache-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0|2.0',
-      ),
-    ),
-    'psr/clock' => 
-    array (
-      'pretty_version' => '1.0.0',
-      'version' => '1.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d',
-    ),
-    'psr/clock-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0',
-      ),
-    ),
-    'psr/container' => 
-    array (
-      'pretty_version' => '1.1.2',
-      'version' => '1.1.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
-    ),
-    'psr/event-dispatcher' => 
-    array (
-      'pretty_version' => '1.0.0',
-      'version' => '1.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0',
-    ),
-    'psr/event-dispatcher-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0',
-      ),
-    ),
-    'psr/http-client' => 
-    array (
-      'pretty_version' => '1.0.3',
-      'version' => '1.0.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90',
-    ),
-    'psr/http-client-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0',
-      ),
-    ),
-    'psr/http-factory' => 
-    array (
-      'pretty_version' => '1.0.2',
-      'version' => '1.0.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e616d01114759c4c489f93b099585439f795fe35',
-    ),
-    'psr/http-factory-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0',
-      ),
-    ),
-    'psr/http-message' => 
-    array (
-      'pretty_version' => '1.1',
-      'version' => '1.1.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba',
-    ),
-    'psr/http-message-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0',
-      ),
-    ),
-    'psr/log' => 
-    array (
-      'pretty_version' => '1.1.4',
-      'version' => '1.1.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
-    ),
-    'psr/log-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0.0 || 2.0.0 || 3.0.0',
-      ),
-    ),
-    'psr/simple-cache' => 
-    array (
-      'pretty_version' => '1.0.1',
-      'version' => '1.0.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
-    ),
-    'psr/simple-cache-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0|2.0',
-      ),
-    ),
-    'qcloud/cos-sdk-v5' => 
-    array (
-      'pretty_version' => 'v2.6.15',
-      'version' => '2.6.15.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '17b973a388dc8848947054daace0fff8d2a4eee0',
-    ),
-    'qiniu/php-sdk' => 
-    array (
-      'pretty_version' => 'v7.14.0',
-      'version' => '7.14.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'ee752ffa7263ce99fca0bd7340cf13c486a3516c',
-    ),
-    'ralouphie/getallheaders' => 
-    array (
-      'pretty_version' => '3.0.3',
-      'version' => '3.0.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '120b605dfeb996808c31b6477290a714d356e822',
-    ),
-    'react/promise' => 
-    array (
-      'pretty_version' => 'v2.11.0',
-      'version' => '2.11.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '1a8460931ea36dc5c76838fec5734d55c88c6831',
-    ),
-    'stechstudio/backoff' => 
-    array (
-      'pretty_version' => '1.2.1',
-      'version' => '1.2.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '7204cddf3f1afcd5368d74d52f4d8c447c5dc311',
-    ),
-    'swoole/ide-helper' => 
-    array (
-      'pretty_version' => '4.8.13',
-      'version' => '4.8.13.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd100c446b2e3d56430cbcab5dc3fa20a9f35c4ef',
-    ),
-    'symfony/cache' => 
-    array (
-      'pretty_version' => 'v5.4.46',
-      'version' => '5.4.46.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '0fe08ee32cec2748fbfea10c52d3ee02049e0f6b',
-    ),
-    'symfony/cache-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.4',
-      'version' => '2.5.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '517c3a3619dadfa6952c4651767fcadffb4df65e',
-    ),
-    'symfony/cache-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0|2.0',
-      ),
-    ),
-    'symfony/deprecation-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.3',
-      'version' => '2.5.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '80d075412b557d41002320b96a096ca65aa2c98d',
-    ),
-    'symfony/event-dispatcher' => 
-    array (
-      'pretty_version' => 'v5.4.45',
-      'version' => '5.4.45.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '72982eb416f61003e9bb6e91f8b3213600dcf9e9',
-    ),
-    'symfony/event-dispatcher-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.4',
-      'version' => '2.5.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f',
-    ),
-    'symfony/event-dispatcher-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '2.0',
-      ),
-    ),
-    'symfony/finder' => 
-    array (
-      'pretty_version' => 'v5.4.45',
-      'version' => '5.4.45.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '63741784cd7b9967975eec610b256eed3ede022b',
-    ),
-    'symfony/http-client' => 
-    array (
-      'pretty_version' => 'v5.4.47',
-      'version' => '5.4.47.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '3b643b83f87e1765d2e9b1e946bb56ee0b4b7bde',
-    ),
-    'symfony/http-client-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.3',
-      'version' => '2.5.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e5cc97c2b4a4db0ba26bebc154f1426e3fd1d2f1',
-    ),
-    'symfony/http-client-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '2.4',
-      ),
-    ),
-    'symfony/http-foundation' => 
-    array (
-      'pretty_version' => 'v5.4.48',
-      'version' => '5.4.48.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '3f38b8af283b830e1363acd79e5bc3412d055341',
-    ),
-    'symfony/polyfill-mbstring' => 
-    array (
-      'pretty_version' => 'v1.31.0',
-      'version' => '1.31.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '85181ba99b2345b0ef10ce42ecac37612d9fd341',
-    ),
-    'symfony/polyfill-php72' => 
-    array (
-      'pretty_version' => 'v1.31.0',
-      'version' => '1.31.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce',
-    ),
-    'symfony/polyfill-php73' => 
-    array (
-      'pretty_version' => 'v1.31.0',
-      'version' => '1.31.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '0f68c03565dcaaf25a890667542e8bd75fe7e5bb',
-    ),
-    'symfony/polyfill-php80' => 
-    array (
-      'pretty_version' => 'v1.31.0',
-      'version' => '1.31.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '60328e362d4c2c802a54fcbf04f9d3fb892b4cf8',
-    ),
-    'symfony/process' => 
-    array (
-      'pretty_version' => 'v5.4.46',
-      'version' => '5.4.46.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '01906871cb9b5e3cf872863b91aba4ec9767daf4',
-    ),
-    'symfony/psr-http-message-bridge' => 
-    array (
-      'pretty_version' => 'v2.3.1',
-      'version' => '2.3.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '581ca6067eb62640de5ff08ee1ba6850a0ee472e',
-    ),
-    'symfony/service-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.3',
-      'version' => '2.5.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a2329596ddc8fd568900e3fc76cba42489ecc7f3',
-    ),
-    'symfony/translation' => 
-    array (
-      'pretty_version' => 'v5.4.45',
-      'version' => '5.4.45.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '98f26acc99341ca4bab345fb14d7b1d7cb825bed',
-    ),
-    'symfony/translation-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.3',
-      'version' => '2.5.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'b0073a77ac0b7ea55131020e87b1e3af540f4664',
-    ),
-    'symfony/translation-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '2.3',
-      ),
-    ),
-    'symfony/var-dumper' => 
-    array (
-      'pretty_version' => 'v4.4.47',
-      'version' => '4.4.47.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '1069c7a3fca74578022fab6f81643248d02f8e63',
-    ),
-    'symfony/var-exporter' => 
-    array (
-      'pretty_version' => 'v5.4.45',
-      'version' => '5.4.45.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '862700068db0ddfd8c5b850671e029a90246ec75',
-    ),
-    'topthink/framework' => 
-    array (
-      'pretty_version' => 'v6.1.4',
-      'version' => '6.1.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '66eb9cf4d627df12911344cd328faf9bb596bf2c',
-    ),
-    'topthink/think' => 
-    array (
-      'pretty_version' => 'dev-master',
-      'version' => 'dev-master',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'b4d08155eb79c5471dc034238c7896deaeaff6a5',
-    ),
-    'topthink/think-captcha' => 
-    array (
-      'pretty_version' => 'v3.0.9',
-      'version' => '3.0.9.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'b1ef360670578214edeebcf824aaf6ab7ee0528b',
-    ),
-    'topthink/think-filesystem' => 
-    array (
-      'pretty_version' => 'v1.0.3',
-      'version' => '1.0.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '29f19f140a9267c717fecd7ccb22c84c2d72382e',
-    ),
-    'topthink/think-helper' => 
-    array (
-      'pretty_version' => 'v3.1.8',
-      'version' => '3.1.8.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '612eea76eec2a22f41b0e24be27f49454e4fd5f5',
-    ),
-    'topthink/think-image' => 
-    array (
-      'pretty_version' => 'v1.0.7',
-      'version' => '1.0.7.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '8586cf47f117481c6d415b20f7dedf62e79d5512',
-    ),
-    'topthink/think-orm' => 
-    array (
-      'pretty_version' => 'v2.0.62',
-      'version' => '2.0.62.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e53bfea572a133039ad687077120de5521af617f',
-    ),
-    'topthink/think-queue' => 
-    array (
-      'pretty_version' => 'v3.0.9',
-      'version' => '3.0.9.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '654812b47dd7c708c4443deed27f212f8382e8da',
-    ),
-    'topthink/think-swoole' => 
-    array (
-      'pretty_version' => 'v4.0.9',
-      'version' => '4.0.9.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'edc326d92fc738c290d5777f0c544477759fa7f3',
-    ),
-    'topthink/think-trace' => 
-    array (
-      'pretty_version' => 'v1.6',
-      'version' => '1.6.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '136cd5d97e8bdb780e4b5c1637c588ed7ca3e142',
-    ),
-    'yurunsoft/composer-include-files' => 
-    array (
-      'pretty_version' => 'v2.0.0',
-      'version' => '2.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '277ed077b85d7a9d7b6b73ff148a48d9d676218d',
-    ),
-    'yurunsoft/guzzle-swoole' => 
-    array (
-      'pretty_version' => 'v2.2.4',
-      'version' => '2.2.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '89bb58446aa0a3d6448de3943b40a5d79b18cbda',
-    ),
-    'yurunsoft/yurun-http' => 
-    array (
-      'pretty_version' => 'v4.4.4',
-      'version' => '4.4.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '427d17c1e870d67e47a51ddd231932da2b041b5c',
-    ),
-  ),
-);
-private static $canGetVendors;
-private static $installedByVendor = array();
-
-
-
-
-
-
-
-public static function getInstalledPackages()
-{
-$packages = array();
-foreach (self::getInstalled() as $installed) {
-$packages[] = array_keys($installed['versions']);
-}
-
-if (1 === \count($packages)) {
-return $packages[0];
-}
-
-return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
-}
-
-
-
-
-
-
-
-
-
-public static function isInstalled($packageName)
-{
-foreach (self::getInstalled() as $installed) {
-if (isset($installed['versions'][$packageName])) {
-return true;
-}
-}
-
-return false;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-public static function satisfies(VersionParser $parser, $packageName, $constraint)
-{
-$constraint = $parser->parseConstraints($constraint);
-$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
-
-return $provided->matches($constraint);
-}
-
-
-
-
-
-
-
-
-
-
-public static function getVersionRanges($packageName)
-{
-foreach (self::getInstalled() as $installed) {
-if (!isset($installed['versions'][$packageName])) {
-continue;
-}
-
-$ranges = array();
-if (isset($installed['versions'][$packageName]['pretty_version'])) {
-$ranges[] = $installed['versions'][$packageName]['pretty_version'];
-}
-if (array_key_exists('aliases', $installed['versions'][$packageName])) {
-$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
-}
-if (array_key_exists('replaced', $installed['versions'][$packageName])) {
-$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
-}
-if (array_key_exists('provided', $installed['versions'][$packageName])) {
-$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
-}
-
-return implode(' || ', $ranges);
-}
-
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-
-
-
-
-public static function getVersion($packageName)
-{
-foreach (self::getInstalled() as $installed) {
-if (!isset($installed['versions'][$packageName])) {
-continue;
-}
-
-if (!isset($installed['versions'][$packageName]['version'])) {
-return null;
-}
-
-return $installed['versions'][$packageName]['version'];
-}
-
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-
-
-
-
-public static function getPrettyVersion($packageName)
-{
-foreach (self::getInstalled() as $installed) {
-if (!isset($installed['versions'][$packageName])) {
-continue;
-}
-
-if (!isset($installed['versions'][$packageName]['pretty_version'])) {
-return null;
-}
-
-return $installed['versions'][$packageName]['pretty_version'];
-}
-
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-
-
-
-
-public static function getReference($packageName)
-{
-foreach (self::getInstalled() as $installed) {
-if (!isset($installed['versions'][$packageName])) {
-continue;
-}
-
-if (!isset($installed['versions'][$packageName]['reference'])) {
-return null;
-}
-
-return $installed['versions'][$packageName]['reference'];
-}
-
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-
-
-
-
-public static function getRootPackage()
-{
-$installed = self::getInstalled();
-
-return $installed[0]['root'];
-}
-
-
-
-
-
-
-
-
-public static function getRawData()
-{
-@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
-
-return self::$installed;
-}
-
-
-
-
-
-
-
-public static function getAllRawData()
-{
-return self::getInstalled();
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-public static function reload($data)
-{
-self::$installed = $data;
-self::$installedByVendor = array();
-}
-
-
-
-
-
-private static function getInstalled()
-{
-if (null === self::$canGetVendors) {
-self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
-}
-
-$installed = array();
-
-if (self::$canGetVendors) {
-foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
-if (isset(self::$installedByVendor[$vendorDir])) {
-$installed[] = self::$installedByVendor[$vendorDir];
-} elseif (is_file($vendorDir.'/composer/installed.php')) {
-$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
-}
-}
-}
-
-$installed[] = self::$installed;
-
-return $installed;
-}
+    /**
+     * @var mixed[]|null
+     * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
+     */
+    private static $installed;
+
+    /**
+     * @var bool|null
+     */
+    private static $canGetVendors;
+
+    /**
+     * @var array[]
+     * @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
+     */
+    private static $installedByVendor = array();
+
+    /**
+     * Returns a list of all package names which are present, either by being installed, replaced or provided
+     *
+     * @return string[]
+     * @psalm-return list<string>
+     */
+    public static function getInstalledPackages()
+    {
+        $packages = array();
+        foreach (self::getInstalled() as $installed) {
+            $packages[] = array_keys($installed['versions']);
+        }
+
+        if (1 === \count($packages)) {
+            return $packages[0];
+        }
+
+        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
+    }
+
+    /**
+     * Returns a list of all package names with a specific type e.g. 'library'
+     *
+     * @param  string   $type
+     * @return string[]
+     * @psalm-return list<string>
+     */
+    public static function getInstalledPackagesByType($type)
+    {
+        $packagesByType = array();
+
+        foreach (self::getInstalled() as $installed) {
+            foreach ($installed['versions'] as $name => $package) {
+                if (isset($package['type']) && $package['type'] === $type) {
+                    $packagesByType[] = $name;
+                }
+            }
+        }
+
+        return $packagesByType;
+    }
+
+    /**
+     * Checks whether the given package is installed
+     *
+     * This also returns true if the package name is provided or replaced by another package
+     *
+     * @param  string $packageName
+     * @param  bool   $includeDevRequirements
+     * @return bool
+     */
+    public static function isInstalled($packageName, $includeDevRequirements = true)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (isset($installed['versions'][$packageName])) {
+                return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Checks whether the given package satisfies a version constraint
+     *
+     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
+     *
+     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
+     *
+     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
+     * @param  string        $packageName
+     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
+     * @return bool
+     */
+    public static function satisfies(VersionParser $parser, $packageName, $constraint)
+    {
+        $constraint = $parser->parseConstraints((string) $constraint);
+        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
+
+        return $provided->matches($constraint);
+    }
+
+    /**
+     * Returns a version constraint representing all the range(s) which are installed for a given package
+     *
+     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
+     * whether a given version of a package is installed, and not just whether it exists
+     *
+     * @param  string $packageName
+     * @return string Version constraint usable with composer/semver
+     */
+    public static function getVersionRanges($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            $ranges = array();
+            if (isset($installed['versions'][$packageName]['pretty_version'])) {
+                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
+            }
+            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
+            }
+            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
+            }
+            if (array_key_exists('provided', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
+            }
+
+            return implode(' || ', $ranges);
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+     */
+    public static function getVersion($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['version'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['version'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+     */
+    public static function getPrettyVersion($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['pretty_version'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
+     */
+    public static function getReference($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['reference'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['reference'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
+     */
+    public static function getInstallPath($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @return array
+     * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
+     */
+    public static function getRootPackage()
+    {
+        $installed = self::getInstalled();
+
+        return $installed[0]['root'];
+    }
+
+    /**
+     * Returns the raw installed.php data for custom implementations
+     *
+     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
+     * @return array[]
+     * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
+     */
+    public static function getRawData()
+    {
+        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
+
+        if (null === self::$installed) {
+            // only require the installed.php file if this file is loaded from its dumped location,
+            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+            if (substr(__DIR__, -8, 1) !== 'C') {
+                self::$installed = include __DIR__ . '/installed.php';
+            } else {
+                self::$installed = array();
+            }
+        }
+
+        return self::$installed;
+    }
+
+    /**
+     * Returns the raw data of all installed.php which are currently loaded for custom implementations
+     *
+     * @return array[]
+     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
+     */
+    public static function getAllRawData()
+    {
+        return self::getInstalled();
+    }
+
+    /**
+     * Lets you reload the static array from another file
+     *
+     * This is only useful for complex integrations in which a project needs to use
+     * this class but then also needs to execute another project's autoloader in process,
+     * and wants to ensure both projects have access to their version of installed.php.
+     *
+     * A typical case would be PHPUnit, where it would need to make sure it reads all
+     * the data it needs from this class, then call reload() with
+     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
+     * the project in which it runs can then also use this class safely, without
+     * interference between PHPUnit's dependencies and the project's dependencies.
+     *
+     * @param  array[] $data A vendor/composer/installed.php data set
+     * @return void
+     *
+     * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
+     */
+    public static function reload($data)
+    {
+        self::$installed = $data;
+        self::$installedByVendor = array();
+    }
+
+    /**
+     * @return array[]
+     * @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
+     */
+    private static function getInstalled()
+    {
+        if (null === self::$canGetVendors) {
+            self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
+        }
+
+        $installed = array();
+
+        if (self::$canGetVendors) {
+            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+                if (isset(self::$installedByVendor[$vendorDir])) {
+                    $installed[] = self::$installedByVendor[$vendorDir];
+                } elseif (is_file($vendorDir.'/composer/installed.php')) {
+                    /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
+                    $required = require $vendorDir.'/composer/installed.php';
+                    $installed[] = self::$installedByVendor[$vendorDir] = $required;
+                    if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
+                        self::$installed = $installed[count($installed) - 1];
+                    }
+                }
+            }
+        }
+
+        if (null === self::$installed) {
+            // only require the installed.php file if this file is loaded from its dumped location,
+            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+            if (substr(__DIR__, -8, 1) !== 'C') {
+                /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
+                $required = require __DIR__ . '/installed.php';
+                self::$installed = $required;
+            } else {
+                self::$installed = array();
+            }
+        }
+
+        if (self::$installed !== array()) {
+            $installed[] = self::$installed;
+        }
+
+        return $installed;
+    }
 }

+ 1 - 1
vendor/composer/autoload_classmap.php

@@ -2,7 +2,7 @@
 
 // autoload_classmap.php @generated by Composer
 
-$vendorDir = dirname(dirname(__FILE__));
+$vendorDir = dirname(__DIR__);
 $baseDir = dirname($vendorDir);
 
 return array(

+ 8 - 8
vendor/composer/autoload_files.php

@@ -6,28 +6,28 @@ $vendorDir = dirname(dirname(__FILE__));
 $baseDir = dirname($vendorDir);
 
 return array(
-    '64f378e945bba50f3c846efbde8847c0' => $vendorDir . '/yurunsoft/guzzle-swoole/src/load_include.php',
-    'ada7bc8b2ef932c0b597f9e326f0e977' => $vendorDir . '/yurunsoft/guzzle-swoole/src/functions.php',
-    'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
+    '9cd13ce3f85590ee0c2a997889ace94b' => $vendorDir . '/yurunsoft/guzzle-swoole/src/load_include.php',
+    '01b1fc10a3134b90c4e9d3887c69cb63' => $vendorDir . '/yurunsoft/guzzle-swoole/src/functions.php',
     '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
-    '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
     '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
-    '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
     '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
+    'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
     'd767e4fc2dc52fe66584ab8c6684783e' => $vendorDir . '/adbario/php-dot-notation/src/helpers.php',
-    '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
+    '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
     '9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
     '35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php',
-    'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
+    '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
     'ad155f8f1cf0d418fe49e248db8c661b' => $vendorDir . '/react/promise/src/functions_include.php',
+    'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
     '2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
     '9a31621970d4295d5f00acf4e277e6f9' => $vendorDir . '/stechstudio/backoff/src/helpers.php',
-    'cc56288302d9df745d97c934d6a6e5f0' => $vendorDir . '/topthink/think-queue/src/common.php',
     'f0e7e63bbb278a92db02393536748c5f' => $vendorDir . '/overtrue/wechat/src/Kernel/Support/Helpers.php',
     '6747f579ad6817f318cc3a7e7a0abb93' => $vendorDir . '/overtrue/wechat/src/Kernel/Helpers.php',
     'cd5441689b14144e5573bf989ee47b34' => $vendorDir . '/qcloud/cos-sdk-v5/src/Common.php',
     '841780ea2e1d6545ea3a253239d59c05' => $vendorDir . '/qiniu/php-sdk/src/Qiniu/functions.php',
     '5dd19d8a547b7318af0c3a93c8bd6565' => $vendorDir . '/qiniu/php-sdk/src/Qiniu/Http/Middleware/Middleware.php',
+    '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
     '1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php',
+    'cc56288302d9df745d97c934d6a6e5f0' => $vendorDir . '/topthink/think-queue/src/common.php',
     'af46dcea2921209ac30627b964175f13' => $vendorDir . '/topthink/think-swoole/src/helpers.php',
 );

+ 1 - 1
vendor/composer/autoload_namespaces.php

@@ -2,7 +2,7 @@
 
 // autoload_namespaces.php @generated by Composer
 
-$vendorDir = dirname(dirname(__FILE__));
+$vendorDir = dirname(__DIR__);
 $baseDir = dirname($vendorDir);
 
 return array(

+ 1 - 1
vendor/composer/autoload_psr4.php

@@ -2,7 +2,7 @@
 
 // autoload_psr4.php @generated by Composer
 
-$vendorDir = dirname(dirname(__FILE__));
+$vendorDir = dirname(__DIR__);
 $baseDir = dirname($vendorDir);
 
 return array(

+ 12 - 37
vendor/composer/autoload_real.php

@@ -25,51 +25,26 @@ class ComposerAutoloaderInit0ef01221f70f4fb275871418332d8a66
         require __DIR__ . '/platform_check.php';
 
         spl_autoload_register(array('ComposerAutoloaderInit0ef01221f70f4fb275871418332d8a66', 'loadClassLoader'), true, true);
-        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
+        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
         spl_autoload_unregister(array('ComposerAutoloaderInit0ef01221f70f4fb275871418332d8a66', 'loadClassLoader'));
 
-        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
-        if ($useStaticLoader) {
-            require __DIR__ . '/autoload_static.php';
+        require __DIR__ . '/autoload_static.php';
+        call_user_func(\Composer\Autoload\ComposerStaticInit0ef01221f70f4fb275871418332d8a66::getInitializer($loader));
 
-            call_user_func(\Composer\Autoload\ComposerStaticInit0ef01221f70f4fb275871418332d8a66::getInitializer($loader));
-        } else {
-            $map = require __DIR__ . '/autoload_namespaces.php';
-            foreach ($map as $namespace => $path) {
-                $loader->set($namespace, $path);
-            }
+        $loader->register(true);
 
-            $map = require __DIR__ . '/autoload_psr4.php';
-            foreach ($map as $namespace => $path) {
-                $loader->setPsr4($namespace, $path);
-            }
+        $filesToLoad = \Composer\Autoload\ComposerStaticInit0ef01221f70f4fb275871418332d8a66::$files;
+        $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
+            if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+                $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
 
-            $classMap = require __DIR__ . '/autoload_classmap.php';
-            if ($classMap) {
-                $loader->addClassMap($classMap);
+                require $file;
             }
-        }
-
-        $loader->register(true);
-
-        if ($useStaticLoader) {
-            $includeFiles = Composer\Autoload\ComposerStaticInit0ef01221f70f4fb275871418332d8a66::$files;
-        } else {
-            $includeFiles = require __DIR__ . '/autoload_files.php';
-        }
-        foreach ($includeFiles as $fileIdentifier => $file) {
-            composerRequire0ef01221f70f4fb275871418332d8a66($fileIdentifier, $file);
+        }, null, null);
+        foreach ($filesToLoad as $fileIdentifier => $file) {
+            $requireFile($fileIdentifier, $file);
         }
 
         return $loader;
     }
 }
-
-function composerRequire0ef01221f70f4fb275871418332d8a66($fileIdentifier, $file)
-{
-    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
-        require $file;
-
-        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
-    }
-}

+ 8 - 8
vendor/composer/autoload_static.php

@@ -7,29 +7,29 @@ namespace Composer\Autoload;
 class ComposerStaticInit0ef01221f70f4fb275871418332d8a66
 {
     public static $files = array (
-        '64f378e945bba50f3c846efbde8847c0' => __DIR__ . '/..' . '/yurunsoft/guzzle-swoole/src/load_include.php',
-        'ada7bc8b2ef932c0b597f9e326f0e977' => __DIR__ . '/..' . '/yurunsoft/guzzle-swoole/src/functions.php',
-        'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
+        '9cd13ce3f85590ee0c2a997889ace94b' => __DIR__ . '/..' . '/yurunsoft/guzzle-swoole/src/load_include.php',
+        '01b1fc10a3134b90c4e9d3887c69cb63' => __DIR__ . '/..' . '/yurunsoft/guzzle-swoole/src/functions.php',
         '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
-        '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
         '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
-        '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
         '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
+        'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
         'd767e4fc2dc52fe66584ab8c6684783e' => __DIR__ . '/..' . '/adbario/php-dot-notation/src/helpers.php',
-        '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
+        '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
         '9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
         '35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php',
-        'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
+        '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
         'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
+        'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
         '2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
         '9a31621970d4295d5f00acf4e277e6f9' => __DIR__ . '/..' . '/stechstudio/backoff/src/helpers.php',
-        'cc56288302d9df745d97c934d6a6e5f0' => __DIR__ . '/..' . '/topthink/think-queue/src/common.php',
         'f0e7e63bbb278a92db02393536748c5f' => __DIR__ . '/..' . '/overtrue/wechat/src/Kernel/Support/Helpers.php',
         '6747f579ad6817f318cc3a7e7a0abb93' => __DIR__ . '/..' . '/overtrue/wechat/src/Kernel/Helpers.php',
         'cd5441689b14144e5573bf989ee47b34' => __DIR__ . '/..' . '/qcloud/cos-sdk-v5/src/Common.php',
         '841780ea2e1d6545ea3a253239d59c05' => __DIR__ . '/..' . '/qiniu/php-sdk/src/Qiniu/functions.php',
         '5dd19d8a547b7318af0c3a93c8bd6565' => __DIR__ . '/..' . '/qiniu/php-sdk/src/Qiniu/Http/Middleware/Middleware.php',
+        '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
         '1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
+        'cc56288302d9df745d97c934d6a6e5f0' => __DIR__ . '/..' . '/topthink/think-queue/src/common.php',
         'af46dcea2921209ac30627b964175f13' => __DIR__ . '/..' . '/topthink/think-swoole/src/helpers.php',
     );
 

+ 969 - 984
vendor/composer/installed.php

@@ -1,986 +1,971 @@
-<?php return array (
-  'root' => 
-  array (
-    'pretty_version' => 'dev-master',
-    'version' => 'dev-master',
-    'aliases' => 
-    array (
+<?php return array(
+    'root' => array(
+        'name' => 'topthink/think',
+        'pretty_version' => 'dev-master',
+        'version' => 'dev-master',
+        'reference' => '26dc268aa174e424bd5abe3b648734c22aa0a437',
+        'type' => 'project',
+        'install_path' => __DIR__ . '/../../',
+        'aliases' => array(),
+        'dev' => true,
+    ),
+    'versions' => array(
+        'adbario/php-dot-notation' => array(
+            'pretty_version' => '2.5.0',
+            'version' => '2.5.0.0',
+            'reference' => '081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../adbario/php-dot-notation',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'alibabacloud/credentials' => array(
+            'pretty_version' => '1.2.0',
+            'version' => '1.2.0.0',
+            'reference' => 'ebcda2e628180b4df235b46a86e1d014c561f5d9',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../alibabacloud/credentials',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'alibabacloud/darabonba-openapi' => array(
+            'pretty_version' => '0.2.13',
+            'version' => '0.2.13.0',
+            'reference' => '0213396384e2c064eefd614f3dd53636a63f987f',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../alibabacloud/darabonba-openapi',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'alibabacloud/dysmsapi-20170525' => array(
+            'pretty_version' => '3.1.0',
+            'version' => '3.1.0.0',
+            'reference' => '5f779cf8d6d8807b9835bff8d058dbab6d59bbf1',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../alibabacloud/dysmsapi-20170525',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'alibabacloud/endpoint-util' => array(
+            'pretty_version' => '0.1.1',
+            'version' => '0.1.1.0',
+            'reference' => 'f3fe88a25d8df4faa3b0ae14ff202a9cc094e6c5',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../alibabacloud/endpoint-util',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'alibabacloud/gateway-spi' => array(
+            'pretty_version' => '1.0.0',
+            'version' => '1.0.0.0',
+            'reference' => '7440f77750c329d8ab252db1d1d967314ccd1fcb',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../alibabacloud/gateway-spi',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'alibabacloud/openapi-util' => array(
+            'pretty_version' => '0.2.1',
+            'version' => '0.2.1.0',
+            'reference' => 'f31f7bcd835e08ca24b6b8ba33637eb4eceb093a',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../alibabacloud/openapi-util',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'alibabacloud/tea' => array(
+            'pretty_version' => '3.2.1',
+            'version' => '3.2.1.0',
+            'reference' => '1619cb96c158384f72b873e1f85de8b299c9c367',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../alibabacloud/tea',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'alibabacloud/tea-fileform' => array(
+            'pretty_version' => '0.3.4',
+            'version' => '0.3.4.0',
+            'reference' => '4bf0c75a045c8115aa8cb1a394bd08d8bb833181',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../alibabacloud/tea-fileform',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'alibabacloud/tea-utils' => array(
+            'pretty_version' => '0.2.21',
+            'version' => '0.2.21.0',
+            'reference' => '5039e45714c6456186d267f5d81a4b260a652495',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../alibabacloud/tea-utils',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'alibabacloud/tea-xml' => array(
+            'pretty_version' => '0.2.4',
+            'version' => '0.2.4.0',
+            'reference' => '3e0c000bf536224eebbac913c371bef174c0a16a',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../alibabacloud/tea-xml',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'alipaysdk/easysdk' => array(
+            'pretty_version' => '2.2.3',
+            'version' => '2.2.3.0',
+            'reference' => 'c6008839a22a5fca08e9f8536730f7abfed522d5',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../alipaysdk/easysdk',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'aliyuncs/oss-sdk-php' => array(
+            'pretty_version' => 'v2.7.2',
+            'version' => '2.7.2.0',
+            'reference' => '483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../aliyuncs/oss-sdk-php',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'async-aws/core' => array(
+            'pretty_version' => '1.21.0',
+            'version' => '1.21.0.0',
+            'reference' => 'eb23cc59515d8d529163313bbf9e02f666e515ef',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../async-aws/core',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'bacon/bacon-qr-code' => array(
+            'pretty_version' => '2.0.8',
+            'version' => '2.0.8.0',
+            'reference' => '8674e51bb65af933a5ffaf1c308a660387c35c22',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../bacon/bacon-qr-code',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'carbonphp/carbon-doctrine-types' => array(
+            'pretty_version' => '2.1.0',
+            'version' => '2.1.0.0',
+            'reference' => '99f76ffa36cce3b70a4a6abce41dba15ca2e84cb',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../carbonphp/carbon-doctrine-types',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'dasprid/enum' => array(
+            'pretty_version' => '1.0.5',
+            'version' => '1.0.5.0',
+            'reference' => '6faf451159fb8ba4126b925ed2d78acfce0dc016',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../dasprid/enum',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'easywechat-composer/easywechat-composer' => array(
+            'pretty_version' => '1.4.1',
+            'version' => '1.4.1.0',
+            'reference' => '3fc6a7ab6d3853c0f4e2922539b56cc37ef361cd',
+            'type' => 'composer-plugin',
+            'install_path' => __DIR__ . '/../easywechat-composer/easywechat-composer',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'endroid/qr-code' => array(
+            'pretty_version' => '4.6.1',
+            'version' => '4.6.1.0',
+            'reference' => 'a75c913b0e4d6ad275e49a2c1de1cacffc6c2184',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../endroid/qr-code',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'ezyang/htmlpurifier' => array(
+            'pretty_version' => 'v4.18.0',
+            'version' => '4.18.0.0',
+            'reference' => 'cb56001e54359df7ae76dc522d08845dc741621b',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../ezyang/htmlpurifier',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'fastknife/ajcaptcha' => array(
+            'pretty_version' => 'v1.2.2',
+            'version' => '1.2.2.0',
+            'reference' => '87c122b6cd950fd98702e929685e5e7c0c517ddc',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../fastknife/ajcaptcha',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'firebase/php-jwt' => array(
+            'pretty_version' => 'v6.10.0',
+            'version' => '6.10.0.0',
+            'reference' => 'a49db6f0a5033aef5143295342f1c95521b075ff',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../firebase/php-jwt',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'guzzlehttp/command' => array(
+            'pretty_version' => '1.3.1',
+            'version' => '1.3.1.0',
+            'reference' => '0eebc653784f4902b3272e826fe8e88743d14e77',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../guzzlehttp/command',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'guzzlehttp/guzzle' => array(
+            'pretty_version' => '7.9.2',
+            'version' => '7.9.2.0',
+            'reference' => 'd281ed313b989f213357e3be1a179f02196ac99b',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../guzzlehttp/guzzle',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'guzzlehttp/guzzle-services' => array(
+            'pretty_version' => '1.4.1',
+            'version' => '1.4.1.0',
+            'reference' => 'bcab7c0d61672b606510a6fe5af3039d04968c0f',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../guzzlehttp/guzzle-services',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'guzzlehttp/promises' => array(
+            'pretty_version' => '2.0.3',
+            'version' => '2.0.3.0',
+            'reference' => '6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../guzzlehttp/promises',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'guzzlehttp/psr7' => array(
+            'pretty_version' => '2.7.0',
+            'version' => '2.7.0.0',
+            'reference' => 'a70f5c95fb43bc83f07c9c948baa0dc1829bf201',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../guzzlehttp/psr7',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'guzzlehttp/ringphp' => array(
+            'pretty_version' => '1.1.1',
+            'version' => '1.1.1.0',
+            'reference' => '5e2a174052995663dd68e6b5ad838afd47dd615b',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../guzzlehttp/ringphp',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'guzzlehttp/streams' => array(
+            'pretty_version' => '3.0.0',
+            'version' => '3.0.0.0',
+            'reference' => '47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../guzzlehttp/streams',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'guzzlehttp/uri-template' => array(
+            'pretty_version' => 'v1.0.3',
+            'version' => '1.0.3.0',
+            'reference' => 'ecea8feef63bd4fef1f037ecb288386999ecc11c',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../guzzlehttp/uri-template',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'intervention/image' => array(
+            'pretty_version' => '2.7.2',
+            'version' => '2.7.2.0',
+            'reference' => '04be355f8d6734c826045d02a1079ad658322dad',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../intervention/image',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'joypack/tencent-map' => array(
+            'pretty_version' => '1.0.0',
+            'version' => '1.0.0.0',
+            'reference' => '97c0269086d53dbecb9c3c6e1d2717645d7940a8',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../joypack/tencent-map',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'league/flysystem' => array(
+            'pretty_version' => '1.1.10',
+            'version' => '1.1.10.0',
+            'reference' => '3239285c825c152bcc315fe0e87d6b55f5972ed1',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../league/flysystem',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'league/flysystem-cached-adapter' => array(
+            'pretty_version' => '1.1.0',
+            'version' => '1.1.0.0',
+            'reference' => 'd1925efb2207ac4be3ad0c40b8277175f99ffaff',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../league/flysystem-cached-adapter',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'league/mime-type-detection' => array(
+            'pretty_version' => '1.15.0',
+            'version' => '1.15.0.0',
+            'reference' => 'ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../league/mime-type-detection',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'lizhichao/one-sm' => array(
+            'pretty_version' => '1.10',
+            'version' => '1.10.0.0',
+            'reference' => '687a012a44a5bfd4d9143a0234e1060543be455a',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../lizhichao/one-sm',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'maennchen/zipstream-php' => array(
+            'pretty_version' => '2.2.6',
+            'version' => '2.2.6.0',
+            'reference' => '30ad6f93cf3efe4192bc7a4c9cad11ff8f4f237f',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../maennchen/zipstream-php',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'markbaker/complex' => array(
+            'pretty_version' => '3.0.2',
+            'version' => '3.0.2.0',
+            'reference' => '95c56caa1cf5c766ad6d65b6344b807c1e8405b9',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../markbaker/complex',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'markbaker/matrix' => array(
+            'pretty_version' => '3.0.1',
+            'version' => '3.0.1.0',
+            'reference' => '728434227fe21be27ff6d86621a1b13107a2562c',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../markbaker/matrix',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'monolog/monolog' => array(
+            'pretty_version' => '2.10.0',
+            'version' => '2.10.0.0',
+            'reference' => '5cf826f2991858b54d5c3809bee745560a1042a7',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../monolog/monolog',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'myclabs/php-enum' => array(
+            'pretty_version' => '1.8.4',
+            'version' => '1.8.4.0',
+            'reference' => 'a867478eae49c9f59ece437ae7f9506bfaa27483',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../myclabs/php-enum',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'nesbot/carbon' => array(
+            'pretty_version' => '2.72.5',
+            'version' => '2.72.5.0',
+            'reference' => 'afd46589c216118ecd48ff2b95d77596af1e57ed',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../nesbot/carbon',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'nette/php-generator' => array(
+            'pretty_version' => 'v3.6.9',
+            'version' => '3.6.9.0',
+            'reference' => 'd31782f7bd2ae84ad06f863391ec3fb77ca4d0a6',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../nette/php-generator',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'nette/utils' => array(
+            'pretty_version' => 'v3.2.10',
+            'version' => '3.2.10.0',
+            'reference' => 'a4175c62652f2300c8017fb7e640f9ccb11648d2',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../nette/utils',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'open-smf/connection-pool' => array(
+            'pretty_version' => 'v1.0.16',
+            'version' => '1.0.16.0',
+            'reference' => 'f70e47dbf56f1869d3207e15825cf38810b865e0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../open-smf/connection-pool',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'overtrue/socialite' => array(
+            'pretty_version' => '3.5.4',
+            'version' => '3.5.4.0',
+            'reference' => '6bd4f0230bcaec5ccfd64a10581a9063233b5a48',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../overtrue/socialite',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'overtrue/wechat' => array(
+            'pretty_version' => '5.30.0',
+            'version' => '5.30.0.0',
+            'reference' => '245d1e821bc5a4609625c3244b111f570692cfc2',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../overtrue/wechat',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'php-http/async-client-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '*',
+            ),
+        ),
+        'php-http/client-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '*',
+            ),
+        ),
+        'phpoffice/phpspreadsheet' => array(
+            'pretty_version' => '1.29.4',
+            'version' => '1.29.4.0',
+            'reference' => '7ca7e325dca3adb6a598385aab81f527b8d6c75d',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpoffice/phpspreadsheet',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'pimple/pimple' => array(
+            'pretty_version' => 'v3.5.0',
+            'version' => '3.5.0.0',
+            'reference' => 'a94b3a4db7fb774b3d78dad2315ddc07629e1bed',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../pimple/pimple',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'psr/cache' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/cache',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'psr/cache-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '1.0|2.0',
+            ),
+        ),
+        'psr/clock' => array(
+            'pretty_version' => '1.0.0',
+            'version' => '1.0.0.0',
+            'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/clock',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'psr/clock-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '1.0',
+            ),
+        ),
+        'psr/container' => array(
+            'pretty_version' => '1.1.2',
+            'version' => '1.1.2.0',
+            'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/container',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'psr/event-dispatcher' => array(
+            'pretty_version' => '1.0.0',
+            'version' => '1.0.0.0',
+            'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/event-dispatcher',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'psr/event-dispatcher-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '1.0',
+            ),
+        ),
+        'psr/http-client' => array(
+            'pretty_version' => '1.0.3',
+            'version' => '1.0.3.0',
+            'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/http-client',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'psr/http-client-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '1.0',
+            ),
+        ),
+        'psr/http-factory' => array(
+            'pretty_version' => '1.0.2',
+            'version' => '1.0.2.0',
+            'reference' => 'e616d01114759c4c489f93b099585439f795fe35',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/http-factory',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'psr/http-factory-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '1.0',
+            ),
+        ),
+        'psr/http-message' => array(
+            'pretty_version' => '1.1',
+            'version' => '1.1.0.0',
+            'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/http-message',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'psr/http-message-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '1.0',
+            ),
+        ),
+        'psr/log' => array(
+            'pretty_version' => '1.1.4',
+            'version' => '1.1.4.0',
+            'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/log',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'psr/log-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '1.0.0 || 2.0.0 || 3.0.0',
+            ),
+        ),
+        'psr/simple-cache' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/simple-cache',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'psr/simple-cache-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '1.0|2.0',
+            ),
+        ),
+        'qcloud/cos-sdk-v5' => array(
+            'pretty_version' => 'v2.6.15',
+            'version' => '2.6.15.0',
+            'reference' => '17b973a388dc8848947054daace0fff8d2a4eee0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../qcloud/cos-sdk-v5',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'qiniu/php-sdk' => array(
+            'pretty_version' => 'v7.14.0',
+            'version' => '7.14.0.0',
+            'reference' => 'ee752ffa7263ce99fca0bd7340cf13c486a3516c',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../qiniu/php-sdk',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'ralouphie/getallheaders' => array(
+            'pretty_version' => '3.0.3',
+            'version' => '3.0.3.0',
+            'reference' => '120b605dfeb996808c31b6477290a714d356e822',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../ralouphie/getallheaders',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'react/promise' => array(
+            'pretty_version' => 'v2.11.0',
+            'version' => '2.11.0.0',
+            'reference' => '1a8460931ea36dc5c76838fec5734d55c88c6831',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../react/promise',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'stechstudio/backoff' => array(
+            'pretty_version' => '1.2.1',
+            'version' => '1.2.1.0',
+            'reference' => '7204cddf3f1afcd5368d74d52f4d8c447c5dc311',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../stechstudio/backoff',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'swoole/ide-helper' => array(
+            'pretty_version' => '4.8.13',
+            'version' => '4.8.13.0',
+            'reference' => 'd100c446b2e3d56430cbcab5dc3fa20a9f35c4ef',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../swoole/ide-helper',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/cache' => array(
+            'pretty_version' => 'v5.4.46',
+            'version' => '5.4.46.0',
+            'reference' => '0fe08ee32cec2748fbfea10c52d3ee02049e0f6b',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/cache',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/cache-contracts' => array(
+            'pretty_version' => 'v2.5.4',
+            'version' => '2.5.4.0',
+            'reference' => '517c3a3619dadfa6952c4651767fcadffb4df65e',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/cache-contracts',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/cache-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '1.0|2.0',
+            ),
+        ),
+        'symfony/deprecation-contracts' => array(
+            'pretty_version' => 'v2.5.3',
+            'version' => '2.5.3.0',
+            'reference' => '80d075412b557d41002320b96a096ca65aa2c98d',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/event-dispatcher' => array(
+            'pretty_version' => 'v5.4.45',
+            'version' => '5.4.45.0',
+            'reference' => '72982eb416f61003e9bb6e91f8b3213600dcf9e9',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/event-dispatcher',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/event-dispatcher-contracts' => array(
+            'pretty_version' => 'v2.5.4',
+            'version' => '2.5.4.0',
+            'reference' => 'e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/event-dispatcher-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '2.0',
+            ),
+        ),
+        'symfony/finder' => array(
+            'pretty_version' => 'v5.4.45',
+            'version' => '5.4.45.0',
+            'reference' => '63741784cd7b9967975eec610b256eed3ede022b',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/finder',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/http-client' => array(
+            'pretty_version' => 'v5.4.47',
+            'version' => '5.4.47.0',
+            'reference' => '3b643b83f87e1765d2e9b1e946bb56ee0b4b7bde',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/http-client',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/http-client-contracts' => array(
+            'pretty_version' => 'v2.5.3',
+            'version' => '2.5.3.0',
+            'reference' => 'e5cc97c2b4a4db0ba26bebc154f1426e3fd1d2f1',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/http-client-contracts',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/http-client-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '2.4',
+            ),
+        ),
+        'symfony/http-foundation' => array(
+            'pretty_version' => 'v5.4.48',
+            'version' => '5.4.48.0',
+            'reference' => '3f38b8af283b830e1363acd79e5bc3412d055341',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/http-foundation',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/polyfill-mbstring' => array(
+            'pretty_version' => 'v1.31.0',
+            'version' => '1.31.0.0',
+            'reference' => '85181ba99b2345b0ef10ce42ecac37612d9fd341',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/polyfill-php72' => array(
+            'pretty_version' => 'v1.31.0',
+            'version' => '1.31.0.0',
+            'reference' => 'fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce',
+            'type' => 'metapackage',
+            'install_path' => null,
+            'aliases' => array(),
+            'dev_requirement' => true,
+        ),
+        'symfony/polyfill-php73' => array(
+            'pretty_version' => 'v1.31.0',
+            'version' => '1.31.0.0',
+            'reference' => '0f68c03565dcaaf25a890667542e8bd75fe7e5bb',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-php73',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/polyfill-php80' => array(
+            'pretty_version' => 'v1.31.0',
+            'version' => '1.31.0.0',
+            'reference' => '60328e362d4c2c802a54fcbf04f9d3fb892b4cf8',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-php80',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/process' => array(
+            'pretty_version' => 'v5.4.46',
+            'version' => '5.4.46.0',
+            'reference' => '01906871cb9b5e3cf872863b91aba4ec9767daf4',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/process',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/psr-http-message-bridge' => array(
+            'pretty_version' => 'v2.3.1',
+            'version' => '2.3.1.0',
+            'reference' => '581ca6067eb62640de5ff08ee1ba6850a0ee472e',
+            'type' => 'symfony-bridge',
+            'install_path' => __DIR__ . '/../symfony/psr-http-message-bridge',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/service-contracts' => array(
+            'pretty_version' => 'v2.5.3',
+            'version' => '2.5.3.0',
+            'reference' => 'a2329596ddc8fd568900e3fc76cba42489ecc7f3',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/service-contracts',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/translation' => array(
+            'pretty_version' => 'v5.4.45',
+            'version' => '5.4.45.0',
+            'reference' => '98f26acc99341ca4bab345fb14d7b1d7cb825bed',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/translation',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/translation-contracts' => array(
+            'pretty_version' => 'v2.5.3',
+            'version' => '2.5.3.0',
+            'reference' => 'b0073a77ac0b7ea55131020e87b1e3af540f4664',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/translation-contracts',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'symfony/translation-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '2.3',
+            ),
+        ),
+        'symfony/var-dumper' => array(
+            'pretty_version' => 'v4.4.47',
+            'version' => '4.4.47.0',
+            'reference' => '1069c7a3fca74578022fab6f81643248d02f8e63',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/var-dumper',
+            'aliases' => array(),
+            'dev_requirement' => true,
+        ),
+        'symfony/var-exporter' => array(
+            'pretty_version' => 'v5.4.45',
+            'version' => '5.4.45.0',
+            'reference' => '862700068db0ddfd8c5b850671e029a90246ec75',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/var-exporter',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'topthink/framework' => array(
+            'pretty_version' => 'v6.1.4',
+            'version' => '6.1.4.0',
+            'reference' => '66eb9cf4d627df12911344cd328faf9bb596bf2c',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/framework',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'topthink/think' => array(
+            'pretty_version' => 'dev-master',
+            'version' => 'dev-master',
+            'reference' => '26dc268aa174e424bd5abe3b648734c22aa0a437',
+            'type' => 'project',
+            'install_path' => __DIR__ . '/../../',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'topthink/think-captcha' => array(
+            'pretty_version' => 'v3.0.9',
+            'version' => '3.0.9.0',
+            'reference' => 'b1ef360670578214edeebcf824aaf6ab7ee0528b',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-captcha',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'topthink/think-filesystem' => array(
+            'pretty_version' => 'v1.0.3',
+            'version' => '1.0.3.0',
+            'reference' => '29f19f140a9267c717fecd7ccb22c84c2d72382e',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-filesystem',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'topthink/think-helper' => array(
+            'pretty_version' => 'v3.1.8',
+            'version' => '3.1.8.0',
+            'reference' => '612eea76eec2a22f41b0e24be27f49454e4fd5f5',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-helper',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'topthink/think-image' => array(
+            'pretty_version' => 'v1.0.7',
+            'version' => '1.0.7.0',
+            'reference' => '8586cf47f117481c6d415b20f7dedf62e79d5512',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-image',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'topthink/think-orm' => array(
+            'pretty_version' => 'v2.0.62',
+            'version' => '2.0.62.0',
+            'reference' => 'e53bfea572a133039ad687077120de5521af617f',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-orm',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'topthink/think-queue' => array(
+            'pretty_version' => 'v3.0.9',
+            'version' => '3.0.9.0',
+            'reference' => '654812b47dd7c708c4443deed27f212f8382e8da',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-queue',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'topthink/think-swoole' => array(
+            'pretty_version' => 'v4.0.9',
+            'version' => '4.0.9.0',
+            'reference' => 'edc326d92fc738c290d5777f0c544477759fa7f3',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-swoole',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'topthink/think-trace' => array(
+            'pretty_version' => 'v1.6',
+            'version' => '1.6.0.0',
+            'reference' => '136cd5d97e8bdb780e4b5c1637c588ed7ca3e142',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../topthink/think-trace',
+            'aliases' => array(),
+            'dev_requirement' => true,
+        ),
+        'yurunsoft/composer-include-files' => array(
+            'pretty_version' => 'v2.0.0',
+            'version' => '2.0.0.0',
+            'reference' => '277ed077b85d7a9d7b6b73ff148a48d9d676218d',
+            'type' => 'composer-plugin',
+            'install_path' => __DIR__ . '/../yurunsoft/composer-include-files',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'yurunsoft/guzzle-swoole' => array(
+            'pretty_version' => 'v2.2.4',
+            'version' => '2.2.4.0',
+            'reference' => '89bb58446aa0a3d6448de3943b40a5d79b18cbda',
+            'type' => 'composer-plugin',
+            'install_path' => __DIR__ . '/../yurunsoft/guzzle-swoole',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
+        'yurunsoft/yurun-http' => array(
+            'pretty_version' => 'v4.4.4',
+            'version' => '4.4.4.0',
+            'reference' => '427d17c1e870d67e47a51ddd231932da2b041b5c',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../yurunsoft/yurun-http',
+            'aliases' => array(),
+            'dev_requirement' => false,
+        ),
     ),
-    'reference' => 'b4d08155eb79c5471dc034238c7896deaeaff6a5',
-    'name' => 'topthink/think',
-  ),
-  'versions' => 
-  array (
-    'adbario/php-dot-notation' => 
-    array (
-      'pretty_version' => '2.5.0',
-      'version' => '2.5.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '081e2cca50c84bfeeea2e3ef9b2c8d206d80ccae',
-    ),
-    'alibabacloud/credentials' => 
-    array (
-      'pretty_version' => '1.2.0',
-      'version' => '1.2.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'ebcda2e628180b4df235b46a86e1d014c561f5d9',
-    ),
-    'alibabacloud/darabonba-openapi' => 
-    array (
-      'pretty_version' => '0.2.13',
-      'version' => '0.2.13.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '0213396384e2c064eefd614f3dd53636a63f987f',
-    ),
-    'alibabacloud/dysmsapi-20170525' => 
-    array (
-      'pretty_version' => '3.1.0',
-      'version' => '3.1.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5f779cf8d6d8807b9835bff8d058dbab6d59bbf1',
-    ),
-    'alibabacloud/endpoint-util' => 
-    array (
-      'pretty_version' => '0.1.1',
-      'version' => '0.1.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'f3fe88a25d8df4faa3b0ae14ff202a9cc094e6c5',
-    ),
-    'alibabacloud/gateway-spi' => 
-    array (
-      'pretty_version' => '1.0.0',
-      'version' => '1.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '7440f77750c329d8ab252db1d1d967314ccd1fcb',
-    ),
-    'alibabacloud/openapi-util' => 
-    array (
-      'pretty_version' => '0.2.1',
-      'version' => '0.2.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'f31f7bcd835e08ca24b6b8ba33637eb4eceb093a',
-    ),
-    'alibabacloud/tea' => 
-    array (
-      'pretty_version' => '3.2.1',
-      'version' => '3.2.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '1619cb96c158384f72b873e1f85de8b299c9c367',
-    ),
-    'alibabacloud/tea-fileform' => 
-    array (
-      'pretty_version' => '0.3.4',
-      'version' => '0.3.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '4bf0c75a045c8115aa8cb1a394bd08d8bb833181',
-    ),
-    'alibabacloud/tea-utils' => 
-    array (
-      'pretty_version' => '0.2.21',
-      'version' => '0.2.21.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5039e45714c6456186d267f5d81a4b260a652495',
-    ),
-    'alibabacloud/tea-xml' => 
-    array (
-      'pretty_version' => '0.2.4',
-      'version' => '0.2.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '3e0c000bf536224eebbac913c371bef174c0a16a',
-    ),
-    'alipaysdk/easysdk' => 
-    array (
-      'pretty_version' => '2.2.3',
-      'version' => '2.2.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'c6008839a22a5fca08e9f8536730f7abfed522d5',
-    ),
-    'aliyuncs/oss-sdk-php' => 
-    array (
-      'pretty_version' => 'v2.7.2',
-      'version' => '2.7.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '483dd0b8bff5d47f0e4ffc99f6077a295c5ccbb5',
-    ),
-    'async-aws/core' => 
-    array (
-      'pretty_version' => '1.21.0',
-      'version' => '1.21.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'eb23cc59515d8d529163313bbf9e02f666e515ef',
-    ),
-    'bacon/bacon-qr-code' => 
-    array (
-      'pretty_version' => '2.0.8',
-      'version' => '2.0.8.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '8674e51bb65af933a5ffaf1c308a660387c35c22',
-    ),
-    'carbonphp/carbon-doctrine-types' => 
-    array (
-      'pretty_version' => '2.1.0',
-      'version' => '2.1.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '99f76ffa36cce3b70a4a6abce41dba15ca2e84cb',
-    ),
-    'dasprid/enum' => 
-    array (
-      'pretty_version' => '1.0.5',
-      'version' => '1.0.5.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '6faf451159fb8ba4126b925ed2d78acfce0dc016',
-    ),
-    'easywechat-composer/easywechat-composer' => 
-    array (
-      'pretty_version' => '1.4.1',
-      'version' => '1.4.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '3fc6a7ab6d3853c0f4e2922539b56cc37ef361cd',
-    ),
-    'endroid/qr-code' => 
-    array (
-      'pretty_version' => '4.6.1',
-      'version' => '4.6.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a75c913b0e4d6ad275e49a2c1de1cacffc6c2184',
-    ),
-    'ezyang/htmlpurifier' => 
-    array (
-      'pretty_version' => 'v4.18.0',
-      'version' => '4.18.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'cb56001e54359df7ae76dc522d08845dc741621b',
-    ),
-    'fastknife/ajcaptcha' => 
-    array (
-      'pretty_version' => 'v1.2.2',
-      'version' => '1.2.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '87c122b6cd950fd98702e929685e5e7c0c517ddc',
-    ),
-    'firebase/php-jwt' => 
-    array (
-      'pretty_version' => 'v6.10.0',
-      'version' => '6.10.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a49db6f0a5033aef5143295342f1c95521b075ff',
-    ),
-    'guzzlehttp/command' => 
-    array (
-      'pretty_version' => '1.3.1',
-      'version' => '1.3.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '0eebc653784f4902b3272e826fe8e88743d14e77',
-    ),
-    'guzzlehttp/guzzle' => 
-    array (
-      'pretty_version' => '7.9.2',
-      'version' => '7.9.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd281ed313b989f213357e3be1a179f02196ac99b',
-    ),
-    'guzzlehttp/guzzle-services' => 
-    array (
-      'pretty_version' => '1.4.1',
-      'version' => '1.4.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'bcab7c0d61672b606510a6fe5af3039d04968c0f',
-    ),
-    'guzzlehttp/promises' => 
-    array (
-      'pretty_version' => '2.0.3',
-      'version' => '2.0.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8',
-    ),
-    'guzzlehttp/psr7' => 
-    array (
-      'pretty_version' => '2.7.0',
-      'version' => '2.7.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a70f5c95fb43bc83f07c9c948baa0dc1829bf201',
-    ),
-    'guzzlehttp/ringphp' => 
-    array (
-      'pretty_version' => '1.1.1',
-      'version' => '1.1.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5e2a174052995663dd68e6b5ad838afd47dd615b',
-    ),
-    'guzzlehttp/streams' => 
-    array (
-      'pretty_version' => '3.0.0',
-      'version' => '3.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5',
-    ),
-    'guzzlehttp/uri-template' => 
-    array (
-      'pretty_version' => 'v1.0.3',
-      'version' => '1.0.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'ecea8feef63bd4fef1f037ecb288386999ecc11c',
-    ),
-    'intervention/image' => 
-    array (
-      'pretty_version' => '2.7.2',
-      'version' => '2.7.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '04be355f8d6734c826045d02a1079ad658322dad',
-    ),
-    'joypack/tencent-map' => 
-    array (
-      'pretty_version' => '1.0.0',
-      'version' => '1.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '97c0269086d53dbecb9c3c6e1d2717645d7940a8',
-    ),
-    'league/flysystem' => 
-    array (
-      'pretty_version' => '1.1.10',
-      'version' => '1.1.10.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '3239285c825c152bcc315fe0e87d6b55f5972ed1',
-    ),
-    'league/flysystem-cached-adapter' => 
-    array (
-      'pretty_version' => '1.1.0',
-      'version' => '1.1.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd1925efb2207ac4be3ad0c40b8277175f99ffaff',
-    ),
-    'league/mime-type-detection' => 
-    array (
-      'pretty_version' => '1.15.0',
-      'version' => '1.15.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'ce0f4d1e8a6f4eb0ddff33f57c69c50fd09f4301',
-    ),
-    'lizhichao/one-sm' => 
-    array (
-      'pretty_version' => '1.10',
-      'version' => '1.10.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '687a012a44a5bfd4d9143a0234e1060543be455a',
-    ),
-    'maennchen/zipstream-php' => 
-    array (
-      'pretty_version' => '2.2.6',
-      'version' => '2.2.6.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '30ad6f93cf3efe4192bc7a4c9cad11ff8f4f237f',
-    ),
-    'markbaker/complex' => 
-    array (
-      'pretty_version' => '3.0.2',
-      'version' => '3.0.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '95c56caa1cf5c766ad6d65b6344b807c1e8405b9',
-    ),
-    'markbaker/matrix' => 
-    array (
-      'pretty_version' => '3.0.1',
-      'version' => '3.0.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '728434227fe21be27ff6d86621a1b13107a2562c',
-    ),
-    'monolog/monolog' => 
-    array (
-      'pretty_version' => '2.10.0',
-      'version' => '2.10.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5cf826f2991858b54d5c3809bee745560a1042a7',
-    ),
-    'myclabs/php-enum' => 
-    array (
-      'pretty_version' => '1.8.4',
-      'version' => '1.8.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a867478eae49c9f59ece437ae7f9506bfaa27483',
-    ),
-    'nesbot/carbon' => 
-    array (
-      'pretty_version' => '2.72.5',
-      'version' => '2.72.5.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'afd46589c216118ecd48ff2b95d77596af1e57ed',
-    ),
-    'nette/php-generator' => 
-    array (
-      'pretty_version' => 'v3.6.9',
-      'version' => '3.6.9.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd31782f7bd2ae84ad06f863391ec3fb77ca4d0a6',
-    ),
-    'nette/utils' => 
-    array (
-      'pretty_version' => 'v3.2.10',
-      'version' => '3.2.10.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a4175c62652f2300c8017fb7e640f9ccb11648d2',
-    ),
-    'open-smf/connection-pool' => 
-    array (
-      'pretty_version' => 'v1.0.16',
-      'version' => '1.0.16.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'f70e47dbf56f1869d3207e15825cf38810b865e0',
-    ),
-    'overtrue/socialite' => 
-    array (
-      'pretty_version' => '3.5.4',
-      'version' => '3.5.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '6bd4f0230bcaec5ccfd64a10581a9063233b5a48',
-    ),
-    'overtrue/wechat' => 
-    array (
-      'pretty_version' => '5.30.0',
-      'version' => '5.30.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '245d1e821bc5a4609625c3244b111f570692cfc2',
-    ),
-    'php-http/async-client-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '*',
-      ),
-    ),
-    'php-http/client-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '*',
-      ),
-    ),
-    'phpoffice/phpspreadsheet' => 
-    array (
-      'pretty_version' => '1.29.4',
-      'version' => '1.29.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '7ca7e325dca3adb6a598385aab81f527b8d6c75d',
-    ),
-    'pimple/pimple' => 
-    array (
-      'pretty_version' => 'v3.5.0',
-      'version' => '3.5.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a94b3a4db7fb774b3d78dad2315ddc07629e1bed',
-    ),
-    'psr/cache' => 
-    array (
-      'pretty_version' => '1.0.1',
-      'version' => '1.0.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
-    ),
-    'psr/cache-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0|2.0',
-      ),
-    ),
-    'psr/clock' => 
-    array (
-      'pretty_version' => '1.0.0',
-      'version' => '1.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d',
-    ),
-    'psr/clock-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0',
-      ),
-    ),
-    'psr/container' => 
-    array (
-      'pretty_version' => '1.1.2',
-      'version' => '1.1.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
-    ),
-    'psr/event-dispatcher' => 
-    array (
-      'pretty_version' => '1.0.0',
-      'version' => '1.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0',
-    ),
-    'psr/event-dispatcher-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0',
-      ),
-    ),
-    'psr/http-client' => 
-    array (
-      'pretty_version' => '1.0.3',
-      'version' => '1.0.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90',
-    ),
-    'psr/http-client-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0',
-      ),
-    ),
-    'psr/http-factory' => 
-    array (
-      'pretty_version' => '1.0.2',
-      'version' => '1.0.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e616d01114759c4c489f93b099585439f795fe35',
-    ),
-    'psr/http-factory-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0',
-      ),
-    ),
-    'psr/http-message' => 
-    array (
-      'pretty_version' => '1.1',
-      'version' => '1.1.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba',
-    ),
-    'psr/http-message-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0',
-      ),
-    ),
-    'psr/log' => 
-    array (
-      'pretty_version' => '1.1.4',
-      'version' => '1.1.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
-    ),
-    'psr/log-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0.0 || 2.0.0 || 3.0.0',
-      ),
-    ),
-    'psr/simple-cache' => 
-    array (
-      'pretty_version' => '1.0.1',
-      'version' => '1.0.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
-    ),
-    'psr/simple-cache-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0|2.0',
-      ),
-    ),
-    'qcloud/cos-sdk-v5' => 
-    array (
-      'pretty_version' => 'v2.6.15',
-      'version' => '2.6.15.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '17b973a388dc8848947054daace0fff8d2a4eee0',
-    ),
-    'qiniu/php-sdk' => 
-    array (
-      'pretty_version' => 'v7.14.0',
-      'version' => '7.14.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'ee752ffa7263ce99fca0bd7340cf13c486a3516c',
-    ),
-    'ralouphie/getallheaders' => 
-    array (
-      'pretty_version' => '3.0.3',
-      'version' => '3.0.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '120b605dfeb996808c31b6477290a714d356e822',
-    ),
-    'react/promise' => 
-    array (
-      'pretty_version' => 'v2.11.0',
-      'version' => '2.11.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '1a8460931ea36dc5c76838fec5734d55c88c6831',
-    ),
-    'stechstudio/backoff' => 
-    array (
-      'pretty_version' => '1.2.1',
-      'version' => '1.2.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '7204cddf3f1afcd5368d74d52f4d8c447c5dc311',
-    ),
-    'swoole/ide-helper' => 
-    array (
-      'pretty_version' => '4.8.13',
-      'version' => '4.8.13.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd100c446b2e3d56430cbcab5dc3fa20a9f35c4ef',
-    ),
-    'symfony/cache' => 
-    array (
-      'pretty_version' => 'v5.4.46',
-      'version' => '5.4.46.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '0fe08ee32cec2748fbfea10c52d3ee02049e0f6b',
-    ),
-    'symfony/cache-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.4',
-      'version' => '2.5.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '517c3a3619dadfa6952c4651767fcadffb4df65e',
-    ),
-    'symfony/cache-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '1.0|2.0',
-      ),
-    ),
-    'symfony/deprecation-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.3',
-      'version' => '2.5.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '80d075412b557d41002320b96a096ca65aa2c98d',
-    ),
-    'symfony/event-dispatcher' => 
-    array (
-      'pretty_version' => 'v5.4.45',
-      'version' => '5.4.45.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '72982eb416f61003e9bb6e91f8b3213600dcf9e9',
-    ),
-    'symfony/event-dispatcher-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.4',
-      'version' => '2.5.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f',
-    ),
-    'symfony/event-dispatcher-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '2.0',
-      ),
-    ),
-    'symfony/finder' => 
-    array (
-      'pretty_version' => 'v5.4.45',
-      'version' => '5.4.45.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '63741784cd7b9967975eec610b256eed3ede022b',
-    ),
-    'symfony/http-client' => 
-    array (
-      'pretty_version' => 'v5.4.47',
-      'version' => '5.4.47.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '3b643b83f87e1765d2e9b1e946bb56ee0b4b7bde',
-    ),
-    'symfony/http-client-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.3',
-      'version' => '2.5.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e5cc97c2b4a4db0ba26bebc154f1426e3fd1d2f1',
-    ),
-    'symfony/http-client-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '2.4',
-      ),
-    ),
-    'symfony/http-foundation' => 
-    array (
-      'pretty_version' => 'v5.4.48',
-      'version' => '5.4.48.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '3f38b8af283b830e1363acd79e5bc3412d055341',
-    ),
-    'symfony/polyfill-mbstring' => 
-    array (
-      'pretty_version' => 'v1.31.0',
-      'version' => '1.31.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '85181ba99b2345b0ef10ce42ecac37612d9fd341',
-    ),
-    'symfony/polyfill-php72' => 
-    array (
-      'pretty_version' => 'v1.31.0',
-      'version' => '1.31.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'fa2ae56c44f03bed91a39bfc9822e31e7c5c38ce',
-    ),
-    'symfony/polyfill-php73' => 
-    array (
-      'pretty_version' => 'v1.31.0',
-      'version' => '1.31.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '0f68c03565dcaaf25a890667542e8bd75fe7e5bb',
-    ),
-    'symfony/polyfill-php80' => 
-    array (
-      'pretty_version' => 'v1.31.0',
-      'version' => '1.31.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '60328e362d4c2c802a54fcbf04f9d3fb892b4cf8',
-    ),
-    'symfony/process' => 
-    array (
-      'pretty_version' => 'v5.4.46',
-      'version' => '5.4.46.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '01906871cb9b5e3cf872863b91aba4ec9767daf4',
-    ),
-    'symfony/psr-http-message-bridge' => 
-    array (
-      'pretty_version' => 'v2.3.1',
-      'version' => '2.3.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '581ca6067eb62640de5ff08ee1ba6850a0ee472e',
-    ),
-    'symfony/service-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.3',
-      'version' => '2.5.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a2329596ddc8fd568900e3fc76cba42489ecc7f3',
-    ),
-    'symfony/translation' => 
-    array (
-      'pretty_version' => 'v5.4.45',
-      'version' => '5.4.45.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '98f26acc99341ca4bab345fb14d7b1d7cb825bed',
-    ),
-    'symfony/translation-contracts' => 
-    array (
-      'pretty_version' => 'v2.5.3',
-      'version' => '2.5.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'b0073a77ac0b7ea55131020e87b1e3af540f4664',
-    ),
-    'symfony/translation-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '2.3',
-      ),
-    ),
-    'symfony/var-dumper' => 
-    array (
-      'pretty_version' => 'v4.4.47',
-      'version' => '4.4.47.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '1069c7a3fca74578022fab6f81643248d02f8e63',
-    ),
-    'symfony/var-exporter' => 
-    array (
-      'pretty_version' => 'v5.4.45',
-      'version' => '5.4.45.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '862700068db0ddfd8c5b850671e029a90246ec75',
-    ),
-    'topthink/framework' => 
-    array (
-      'pretty_version' => 'v6.1.4',
-      'version' => '6.1.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '66eb9cf4d627df12911344cd328faf9bb596bf2c',
-    ),
-    'topthink/think' => 
-    array (
-      'pretty_version' => 'dev-master',
-      'version' => 'dev-master',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'b4d08155eb79c5471dc034238c7896deaeaff6a5',
-    ),
-    'topthink/think-captcha' => 
-    array (
-      'pretty_version' => 'v3.0.9',
-      'version' => '3.0.9.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'b1ef360670578214edeebcf824aaf6ab7ee0528b',
-    ),
-    'topthink/think-filesystem' => 
-    array (
-      'pretty_version' => 'v1.0.3',
-      'version' => '1.0.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '29f19f140a9267c717fecd7ccb22c84c2d72382e',
-    ),
-    'topthink/think-helper' => 
-    array (
-      'pretty_version' => 'v3.1.8',
-      'version' => '3.1.8.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '612eea76eec2a22f41b0e24be27f49454e4fd5f5',
-    ),
-    'topthink/think-image' => 
-    array (
-      'pretty_version' => 'v1.0.7',
-      'version' => '1.0.7.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '8586cf47f117481c6d415b20f7dedf62e79d5512',
-    ),
-    'topthink/think-orm' => 
-    array (
-      'pretty_version' => 'v2.0.62',
-      'version' => '2.0.62.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e53bfea572a133039ad687077120de5521af617f',
-    ),
-    'topthink/think-queue' => 
-    array (
-      'pretty_version' => 'v3.0.9',
-      'version' => '3.0.9.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '654812b47dd7c708c4443deed27f212f8382e8da',
-    ),
-    'topthink/think-swoole' => 
-    array (
-      'pretty_version' => 'v4.0.9',
-      'version' => '4.0.9.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'edc326d92fc738c290d5777f0c544477759fa7f3',
-    ),
-    'topthink/think-trace' => 
-    array (
-      'pretty_version' => 'v1.6',
-      'version' => '1.6.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '136cd5d97e8bdb780e4b5c1637c588ed7ca3e142',
-    ),
-    'yurunsoft/composer-include-files' => 
-    array (
-      'pretty_version' => 'v2.0.0',
-      'version' => '2.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '277ed077b85d7a9d7b6b73ff148a48d9d676218d',
-    ),
-    'yurunsoft/guzzle-swoole' => 
-    array (
-      'pretty_version' => 'v2.2.4',
-      'version' => '2.2.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '89bb58446aa0a3d6448de3943b40a5d79b18cbda',
-    ),
-    'yurunsoft/yurun-http' => 
-    array (
-      'pretty_version' => 'v4.4.4',
-      'version' => '4.4.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '427d17c1e870d67e47a51ddd231932da2b041b5c',
-    ),
-  ),
 );

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