wesmiler 5 månader sedan
förälder
incheckning
88715b12f3
100 ändrade filer med 13999 tillägg och 1 borttagningar
  1. 1 1
      .env
  2. 591 0
      app/Console/Commands/SocketServer.php
  3. 41 0
      app/Console/Kernel.php
  4. 37 0
      app/Exceptions/Handler.php
  5. 238 0
      app/Exports/Export.php
  6. 212 0
      app/Helpers/Jwt.php
  7. 2361 0
      app/Helpers/common.php
  8. 22 0
      app/Helpers/constants.php
  9. 11 0
      app/Helpers/function.php
  10. 63 0
      app/Http/Controllers/Admin/AccountController.php
  11. 36 0
      app/Http/Controllers/Admin/ActionLogController.php
  12. 37 0
      app/Http/Controllers/Admin/AdController.php
  13. 41 0
      app/Http/Controllers/Admin/ArticleController.php
  14. 165 0
      app/Http/Controllers/Admin/Backend.php
  15. 36 0
      app/Http/Controllers/Admin/CityController.php
  16. 36 0
      app/Http/Controllers/Admin/ConfigController.php
  17. 36 0
      app/Http/Controllers/Admin/ConfigGroupController.php
  18. 22 0
      app/Http/Controllers/Admin/Controller.php
  19. 111 0
      app/Http/Controllers/Admin/DepositController.php
  20. 57 0
      app/Http/Controllers/Admin/DriverController.php
  21. 66 0
      app/Http/Controllers/Admin/GoodsController.php
  22. 159 0
      app/Http/Controllers/Admin/IndexController.php
  23. 37 0
      app/Http/Controllers/Admin/LayoutController.php
  24. 73 0
      app/Http/Controllers/Admin/LoginController.php
  25. 83 0
      app/Http/Controllers/Admin/MemberController.php
  26. 36 0
      app/Http/Controllers/Admin/MenuController.php
  27. 95 0
      app/Http/Controllers/Admin/MessageController.php
  28. 49 0
      app/Http/Controllers/Admin/NoticeController.php
  29. 110 0
      app/Http/Controllers/Admin/OrderController.php
  30. 72 0
      app/Http/Controllers/Admin/RoleController.php
  31. 109 0
      app/Http/Controllers/Admin/UploadController.php
  32. 49 0
      app/Http/Controllers/Admin/UserController.php
  33. 80 0
      app/Http/Controllers/Admin/WithdrawController.php
  34. 81 0
      app/Http/Controllers/Api/UploadController.php
  35. 60 0
      app/Http/Controllers/Api/v1/AccountController.php
  36. 95 0
      app/Http/Controllers/Api/v1/ArticleController.php
  37. 72 0
      app/Http/Controllers/Api/v1/DepositController.php
  38. 67 0
      app/Http/Controllers/Api/v1/GoodsController.php
  39. 110 0
      app/Http/Controllers/Api/v1/IndexController.php
  40. 129 0
      app/Http/Controllers/Api/v1/LoginController.php
  41. 133 0
      app/Http/Controllers/Api/v1/MemberController.php
  42. 39 0
      app/Http/Controllers/Api/v1/MessageController.php
  43. 112 0
      app/Http/Controllers/Api/v1/NotifyController.php
  44. 102 0
      app/Http/Controllers/Api/v1/OrderController.php
  45. 23 0
      app/Http/Controllers/Api/v1/TestController.php
  46. 184 0
      app/Http/Controllers/Api/webApp.php
  47. 97 0
      app/Http/Controllers/BaseController.php
  48. 74 0
      app/Http/Kernel.php
  49. 24 0
      app/Http/Middleware/ActionLog.php
  50. 21 0
      app/Http/Middleware/Authenticate.php
  51. 54 0
      app/Http/Middleware/EnableCrossRequestMiddleware.php
  52. 17 0
      app/Http/Middleware/EncryptCookies.php
  53. 17 0
      app/Http/Middleware/PreventRequestsDuringMaintenance.php
  54. 32 0
      app/Http/Middleware/RedirectIfAuthenticated.php
  55. 18 0
      app/Http/Middleware/TrimStrings.php
  56. 20 0
      app/Http/Middleware/TrustHosts.php
  57. 23 0
      app/Http/Middleware/TrustProxies.php
  58. 50 0
      app/Http/Middleware/UserLogin.php
  59. 17 0
      app/Http/Middleware/VerifyCsrfToken.php
  60. 82 0
      app/Http/Middleware/WebLogin.php
  61. 48 0
      app/Http/Validator/AccountValidator.php
  62. 56 0
      app/Http/Validator/BaseValidator.php
  63. 75 0
      app/Http/Validator/MemberValidator.php
  64. 49 0
      app/Http/Validator/OrderValidator.php
  65. 2 0
      app/Lib/phpqrcode/.gitignore
  66. 38 0
      app/Lib/phpqrcode/CHANGELOG
  67. 165 0
      app/Lib/phpqrcode/LICENSE
  68. 3719 0
      app/Lib/phpqrcode/QRcode.php
  69. 61 0
      app/Lib/phpqrcode/README
  70. 2 0
      app/Lib/phpqrcode/VERSION
  71. 34 0
      app/Models/AccountLogModel.php
  72. 169 0
      app/Models/ActionLogModel.php
  73. 53 0
      app/Models/AdModel.php
  74. 25 0
      app/Models/ArticleCateModel.php
  75. 25 0
      app/Models/ArticleModel.php
  76. 34 0
      app/Models/BalanceLogModel.php
  77. 1253 0
      app/Models/BaseModel.php
  78. 291 0
      app/Models/CacheModel.php
  79. 25 0
      app/Models/CityModel.php
  80. 25 0
      app/Models/ConfigGroupModel.php
  81. 41 0
      app/Models/ConfigModel.php
  82. 35 0
      app/Models/DepositModel.php
  83. 101 0
      app/Models/GoodsModel.php
  84. 98 0
      app/Models/MemberModel.php
  85. 64 0
      app/Models/MenuModel.php
  86. 56 0
      app/Models/MessageModel.php
  87. 30 0
      app/Models/NoticeModel.php
  88. 70 0
      app/Models/OrderModel.php
  89. 34 0
      app/Models/PaymentModel.php
  90. 25 0
      app/Models/RoleMenuModel.php
  91. 25 0
      app/Models/RoleModel.php
  92. 52 0
      app/Models/User.php
  93. 56 0
      app/Models/UserModel.php
  94. 26 0
      app/Models/UserRoleModel.php
  95. 66 0
      app/Providers/AppServiceProvider.php
  96. 30 0
      app/Providers/AuthServiceProvider.php
  97. 21 0
      app/Providers/BroadcastServiceProvider.php
  98. 32 0
      app/Providers/EventServiceProvider.php
  99. 63 0
      app/Providers/RouteServiceProvider.php
  100. 0 0
      app/Services/Api/AccountService.php

+ 1 - 1
.env

@@ -1,4 +1,4 @@
-APP_NAME=jdapp
+APP_NAME=dshmp
 APP_ENV=local
 LOCAL_LANG=zh-cn
 APP_KEY=base64:5c43a8wcR8LOQtT3fxxtJ/Y4Hf4y4KdLsGF5Gi6v7SY=

+ 591 - 0
app/Console/Commands/SocketServer.php

@@ -0,0 +1,591 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Helpers\Jwt;
+use App\Models\DepositModel;
+use App\Models\MessageModel;
+use App\Services\Api\DepositService;
+use App\Services\Api\MemberService;
+use App\Services\Api\OrderService;
+use App\Services\Common\MessageService;
+use App\Services\ConfigService;
+use App\Services\RedisService;
+use Illuminate\Console\Command;
+use const http\Client\Curl\SSL_VERSION_SSLv3;
+use const http\Client\Curl\SSL_VERSION_TLSv1_2;
+
+class SocketServer extends Command
+{
+    public $ws;
+
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'swoole:chat {op?}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Chat server run';
+
+    protected $logger = null;
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return mixed
+     */
+    public function handle()
+    {
+        $op = $this->argument('op');
+        $op = $op ? $op : 'start';
+        if ($op == 'start') {
+            echo "swoole chat service start ...\n";
+            $this->start();
+        } else if ($op == 'stop') {
+            echo "swoole chat service stop ...\n";
+            $this->stop();
+        }
+    }
+
+    /**
+     * 运行
+     */
+    public function start()
+    {
+        try {
+            //创建websocket服务器对象,监听0.0.0.0:7104端口
+            // HTTPS 通过nginx 配置证书即可
+            $this->ws = new \Swoole\WebSocket\Server("0.0.0.0", env('SOCKET_PORT', '8660'));
+
+            //监听WebSocket连接打开事件
+            $this->ws->on('open', [$this, 'open']);
+
+            //监听WebSocket消息事件
+            $this->ws->on('message', [$this, 'message']);
+
+            //监听WebSocket主动推送消息事件
+            $this->ws->on('request', [$this, 'request']);
+
+            //监听WebSocket连接关闭事件
+            $this->ws->on('close', [$this, 'close']);
+
+            $this->ws->start();
+        } catch (\Exception $exception) {
+            $date = date('Y-m-d H:i:s');
+            RedisService::set("caches:sockets:error", $exception->getMessage(), 600);
+            $this->info("【{$date}】Socket:运行异常=》" . $exception->getMessage());
+        }
+    }
+
+    /**
+     * 建立连接
+     * @param $ws
+     * @param $request
+     */
+    public function open($ws, $request)
+    {
+        $date = date('Y-m-d H:i:s');
+        $logFile = '/storage/logs/swoole-task-'.date('Y-m-d', time() - 86400).'.log';
+        if(file_exists(base_path().$logFile)){
+            unlink(base_path().$logFile);
+        }
+
+        $fdData = RedisService::get("chats:bind:chat_1");
+        $customFd = $fdData && isset($fdData['fd'])? $fdData['fd'] : 0;
+        $checkFd = RedisService::get("chats:frames:" . $customFd);
+        RedisService::clear('chats:checkCustom:from_'.$request->fd);
+        $this->ws->push($request->fd, json_encode(['success' => 'true', 'op' => 'conn', 'message' => '连接成功','custom_fd'=>$checkFd && $customFd? $customFd:0, 'fd' => $request->fd], 256));
+        $this->info("【{$date}】Socket:客户端【{$request->fd}】连接成功");
+    }
+
+    /**
+     * 接收消息
+     * @param $ws
+     * @param $frame
+     */
+    public function message($ws, $frame)
+    {
+        $date = date('Y-m-d H:i:s');
+        RedisService::set("chats:frames:" . $frame->fd, json_decode($frame->data, true), 86400);
+        $fdData = RedisService::get("chats:bind:chat_1");
+        $customFd = $fdData && isset($fdData['fd'])? $fdData['fd'] : 0;
+        if ($frame->data == 'ping') {
+            $this->ws->push($frame->fd, 'pong');
+            if($customFd != $frame->fd){
+                $this->sendMsg($frame->fd, ['success' => true,'op'=>'custom', 'message' => $customFd?'客服上线':'客服离线', 'scene'=>'check', 'data' => ['online'=>$customFd,'to_fd'=>$customFd], 't' => time()]);
+            }
+
+            // 推送客服保证金信息
+            if($customFd == $frame->fd){
+               $messages = MessageService::make()->getUnreadList(0);
+               $count = isset($messages['count'])? $messages['count'] : 0;
+               if($count>0){
+                   $this->sendMsg($frame->fd, ['success' => true,'op'=>'notice', 'message' => '消息通知', 'scene'=>'deposit', 'data' => $messages, 't' => time()]);
+               }
+            }
+
+            $this->info("【{$date}】Socket:客户端【{$frame->fd}】心跳包",false);
+            return false;
+        }
+        // 推送客服保证金信息
+        else if($customFd && RedisService::get("chats:frames:" . $customFd)){
+            $messages = MessageService::make()->getUnreadList(0);
+            $count = isset($messages['count'])? $messages['count'] : 0;
+            if($count>0){
+                $this->sendMsg($customFd, ['success' => true,'op'=>'notice', 'message' => '消息通知', 'scene'=>'deposit', 'data' => $messages, 't' => time()]);
+            }
+        }
+
+        // 消息处理
+        $frameId = $frame->fd;
+        $data = $frame->data ? json_decode($frame->data, true) : [];
+        $fromUid = isset($data['from_uid']) ? intval($data['from_uid']) : 0;
+        $isCustom = isset($data['is_custom']) ? intval($data['is_custom']) : 0;
+        $token = isset($data['token']) ? $data['token'] : '';
+        $op = isset($data['op']) ? $data['op'] : '';
+        $scene = isset($data['scene']) && $data['scene'] ? $data['scene'] : 'chat';
+        $toUid = isset($data['to_uid']) ? intval($data['to_uid']) : 0;
+        $jwt = new Jwt('jwt_jd_app');
+        $userId = $jwt->verifyToken($token);
+        if (!$isCustom && $userId != $fromUid) {
+            $this->info("【{$scene} {$date}】Socket:请先登录再连接【{$frameId}-{$fromUid}】");
+            $this->sendMsg($frameId, ['success' => false,'op'=>'error', 'message' => '请先登录', 'scene'=>$scene, 'data' => $data, 't' => time()]);
+            return false;
+        }
+
+        if ($op != 'login' && ($toUid<=0 || $fromUid == $toUid)) {
+            $this->info("【{$scene} {$date}】Socket:参数错误【{$fromUid}-{$toUid}】");
+            $this->sendMsg($frameId, ['success' => false,'op'=>'error', 'message' => '参数错误,请先选择回复用户~', 'scene'=>$scene, 'data' => $data, 't' => time()]);
+            return false;
+        }
+
+        // 签名验证
+        $system = isset($data['system']) ? $data['system'] : [];
+        $uuid = isset($system['uuid'])? $system['uuid'] : 0;
+        $ctime = isset($system['ct'])? $system['ct'] : 0;
+        $message = isset($data['message']) ? trim($data['message']) : '';
+        $sign = isset($data['sign']) ? trim($data['sign']) : '';
+        $checkSign = getSign($op.'&'.$message.'&'.$fromUid.'&'.$uuid.'&'.$ctime);
+        if($checkSign != $sign){
+            $this->info("【{$scene} {$date}】Socket:签名失败【{$frameId}-{$fromUid}】");
+            $this->sendMsg($frameId, ['success' => false,'op'=>'error', 'message' => '请求签名失败', 'scene'=>$scene,'sign'=>$checkSign, 'data' => $data, 't' => time()]);
+            return false;
+        }
+
+        $apiUrl = env('APP_URL','');
+        $chatKey = isset($data['chat_key']) ? trim($data['chat_key']) : '';
+        $chatKey = $chatKey ? $chatKey : getChatKey($fromUid, $toUid);
+        try {
+            // 推送Fd处理
+            if ($fromUid && $frameId) {
+                RedisService::set("chats:bind:{$scene}_{$fromUid}", ['fd' => $frameId,'scene'=>$scene, 'user_id' => $fromUid, 'uuid' => $uuid, 'chat_key' => $chatKey], 3600);
+            }
+
+            switch ($op) {
+                case 'chat': // 图文聊天
+                    $msgType = isset($data['msg_type']) ? $data['msg_type'] : 1;
+
+
+
+                    // 发送参数验证
+                    if ($fromUid <= 0 || empty($message)) {
+                        $this->info("【{$scene} {$date}】Chat:参数错误,from@{$fromUid}-to@{$toUid}。");
+                        $this->sendMsg($frameId, ['success' => false,'op'=>'push','scene'=>$scene,'data'=>$data, 'message' => '参数错误']);
+                        return false;
+                    }
+
+                    // 敏感词过滤
+                    $message = \App\Services\Api\MessageService::make()->checkMessage($message);
+
+                    // 用户私聊
+                    $fromInfo = [];
+                    if($fromUid>1){
+                        $fromInfo = MemberService::make()->getInfo(['id'=> $fromUid,'status'=>1],[],false);
+                        if(empty($fromInfo)){
+                            $this->info("【{$scene} {$date}】Chat:发送用户不存在,from@{$fromUid}-to@{$toUid}。");
+                            $this->sendMsg($frameId, ['success' => false,'op'=>'push','scene'=>$scene,'data'=>$data, 'message' => '您的账号不可用或已冻结,请联系客服']);
+                            return false;
+                        }
+                    }
+
+                    $toInfo = [];
+                    if($toUid>1){
+                        $toInfo = MemberService::make()->getInfo(['id'=> $toUid,'status'=>1],[],false);
+                        if(empty($toInfo)){
+                            $this->info("【{$scene} {$date}】Chat:接收用户不存在,from@{$fromUid}-to@{$toUid}。");
+                            $this->sendMsg($frameId, ['success' => false,'op'=>'push','scene'=>$scene,'data'=>$data, 'message' => '对方账号不可用或无法接收消息']);
+                            return false;
+                        }
+                    }
+
+                    $fromUserName = isset($fromInfo['realname'])? $fromInfo['realname'] : ($fromUid>1? '用户'.$fromUid:'客服');
+                    $fromAvatar = isset($fromInfo['avatar']) && $fromInfo['avatar']? $fromInfo['avatar'] : get_image_url($fromUid>1?'/images/member/logo.png':'/images/member/custom.png');
+                    $toUserName = isset($toInfo['realname'])? $toInfo['realname'] : ($toUid>1? '用户'.$toUid:'客服');
+                    $toAvatar = isset($toInfo['avatar']) && $toInfo['avatar']? $toInfo['avatar'] : get_image_url($toUid>1?'/images/member/logo.png':'/images/member/custom.png');
+                    $msgData = [
+                        'from_uid' => $fromUid,
+                        'to_uid' => $toUid,
+                        'type' => 1,
+                        'msg_type' => $msgType,
+                        'title' => '聊天消息',
+                        'description' => $msgType == 2 ? '[图片]' : mb_substr($message, 0, 20),
+                        'content' => $msgType==2? get_image_path($message) : $message,
+                        'chat_key' => $chatKey,
+                        'create_time' => time(),
+                        'update_time' => time(),
+                        'is_read' => 2,
+                        'status' => 1
+                    ];
+                    // 敏感消息
+                    if(empty($message)){
+                        $msgData['from_user_name'] = $fromUserName;
+                        $msgData['from_user_avatar'] = get_image_url($fromAvatar, $apiUrl);
+                        $msgData['to_user_name'] = $toUserName;
+                        $msgData['to_user_avatar'] = get_image_url($toAvatar, $apiUrl);
+                        $msgData['time_text'] = dateFormat($msgData['create_time']);
+                        $msgData['content'] = '<span style="color: red;">敏感内容</span>';
+                        $this->sendMsg($frameId, ['success' => true, 'op' => 'push', 'scene'=> $scene,'custom_fd'=>$customFd, 'data' => $msgData, 'message' => '发送成功:' . $frameId]);
+                        return false;
+                    }
+
+                    if (!$id = MessageModel::insertGetId($msgData)) {
+                        $data = ['success' => false,'op'=>'push','scene'=>$scene,'data'=>$msgData, 'message' => '消息发送失败'];
+                        $this->sendMsg($frameId, $data);
+                        return false;
+                    }
+
+                    // 推送消息给对方
+                    $msgData['from_user_name'] = $fromUserName;
+                    $msgData['from_user_avatar'] = get_image_url($fromAvatar, $apiUrl);
+                    $msgData['to_user_name'] = $toUserName;
+                    $msgData['to_user_avatar'] = get_image_url($toAvatar, $apiUrl);
+                    $msgData['time_text'] = dateFormat($msgData['create_time']);
+                    if($msgData['msg_type'] == 1 || $msgData['msg_type'] == 3){
+                        $msgData['content'] = format_message($msgData['content']);
+                    }else if($msgData['msg_type'] == 2){
+                        $msgData['content'] = $msgData['content']? get_image_url($msgData['content'],$apiUrl) : '';
+                    }else if($msgData['msg_type'] == 4){
+                        $msgData['content'] = $msgData['content']? json_decode($msgData['content'], true) : [];
+                    }
+
+                    // 接收方缓存
+                    RedisService::clear("caches:messages:unread_count_{$toUid}");
+
+                    // 返回自身消息
+                    $this->sendMsg($frameId, ['success' => true, 'op' => 'push', 'scene'=> $scene,'custom_fd'=>$customFd, 'data' => $msgData, 'message' => '发送成功:' . $frameId]);
+
+                    // 推送给对方消息
+                    $pushCustom = ConfigService::make()->getConfigByCode('push_custom_message',1);
+                    $toBindData = RedisService::get("chats:bind:{$scene}_{$toUid}");
+                    $toFd = isset($toBindData['fd']) ? $toBindData['fd'] : 0;
+                    if ($toBindData && $toFd) {
+                        $this->sendMsg($toFd, ['success' => true, 'op' => 'push' ,'scene'=> $scene,'custom_fd'=>$customFd, 'data' => $msgData, 'message' => '推送消息成功:' . $toFd]);
+                        $this->info("【{$date}】Chat:客户端【{$frameId}-{$fromUid}】推送消息给【{$toFd}-{$toUid}。");
+                    }
+
+                    // 如果开启离线推送,或一直推送,根据关键词推送客服消息
+                    if((($pushCustom == 1 && !$toFd)||($pushCustom==2) && ($msgType == 1) )&& $fromUid >1){
+                        // 搜索内容
+                        $replyContent = ConfigService::make()->getContentByKw($message);
+                        $sendData = $msgData = [
+                            'from_uid' => 1,
+                            'to_uid' => $fromUid,
+                            'type' => 1,
+                            'msg_type' => 3,
+                            'title' => '客服消息',
+                            'description' => mb_substr($message, 0, 20),
+                            'content' => $replyContent,
+                            'chat_key' => $chatKey,
+                            'create_time' => time(),
+                            'update_time' => time(),
+                            'is_read' => 1,
+                            'status' => 1
+                        ];
+                        $sendData['from_user_name'] = $toUserName;
+                        $sendData['from_user_avatar'] = $toAvatar;
+                        $sendData['to_user_name'] = $fromUserName;
+                        $sendData['to_user_avatar'] = $fromAvatar;
+                        $sendData['content'] = format_message($replyContent);
+                        $sendData['time_text'] = dateFormat($msgData['create_time']);
+                        if($replyContent){
+                            if (MessageModel::insertGetId($msgData)) {
+                                $this->sendMsg($frameId, ['success' => true, 'op' => 'push', 'scene'=> $scene, 'data' => $sendData, 'message' => '回复成功:' . $frameId]);
+                            }
+                        }else{
+                            $replyContent = ConfigService::make()->getConfigByCode('custom_offline_reply','');
+                            if($replyContent){
+                                $sendData['content'] = format_message($replyContent);
+                                $this->sendMsg($frameId, ['success' => true, 'op' => 'push', 'scene'=> $scene, 'data' => $sendData, 'message' => '回复成功:' . $frameId]);
+
+                            }
+                        }
+                    }
+
+                    break;
+                case 'refund_apply': // 保证金退款申请消息通知
+                    $orderId = isset($data['order_id'])? $data['order_id'] : 0;
+
+                    // 发送参数验证
+                    if ($fromUid <= 0 || empty($message) || empty($orderId)) {
+                        $this->info("【{$scene} {$date}】Message:参数错误,from@{$fromUid}-to@{$toUid}。");
+                        $this->sendMsg($frameId, ['success' => false,'op'=>'notice','scene'=>$scene,'data'=>$data, 'message' => '参数错误']);
+                        return false;
+                    }
+
+                    // 订单信息
+                    $orderInfo = DepositService::make()->getInfo($orderId);
+                    $orderNo = isset($orderInfo['refund_no'])? $orderInfo['refund_no'] : '';
+                    $orderMoney = isset($orderInfo['refund_money'])? $orderInfo['refund_money'] : 0;
+                    if(empty($orderInfo) || $orderMoney<=0){
+                        $this->info("【{$scene} {$date}】Message:订单信息不存在,from@{$fromUid}-to@{$toUid}-{$orderId}。");
+                        $this->sendMsg($frameId, ['success' => false,'op'=>'notice','scene'=>$scene,'data'=>$data, 'message' => '订单信息不存在']);
+                        return false;
+                    }
+
+                    $msgData = [
+                        'from_uid' => $fromUid,
+                        'to_uid' => $toUid,
+                        'type' => 4,
+                        'msg_type' => 4,
+                        'title' => '保证金退款申请消息',
+                        'description' => $message,
+                        'order_no' => $orderNo,
+                        'content' => json_encode([
+                            'title'=> $message.'<span class="ele-text-primary">查看订单</span>',
+                            'order_no'=> $orderNo,
+                            'money'=> $orderMoney,
+                            'date'=> date('Y-m-d H:i:s'),
+                            'user_id'=> $fromUid,
+                            'type'=> 'deposit',
+                            'remark'=> '退保申请',
+                        ],256),
+                        'chat_key' => $chatKey,
+                        'create_time' => time(),
+                        'update_time' => time(),
+                        'is_read' => 2,
+                        'status' => 1
+                    ];
+                    if (!$id = MessageModel::insertGetId($msgData)) {
+                        $data = ['success' => false,'op'=>'notice','scene'=>$scene,'data'=>$msgData, 'message' => '消息发送失败'];
+                        $this->sendMsg($frameId, $data);
+                        return false;
+                    }
+
+                    // 推送消息给对方
+                    $msgData['time_text'] = dateFormat($msgData['create_time']);
+                    $msgData['content'] = $msgData['content']? json_decode($msgData['content'], true) : [];
+
+                    // 返回自身消息
+                    $this->sendMsg($frameId, ['success' => true, 'op' => 'notice', 'scene'=> $scene,'custom_fd'=>$customFd, 'data' => $msgData, 'message' => '发送成功:' . $frameId]);
+
+                    // 推送给对方消息
+                    $toBindData = RedisService::get("chats:bind:{$scene}_{$toUid}");
+                    $toFd = isset($toBindData['fd']) ? $toBindData['fd'] : 0;
+                    if ($toBindData && $toFd) {
+                        $this->sendMsg($toFd, ['success' => true, 'op' => 'notice' ,'scene'=> $scene,'custom_fd'=>$customFd, 'data' => ['count'=>1,'list'=>[$msgData]], 'message' => '推送消息成功:' . $toFd]);
+                        $this->info("【{$date}】Message:客户端【{$frameId}-{$fromUid}】推送消息给【{$toFd}-{$toUid}。");
+                    }
+                    break;
+                case 'notice': // 其他消息通知
+                    $type = isset($data['type']) ? $data['type'] : 5;
+                    $order = isset($data['order']) ? $data['order'] : [];
+
+                    // 发送参数验证
+                    if ($fromUid <= 0 || empty($message) || empty($order)) {
+                        $this->info("【{$scene} {$date}】Message:参数错误,from@{$fromUid}-to@{$toUid}。");
+                        $this->sendMsg($frameId, ['success' => false,'op'=>'notice','scene'=>$scene,'data'=>$data, 'message' => '参数错误']);
+                        return false;
+                    }
+
+                    $msgData = [
+                        'from_uid' => $fromUid,
+                        'to_uid' => $toUid,
+                        'type' => $type,
+                        'msg_type' => 4,
+                        'title' => $message,
+                        'order_no' => isset($order['order_no'])?$order['order_no'] : '',
+                        'description' => isset($order['title'])? $order['title'] : '有新的订单消息',
+                        'content' => json_encode($order,256),
+                        'chat_key' => $chatKey,
+                        'create_time' => time(),
+                        'update_time' => time(),
+                        'is_read' => 2,
+                        'status' => 1
+                    ];
+                    if (!$id = MessageModel::insertGetId($msgData)) {
+                        $data = ['success' => false,'op'=>'notice','scene'=>$scene,'data'=>$msgData, 'message' => '消息发送失败'];
+                        $this->sendMsg($frameId, $data);
+                        return false;
+                    }
+
+                    // 推送消息给对方
+                    $msgData['time_text'] = dateFormat($msgData['create_time']);
+                    $msgData['content'] = $msgData['content']? json_decode($msgData['content'], true) : [];
+
+                    // 返回自身消息
+                    $this->sendMsg($frameId, ['success' => true, 'op' => 'notice', 'scene'=> $scene,'custom_fd'=>$customFd, 'data' => $msgData, 'message' => '发送成功:' . $frameId]);
+
+                    // 推送给对方消息
+                    $toBindData = RedisService::get("chats:bind:{$scene}_{$toUid}");
+                    $toFd = isset($toBindData['fd']) ? $toBindData['fd'] : 0;
+                    echo $toFd;
+                    if ($toBindData && $toFd) {
+                        $this->sendMsg($toFd, ['success' => true, 'op' => 'notice' ,'scene'=> $scene,'custom_fd'=>$customFd, 'data' => ['count'=>1,'list'=>[$msgData]], 'message' => '推送消息成功:' . $toFd]);
+                        $this->info("【{$date}】Message:客户端【{$frameId}-{$fromUid}】推送消息给【{$toFd}-{$toUid}。");
+                    }
+                    break;
+                case 'login': // 登录
+                    if($toUid<=0){
+                        $toUid = 1;
+                        $data['to_uid'] = $toUid;
+                        $data['is_custom'] = true;
+                        $data['to_user_name'] = '客服';
+                    }
+
+                    // 未读消息
+                    $unreadCount = 0;
+                    if($fromUid==1){
+                        $unreadCount = intval(\App\Services\Api\MessageService::make()->getUnreadCount(1));
+                    }
+
+
+                    $fdData = RedisService::get("chats:bind:chat_".$toUid);
+                    $toFd = $fdData && isset($fdData['fd'])? $fdData['fd'] : 0;
+                    $checkFd = RedisService::get("chats:frames:" . $toFd);
+                    $online = $checkFd && $toFd? 1 : 0;
+                    $data['to_fd'] = $online? $toFd : 0;
+                    $data['chat_key'] = getChatKey($fromUid,$toUid);
+                    $this->info("【{$scene} {$date}】Socket:登录成功【{$frameId}-{$fromUid}-{$op}】。");
+                    $this->sendMsg($frameId, ['success' => true,'op'=> $op, 'scene'=>$scene,'custom_fd'=>$customFd,'unread'=>$unreadCount, 'message' => '登录成功', 'data' => $data, 't' => time()]);
+                    break;
+                 default:
+                    $this->sendMsg($frameId, ['success' => false, 'message' => 'ok', 'scene'=>$scene,'custom_fd'=>$customFd, 'data' => $data, 't' => time()]);
+                    break;
+            }
+
+            $this->info("【{$scene} {$date}】Chat:客户端【{$frameId}】消息处理成功");
+        } catch (\Exception $exception) {
+            RedisService::set("caches:sockets:error_{$frameId}", ['error' => $exception->getMessage(),'trace'=>$exception->getTrace(), 'date' => $date], 7200);
+            $this->info("【{$scene} {$date}】Chat:客户端【{$frameId}】消息处理错误 " . $exception->getMessage());
+        }
+    }
+
+    /**
+     * 签名验证
+     * @param $data
+     * @return bool
+     */
+    public function checkSign($data)
+    {
+        $checkSign = isset($data['sign']) ? $data['sign'] : '';
+        $sign = getSign($data);
+        if ($sign != $checkSign) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 推送消息
+     * @param $fd
+     * @param $op
+     * @param $data
+     */
+    public function sendMsg($fd, $data)
+    {
+        $date = date('Y-m-d H:i:s');
+        try {
+            if (!RedisService::exists("chats:frames:" . $fd)) {
+                $this->info("【{$date}】Chat:客户端【{$fd}】推送用户已经掉线 ");
+                return false;
+            }
+            $this->ws->push($fd, json_encode($data, 256));
+        } catch (\Exception $exception) {
+            $this->info("【{$date}】Chat:客户端【{$fd}】消息处理错误 " . $exception->getMessage());
+        }
+    }
+
+    /**
+     * 接收请求
+     * @param $request
+     * @param $response
+     */
+    public function request($request, $response)
+    {
+
+    }
+
+    /**
+     * 关闭连接
+     * @param $ws
+     * @param $fd
+     */
+    public function close($ws, $fd = '')
+    {
+        $date = date('Y-m-d H:i:s');
+        RedisService::clear("chats:frames:" . $fd);
+        $this->info("【{$date}】Chat:客户端【{$fd}】连接关闭");
+        RedisService::clear('chats:checkCustom:from_'.$fd);
+        $this->ws->close($fd);
+
+        // 清理历史消息
+        if(!RedisService::get("caches:messages:clear")){
+            $chatLogCount = ConfigService::make()->getConfigByCode('chat_log_count',300);
+            $expireTime = ConfigService::make()->getConfigByCode('chat_log_expire',30);
+            $expireTime = $expireTime>0 && $expireTime <= 365? $expireTime : 30;
+            $expireTime = $expireTime * 24 * 3600;
+            if(MessageModel::count('id')>$chatLogCount){
+                MessageModel::where('create_time','<', time() - $expireTime)->delete();
+            }
+        }
+    }
+
+    /**
+     * 停止运行
+     */
+    public function stop()
+    {
+        // 直接杀
+        $stoSh = base_path().'/crontab/socketStop.sh';
+        if(file_exists($stoSh) && function_exists('exec')){
+            exec("{$stoSh}");
+        }
+
+        echo "$stoSh\n";
+        echo "chat stop success...\n";
+
+        if ($this->ws) {
+            $date = date('Y-m-d H:i:s');
+            $this->info("【{$date}】Chat:停止运行服务");
+            $this->ws->close();
+        }
+    }
+
+    /**
+     * 消息
+     * @param string $data
+     */
+    public function info($data,$verbosity=true)
+    {
+        \logger()->channel('chat')->info($data);
+        if(env('SWOOLE_LOG', true) && $verbosity){
+            parent::info($data);
+        }
+    }
+}

+ 41 - 0
app/Console/Kernel.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace App\Console;
+
+use Illuminate\Console\Scheduling\Schedule;
+use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
+
+class Kernel extends ConsoleKernel
+{
+    /**
+     * The Artisan commands provided by your application.
+     *
+     * @var array
+     */
+    protected $commands = [
+        //
+    ];
+
+    /**
+     * Define the application's command schedule.
+     *
+     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
+     * @return void
+     */
+    protected function schedule(Schedule $schedule)
+    {
+        // $schedule->command('inspire')->hourly();
+    }
+
+    /**
+     * Register the commands for the application.
+     *
+     * @return void
+     */
+    protected function commands()
+    {
+        $this->load(__DIR__.'/Commands');
+
+        require base_path('routes/console.php');
+    }
+}

+ 37 - 0
app/Exceptions/Handler.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace App\Exceptions;
+
+use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
+
+class Handler extends ExceptionHandler
+{
+    /**
+     * A list of the exception types that are not reported.
+     *
+     * @var array
+     */
+    protected $dontReport = [
+        //
+    ];
+
+    /**
+     * A list of the inputs that are never flashed for validation exceptions.
+     *
+     * @var array
+     */
+    protected $dontFlash = [
+        'password',
+        'password_confirmation',
+    ];
+
+    /**
+     * Register the exception handling callbacks for the application.
+     *
+     * @return void
+     */
+    public function register()
+    {
+        //
+    }
+}

+ 238 - 0
app/Exports/Export.php

@@ -0,0 +1,238 @@
+<?php
+
+namespace App\Exports;
+
+use Illuminate\Support\Collection;
+use Maatwebsite\Excel\Concerns\FromCollection;
+use Maatwebsite\Excel\Concerns\WithEvents;
+use Maatwebsite\Excel\Concerns\WithHeadings;
+use Maatwebsite\Excel\Events\AfterSheet;
+use PhpOffice\PhpSpreadsheet\Style\Border;
+
+/**
+ * 导出Excel类
+ * @author 牧羊人
+ * @since 2021/4/10
+ * Class Export
+ * @package App\Exports
+ */
+class Export implements FromCollection, WithHeadings, WithEvents
+{
+    protected $data;
+    protected $headings;
+    protected $columnWidth = [];//设置列宽       key:列  value:宽
+    protected $rowHeight = [];  //设置行高       key:行  value:高
+    protected $mergeCells = []; //合并单元格    value:A1:K8
+    protected $font = [];       //设置字体       key:A1:K8  value:Arial
+    protected $fontSize = [];       //设置字体大小       key:A1:K8  value:11
+    protected $bold = [];       //设置粗体       key:A1:K8  value:true
+    protected $background = []; //设置背景颜色    key:A1:K8  value:#F0F0F0F
+    protected $vertical = [];   //设置定位       key:A1:K8  value:center
+    protected $sheetName; //sheet title
+    protected $borders = []; //设置边框颜色  key:A1:K8  value:#000000
+    //设置页面属性时如果无效   更改excel格式尝试即可
+    //构造函数传值
+    public function __construct($data, $headings, $sheetName)
+    {
+        $this->data = $data;
+        $this->headings = $headings;
+        $this->sheetName = $sheetName;
+        $this->createData();
+    }
+
+    public function headings(): array
+    {
+        return $this->headings;
+    }
+
+    //数组转集合
+    public function collection()
+    {
+        return new Collection($this->data);
+    }
+
+    //业务代码
+    public function createData()
+    {
+        $this->data = collect($this->data)->toArray();
+    }
+
+    public function registerEvents(): array
+    {
+        return [
+            AfterSheet::class => function (AfterSheet $event) {
+                //设置区域单元格垂直居中
+                $event->sheet->getDelegate()->getStyle('A1:Z1265')->getAlignment()->setVertical('center');
+                //设置区域单元格水平居中
+                $event->sheet->getDelegate()->getStyle('A1:Z1265')->getAlignment()->setHorizontal('center');
+                //设置列宽
+                foreach ($this->columnWidth as $column => $width) {
+                    $event->sheet->getDelegate()
+                        ->getColumnDimension($column)
+                        ->setWidth($width);
+                }
+                //设置行高,$i为数据行数
+                foreach ($this->rowHeight as $row => $height) {
+                    $event->sheet->getDelegate()
+                        ->getRowDimension($row)
+                        ->setRowHeight($height);
+                }
+
+                //设置区域单元格垂直居中
+                foreach ($this->vertical as $region => $position) {
+                    $event->sheet->getDelegate()
+                        ->getStyle($region)
+                        ->getAlignment()
+                        ->setVertical($position);
+                }
+
+                //设置区域单元格字体
+                foreach ($this->font as $region => $value) {
+                    $event->sheet->getDelegate()
+                        ->getStyle($region)
+                        ->getFont()->setName($value);
+                }
+                //设置区域单元格字体大小
+                foreach ($this->fontSize as $region => $value) {
+                    $event->sheet->getDelegate()
+                        ->getStyle($region)
+                        ->getFont()
+                        ->setSize($value);
+                }
+
+                //设置区域单元格字体粗体
+                foreach ($this->bold as $region => $bool) {
+                    $event->sheet->getDelegate()
+                        ->getStyle($region)
+                        ->getFont()
+                        ->setBold($bool);
+                }
+
+
+                //设置区域单元格背景颜色
+                foreach ($this->background as $region => $item) {
+                    $event->sheet->getDelegate()->getStyle($region)->applyFromArray([
+                        'fill' => [
+                            'fillType' => 'linear', //线性填充,类似渐变
+                            'startColor' => [
+                                'rgb' => $item //初始颜色
+                            ],
+                            //结束颜色,如果需要单一背景色,请和初始颜色保持一致
+                            'endColor' => [
+                                'argb' => $item
+                            ]
+                        ]
+                    ]);
+                }
+                //设置边框颜色
+                foreach ($this->borders as $region => $item) {
+                    $event->sheet->getDelegate()->getStyle($region)->applyFromArray([
+                        'borders' => [
+                            'allBorders' => [
+                                'borderStyle' => Border::BORDER_THIN,
+                                'color' => ['argb' => $item],
+                            ],
+                        ],
+                    ]);
+                }
+                //合并单元格
+                $event->sheet->getDelegate()->setMergeCells($this->mergeCells);
+                if (!empty($this->sheetName)) {
+                    $event->sheet->getDelegate()->setTitle($this->sheetName);
+                }
+            }
+        ];
+    }
+
+    /**
+     * @return array
+     * [
+     *    'B' => 40,
+     *    'C' => 60
+     * ]
+     */
+    public function setColumnWidth(array $columnwidth)
+    {
+        $this->columnWidth = array_change_key_case($columnwidth, CASE_UPPER);
+    }
+
+    /**
+     * @return array
+     * [
+     *    1 => 40,
+     *    2 => 60
+     * ]
+     */
+    public function setRowHeight(array $rowHeight)
+    {
+        $this->rowHeight = $rowHeight;
+    }
+
+    /**
+     * @return array
+     * [
+     *    A1:K7 => '宋体'
+     * ]
+     */
+    public function setFont(array $font)
+    {
+        $this->font = array_change_key_case($font, CASE_UPPER);
+    }
+
+    /**
+     * @return array
+     * @2020/3/22 10:33
+     * [
+     *    A1:K7 => true
+     * ]
+     */
+    public function setBold(array $bold)
+    {
+        $this->bold = array_change_key_case($bold, CASE_UPPER);
+    }
+
+    /**
+     * @return array
+     * @2020/3/22 10:33
+     * [
+     *    A1:K7 => F0FF0F
+     * ]
+     */
+    public function setBackground(array $background)
+    {
+        $this->background = array_change_key_case($background, CASE_UPPER);
+    }
+
+    /**
+     * @return array
+     * [
+     *    A1:K7
+     * ]
+     */
+    public function setMergeCells(array $mergeCells)
+    {
+        $this->mergeCells = array_change_key_case($mergeCells, CASE_UPPER);
+    }
+
+    /**
+     * @return array
+     * [
+     *    A1:K7 => 14
+     * ]
+     */
+    public function setFontSize(array $fontSize)
+    {
+        $this->fontSize = array_change_key_case($fontSize, CASE_UPPER);
+    }
+
+    /**
+     * @return array
+     * [
+     *    A1:K7 => #000000
+     * ]
+     */
+    public function setBorders(array $borders)
+    {
+        $this->borders = array_change_key_case($borders, CASE_UPPER);
+    }
+}

+ 212 - 0
app/Helpers/Jwt.php

@@ -0,0 +1,212 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Helpers;
+
+/**
+ * JWT鉴权
+ * @author laravel开发员
+ * @since 2020/11/14
+ * Class Jwt
+ * @package App\Helpers
+ */
+class Jwt
+{
+    // 头部
+    private static $header = [
+        'alg' => 'HS256', //生成signature的算法
+        'typ' => 'JWT'    //JWT 令牌统一写为JWT
+    ];
+
+    // 使用HMAC生成信息摘要时所使用的密钥
+    private static $key = '34c68cdccb5b6feb4f7f0a5ede9f5932';
+    private static $scene = 'jwt_yh';
+
+    public function __construct($scene='')
+    {
+        if($scene){
+            self::$scene = $scene;
+        }
+    }
+
+    /**
+     * alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT
+     * @return string
+     * @author laravel开发员
+     * @since 2020/11/14
+     */
+    public function getHeader()
+    {
+        return self::base64UrlEncode(json_encode(self::$header, JSON_UNESCAPED_UNICODE));
+    }
+
+   /**
+     * Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据
+     * JWT 规定了7个官方字段,供选用,这里可以存放私有信息,比如uid
+     * @param $uid
+     * @return string
+     * @author laravel开发员
+     * @since 2020/11/14
+     */
+    public function getPayload($uid)
+    {
+        $payload = [
+            'iss' => self::$scene?self::$scene:'jwt_yh', //签发人
+            'exp' => time() + 60 * 60 * 24 * 7, //过期时间
+            'sub' => 'YH', //主题
+            'aud' => 'every', //受众
+            'nbf' => time(), //生效时间,该时间之前不接收处理该Token
+            'iat' => time(), //签发时间
+            'jti' => 10001, //编号(JWT ID用于标识该JWT)
+            'uid' => $uid, //私有信息,uid
+        ];
+
+        return self::base64UrlEncode(json_encode($payload, JSON_UNESCAPED_UNICODE));
+    }
+
+    /**
+     * 获取Token
+     * @param array $payload jwt载荷
+     * 格式如下非必须:
+     * [
+     *  'iss'=>'jwt_admin',  //该JWT的签发者
+     *  'iat'=>time(),  //签发时间
+     *  'exp'=>time()+7200,  //过期时间
+     *  'nbf'=>time()+60,  //该时间之前不接收处理该Token
+     *  'sub'=>'www.admin.com',  //面向的用户
+     *  'jti'=>md5(uniqid('JWT').time())  //该Token唯一标识
+     * ]
+     * @return bool|string 返回结果
+     * @author laravel开发员
+     * @since 2020/11/14
+     */
+    public function getToken($uid)
+    {
+        // 获取JWT头
+        $header = self::getHeader();
+        // 获取JWT有效载荷
+        $payload = self::getPayload($uid);
+
+        // JWT头拼接JWT有效载荷
+        $raw = $header . '.' . $payload;
+
+        $sign = self::signature($raw, self::$key, self::$header['alg']);
+        // Token字符串
+        $token = $raw . '.' . $sign;
+        // 返回Token
+        return $token;
+    }
+
+    /**
+     * 验证token是否有效,默认验证exp,nbf,iat时间
+     * @param string $token token字符串
+     * @return bool|mixed 返回结果
+     * @author laravel开发员
+     * @since 2020/11/14
+     */
+    public function verifyToken(string $token)
+    {
+        if (!$token) {
+            return false;
+        }
+        $tokens = explode('.', $token);
+
+        if (count($tokens) != 3) {
+            return false;
+        }
+
+        list($base64header, $base64payload, $sign) = $tokens;
+
+        // 获取jwt算法
+        $base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);
+        if (empty($base64decodeheader['alg'])) {
+            return false;
+        }
+
+        //签名验证
+        if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign) {
+            return false;
+        }
+
+        $payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);
+
+
+
+        //签发时间大于当前服务器时间验证失败
+        if (isset($payload['iat']) && $payload['iat'] > time()) {
+            return false;
+        }
+
+        //过期时间小宇当前服务器时间验证失败
+        if (isset($payload['exp']) && $payload['exp'] < time()) {
+            return false;
+        }
+
+        //该nbf时间之前不接收处理该Token
+        if (isset($payload['nbf']) && $payload['nbf'] > time()) {
+            return false;
+        }
+
+        $uid = isset($payload['uid'])? $payload['uid'] : 0;
+        $scene = isset($payload['iss'])? $payload['iss'] : '';
+        if($scene != self::$scene){
+            return false;
+        }
+
+        return $uid;
+    }
+
+    /**
+     * base64UrlEncode编码实现
+     * @param string $str 需要编码的字符串
+     * @return mixed 返回结果
+     * @author laravel开发员
+     * @since 2020/11/14
+     */
+    private static function base64UrlEncode(string $str)
+    {
+        return str_replace('=', '', strtr(base64_encode($str), '+/', '-_'));
+    }
+
+    /**
+     * base64UrlDecode解码实现
+     * @param string $str 需要解码的字符串
+     * @return bool|string 返回结果
+     * @author laravel开发员
+     * @since 2020/11/14
+     */
+    private static function base64UrlDecode(string $str)
+    {
+        $remainder = strlen($str) % 4;
+        if ($remainder) {
+            $addlen = 4 - $remainder;
+            $str .= str_repeat('=', $addlen);
+        }
+        return base64_decode(strtr($str, '-_', '+/'));
+    }
+
+    /**
+     * HMACSHA256签名实现
+     * @param string $str 待签名字符串
+     * @param string $key 加密密钥
+     * @param string $alg 算法方式
+     * @return mixed 返回结果
+     * @author laravel开发员
+     * @since 2020/11/14
+     */
+    private static function signature(string $str, string $key, string $alg)
+    {
+        $alg_config = array(
+            'HS256' => 'sha256'
+        );
+        return self::base64UrlEncode(hash_hmac($alg_config[$alg], $str, $key, true));
+    }
+}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2361 - 0
app/Helpers/common.php


+ 22 - 0
app/Helpers/constants.php

@@ -0,0 +1,22 @@
+<?php
+/// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+// 自定义系统常量公共类
+
+define('MESSAGE_OK', '操作成功');
+define('MESSAGE_FAILED', '操作失败');
+define('MESSAGE_SYSTEM_ERROR', '系统繁忙,请稍后再试');
+define('MESSAGE_PARAMETER_MISSING', '参数丢失');
+define('MESSAGE_PARAMETER_ERROR', '参数错误');
+define('MESSAGE_PERMISSON_DENIED', '没有权限');
+define('MESSAGE_INTERNAL_ERROR', '服务器繁忙,请稍后再试');
+
+define('MESSAGE_NEEDLOGIN', '请登录');

+ 11 - 0
app/Helpers/function.php

@@ -0,0 +1,11 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+

+ 63 - 0
app/Http/Controllers/Admin/AccountController.php

@@ -0,0 +1,63 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\AccountService;
+
+/**
+ * 账户明细管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class AccountController
+ * @package App\Http\Controllers
+ */
+class AccountController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * AccountController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new AccountService();
+    }
+
+    // 记录
+    public function index()
+    {
+        try {
+            $pageSize = request()->get('limit', 15);
+            $list = $this->service->getDataList(request()->all(), $pageSize);
+            $message = array(
+                "msg" => '操作成功',
+                "code" => 0,
+                "data" => isset($list['list'])? $list['list']:[],
+                "counts" => isset($list['counts'])? $list['counts']:[],
+                "count" => isset($list['total'])? $list['total']:0,
+            );
+            return $message;
+        } catch (\Exception $exception){
+            $message = array(
+                "msg" => '失败:'.$exception->getMessage(),
+                "code" => -1,
+                "counts" => [],
+                "data" => [],
+                "count" => 0,
+            );
+            return $message;
+        }
+
+    }
+}

+ 36 - 0
app/Http/Controllers/Admin/ActionLogController.php

@@ -0,0 +1,36 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\ActionLogService;
+
+/**
+ * 行为日志-控制器
+ * @author laravel开发员
+ * @since 2020/11/12
+ * Class ActionLogController
+ * @package App\Http\Controllers
+ */
+class ActionLogController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/12
+     * ActionLogController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new ActionLogService();
+    }
+}

+ 37 - 0
app/Http/Controllers/Admin/AdController.php

@@ -0,0 +1,37 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+
+use App\Services\Common\AdService;
+
+/**
+ * 广告管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class AdController
+ * @package App\Http\Controllers
+ */
+class AdController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * AdController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new AdService();
+    }
+}

+ 41 - 0
app/Http/Controllers/Admin/ArticleController.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+use App\Services\Common\ArticleService;
+
+/**
+ * 文章
+ * Class ArticleController
+ * @package App\Http\Controllers\Admin
+ */
+class ArticleController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * ArticleController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new ArticleService();
+    }
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function index()
+    {
+        $pageSize = request()->get('limit', 15);
+        $list = $this->service->getDataList(request()->all(), $pageSize);
+        $message = array(
+            "msg" => '操作成功',
+            "code" => 0,
+            "data" => isset($list['list'])? $list['list']:[],
+            "count" => isset($list['total'])? $list['total']:0,
+        );
+        return $message;
+    }
+}

+ 165 - 0
app/Http/Controllers/Admin/Backend.php

@@ -0,0 +1,165 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Helpers\Jwt;
+use App\Http\Controllers\BaseController;
+use App\Models\UserModel;
+
+/**
+ * 后台控制器基类
+ * @author laravel开发员
+ * @since 2020/11/10
+ * Class Backend
+ * @package App\Http\Controllers
+ */
+class Backend extends BaseController
+{
+    // 模型
+    protected $model;
+    // 服务
+    protected $service;
+    // 校验
+    protected $validate;
+    // 登录ID
+    protected $userId;
+    // 登录信息
+    protected $userInfo;
+
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/10
+     * Backend constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        // 初始化配置
+        $this->initConfig();
+
+        // 登录检测中间件
+        $this->middleware('user.login');
+
+        // 初始化登录信息
+        $this->middleware(function ($request, $next) {
+            // 请求头信息
+            $token = $request->headers->get('Authorization');
+            $token = str_replace("Bearer ", null, $token);
+            // JWT解密token
+            $jwt = new Jwt();
+            $userId = $jwt->verifyToken($token);
+
+            // 登录验证
+            $this->initLogin($userId);
+
+            return $next($request);
+        });
+    }
+
+    /**
+     * 初始化配置
+     * @author laravel开发员
+     * @since 2020/11/10
+     */
+    public function initConfig()
+    {
+        // 请求参数
+        $this->param = \request()->input();
+
+        // 分页基础默认值
+        defined('PERPAGE') or define('PERPAGE', isset($this->param['limit']) ? $this->param['limit'] : 20);
+        defined('PAGE') or define('PAGE', isset($this->param['page']) ? $this->param['page'] : 1);
+    }
+
+    /**
+     * 登录验证
+     * @param $userId 用户ID
+     * @return
+     * @author laravel开发员
+     * @since 2020/8/31
+     */
+    public function initLogin($userId)
+    {
+        // 登录用户ID
+        $this->userId = $userId;
+
+        // 登录用户信息
+        if ($userId) {
+            $adminModel = new UserModel();
+            $userInfo = $adminModel->getInfo($this->userId);
+            $this->userInfo = $userInfo;
+        }
+
+    }
+
+    /**
+     * 获取数据列表
+     * @return mixed
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function index()
+    {
+        $result = $this->service->getList();
+        return $result;
+    }
+
+    /**
+     * 获取数据详情
+     * @return mixed
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function info()
+    {
+        $result = $this->service->info();
+        return $result;
+    }
+
+    /**
+     * 添加或编辑
+     * @return mixed
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function edit()
+    {
+        $result = $this->service->edit();
+        return $result;
+    }
+
+    /**
+     * 删除数据
+     * @return mixed
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function delete()
+    {
+        $result = $this->service->delete();
+        return $result;
+    }
+
+    /**
+     * 设置状态
+     * @return mixed
+     * @since 2020/11/21
+     * @author laravel开发员
+     */
+    public function status()
+    {
+        $result = $this->service->status();
+        return $result;
+    }
+
+}

+ 36 - 0
app/Http/Controllers/Admin/CityController.php

@@ -0,0 +1,36 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\CityService;
+
+/**
+ * 城市管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class CityController
+ * @package App\Http\Controllers
+ */
+class CityController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * CityController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new CityService();
+    }
+}

+ 36 - 0
app/Http/Controllers/Admin/ConfigController.php

@@ -0,0 +1,36 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\ConfigService;
+
+/**
+ * 配置管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class ConfigController
+ * @package App\Http\Controllers
+ */
+class ConfigController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * ConfigController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new ConfigService();
+    }
+}

+ 36 - 0
app/Http/Controllers/Admin/ConfigGroupController.php

@@ -0,0 +1,36 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\ConfigGroupService;
+
+/**
+ * 配置分组-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class ConfigGroupController
+ * @package App\Http\Controllers
+ */
+class ConfigGroupController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * ConfigGroupController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new ConfigGroupService();
+    }
+}

+ 22 - 0
app/Http/Controllers/Admin/Controller.php

@@ -0,0 +1,22 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
+use Illuminate\Foundation\Bus\DispatchesJobs;
+use Illuminate\Foundation\Validation\ValidatesRequests;
+use Illuminate\Routing\Controller as BaseController;
+
+class Controller extends BaseController
+{
+    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
+}

+ 111 - 0
app/Http/Controllers/Admin/DepositController.php

@@ -0,0 +1,111 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\DepositService;
+
+/**
+ * 保证金管理
+ * @package App\Http\Controllers\Admin
+ */
+class DepositController extends Backend
+{
+
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * GoodsController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new DepositService();
+    }
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function index()
+    {
+        $pageSize = request()->get('limit', 10);
+        $list = $this->service->getDataList(request()->all(), $pageSize);
+        $message = array(
+            "msg" => '操作成功',
+            "code" => 0,
+            "data" => isset($list['list'])? $list['list']:[],
+            "counts" => isset($list['counts'])? $list['counts']:[],
+            "count" => isset($list['total'])? $list['total']:0,
+        );
+        return $message;
+    }
+
+
+    /**
+     * 审核
+     * @return array
+     */
+    public function confirm()
+    {
+        $params = request()->post();
+        if(DepositService::make()->confirm($this->userId,$params)){
+            return message(DepositService::make()->getError(), true);
+        }else{
+            return message(DepositService::make()->getError(), false);
+        }
+    }
+
+    /**
+     * 打款
+     * @return array
+     */
+    public function payment()
+    {
+        $params = request()->post();
+        if(DepositService::make()->payment($this->userId,$params)){
+            return message(DepositService::make()->getError(), true);
+        }else{
+            return message(DepositService::make()->getError(), false);
+        }
+    }
+
+    /**
+     * 获取配置
+     * @return array
+     */
+    public function getSetting()
+    {
+        if($config = DepositService::make()->getSetting()){
+            return message(1010, true, $config);
+        }else{
+            return message(1009, false);
+        }
+    }
+
+    /**
+     * 保存设置
+     * @return array
+     */
+    public function saveSetting()
+    {
+        $params = request()->post();
+        if(DepositService::make()->saveSetting($this->userId,$params)){
+            return message(DepositService::make()->getError(), true);
+        }else{
+            return message(DepositService::make()->getError(), false);
+        }
+    }
+
+    /**
+     * 删除数据
+     * @return mixed
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function delete()
+    {
+        $result = $this->service->delete();
+        return $result;
+    }
+}

+ 57 - 0
app/Http/Controllers/Admin/DriverController.php

@@ -0,0 +1,57 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+
+use App\Services\Common\DriverService;
+
+/**
+ * 司机管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Http\Controllers
+ */
+class DriverController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new DriverService();
+    }
+
+    public function index()
+    {
+        $pageSize = request()->get('limit', 10);
+        $list = $this->service->getDataList(request()->all(), $pageSize);
+        $message = array(
+            "msg" => '操作成功',
+            "code" => 0,
+            "data" => isset($list['list'])? $list['list']:[],
+            "count" => isset($list['total'])? $list['total']:0,
+        );
+        return $message;
+    }
+
+    /**
+     * 选项列表
+     * @return mixed
+     */
+    public function options(){
+        $result = $this->service->options();
+        return message(1002,true, $result);
+    }
+}

+ 66 - 0
app/Http/Controllers/Admin/GoodsController.php

@@ -0,0 +1,66 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+
+use App\Services\Common\GoodsService;
+
+/**
+ * 商品管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class GoodsController
+ * @package App\Http\Controllers
+ */
+class GoodsController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * GoodsController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new GoodsService();
+    }
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function index()
+    {
+        $pageSize = request()->get('limit', 10);
+        $list = $this->service->getDataList(request()->all(), $pageSize);
+        $message = array(
+            "msg" => '操作成功',
+            "code" => 0,
+            "data" => isset($list['list'])? $list['list']:[],
+            "count" => isset($list['total'])? $list['total']:0,
+        );
+        return $message;
+    }
+
+    /**
+     * 删除数据
+     * @return mixed
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function delete()
+    {
+        $result = $this->service->delete();
+        return $result;
+    }
+}

+ 159 - 0
app/Http/Controllers/Admin/IndexController.php

@@ -0,0 +1,159 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\BalanceLogService;
+use App\Services\Common\DepositService;
+use App\Services\Common\GoodsService;
+use App\Services\Common\MemberService;
+use App\Services\Common\MenuService;
+use App\Services\Common\OrderService;
+use App\Services\Common\UserService;
+use App\Services\RedisService;
+use App\utils\TimeUtils;
+
+/**
+ * 系统主页控制器
+ * @author laravel开发员
+ * @since 2020/11/10
+ * Class IndexController
+ * @package App\Http\Controllers
+ */
+class IndexController extends Backend
+{
+
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/10
+     * IndexController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * 后台主页
+     * @author laravel开发员
+     * @since 2020/11/10
+     */
+    public function getMenuList()
+    {
+        $menuService = new MenuService();
+        $menuList = $menuService->getPermissionList($this->userId);
+        return $menuList;
+    }
+
+    /**
+     * 获取个人信息
+     * @return array
+     * @since 2020/11/10
+     * @author laravel开发员
+     */
+    public function getUserInfo()
+    {
+        $userService = new UserService();
+        $result = $userService->getUserInfo($this->userId);
+        return $result;
+    }
+
+    /**
+     * 更新个人资料
+     * @return mixed
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function updateUserInfo()
+    {
+        $userService = new UserService();
+        $result = $userService->updateUserInfo($this->userId);
+        return $result;
+    }
+
+    /**
+     * 更新密码
+     * @return mixed
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function updatePwd()
+    {
+        $userService = new UserService();
+        $result = $userService->updatePwd($this->userId);
+        return $result;
+    }
+
+    /**
+     * 清除缓存
+     * @return array
+     */
+    public function clearCache()
+    {
+
+        RedisService::keyDel("caches:adm*");
+        RedisService::keyDel("caches:index*");
+        RedisService::keyDel("caches:good*");
+        RedisService::keyDel("caches:advert*");
+        RedisService::keyDel("caches:count*");
+        RedisService::keyDel("caches:account*");
+        RedisService::keyDel("caches:article*");
+        RedisService::keyDel("caches:member*");
+        RedisService::keyDel("caches:config*");
+        RedisService::keyDel("caches:deposit*");
+        RedisService::keyDel("caches:order*");
+        RedisService::keyDel(env('APP_NAME')."_cache:*");
+        //Cache::flush();
+        return message(MESSAGE_OK, true);
+    }
+
+    /**
+     * 获取首页数据
+     * @return array
+     */
+    public function statistics()
+    {
+        $datas = [
+            // 用户
+            'users'    => [
+                'count'            => MemberService::make()->getRegisterCount(),  // 总用户数
+                'count_by_day'     => MemberService::make()->getRegisterCount(TimeUtils::beginToday(), TimeUtils::endToday()),  // 今日注册
+                'count_by_month'   => MemberService::make()->getRegisterCount(TimeUtils::beginMonth(), TimeUtils::endMonth()), // 本月注册
+                'count_by_confirm'   => MemberService::make()->getRegisterCount(0,0,2), // 待审核
+            ],
+            'goods'=>[
+                'count_by_all'=> GoodsService::make()->getCounts(0),
+                'count_by_up'=> GoodsService::make()->getCounts(1),
+                'count_by_success'=> GoodsService::make()->getCounts(2),
+            ],
+            // 订单
+            'orders'   => [
+                'count'   => OrderService::make()->getCountByTime(), // 总量
+                'count_by_day'     => OrderService::make()->getCountByTime(TimeUtils::beginToday(), TimeUtils::endToday()),  // 今日
+                'count_by_month'   => OrderService::make()->getCountByTime(TimeUtils::beginMonth(), TimeUtils::endMonth()), // 本月
+                'amount_by_day'   => OrderService::make()->getTotalByTime(TimeUtils::beginToday(), TimeUtils::endToday()), // 日营业额
+                'amount_by_month'   =>  OrderService::make()->getTotalByTime(TimeUtils::beginMonth(), TimeUtils::endMonth()), // 月营业额
+            ],
+            'deposit'=>[
+                'total'=> DepositService::make()->getTotal(0),
+                'withdraw'=> DepositService::make()->getTotal(1),
+            ],
+            // 营收
+            'balance'   => [
+                'income_by_total'=> OrderService::make()->getTotalByTime(),
+                'withdraw_by_total'=> BalanceLogService::make()->getTotal(),
+            ],
+        ];
+
+        return message(1010, true, $datas);
+    }
+}

+ 37 - 0
app/Http/Controllers/Admin/LayoutController.php

@@ -0,0 +1,37 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\LayoutService;
+
+/**
+ * 布局管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class LayoutController
+ * @package App\Http\Controllers
+ */
+class LayoutController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * LayoutController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new LayoutService();
+    }
+
+}

+ 73 - 0
app/Http/Controllers/Admin/LoginController.php

@@ -0,0 +1,73 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Models\ActionLogModel;
+use App\Services\Common\LoginService;
+
+/**
+ * 登录控制器
+ * @author laravel开发员
+ * @since 2020/11/10
+ * Class LoginController
+ * @package App\Http\Controllers
+ */
+class LoginController extends Backend
+{
+
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/10
+     * LoginController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new LoginService();
+    }
+
+    /**
+     * 获取验证码
+     * @return mixed
+     * @since 2020/11/10
+     * @author laravel开发员
+     */
+    public function captcha()
+    {
+        $result = $this->service->captcha();
+        return $result;
+    }
+
+    /**
+     * 系统登录
+     * @author laravel开发员
+     * @since 2020/11/10
+     */
+    public function login()
+    {
+        $result = $this->service->login();
+        return $result;
+    }
+
+    /**
+     * 退出系统
+     * @author laravel开发员
+     * @since 2020/11/10
+     */
+    public function logout()
+    {
+        $result = $this->service->logout();
+        return $result;
+    }
+
+}

+ 83 - 0
app/Http/Controllers/Admin/MemberController.php

@@ -0,0 +1,83 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Http\Validator\MemberValidator;
+use App\Services\Common\MemberService;
+
+/**
+ * 会员管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class MemberController
+ * @package App\Http\Controllers
+ */
+class MemberController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * MemberController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new MemberService();
+    }
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function index()
+    {
+        $pageSize = request()->get('limit', 10);
+        $list = $this->service->getDataList(request()->all(), $pageSize);
+        $message = array(
+            "msg" => '操作成功',
+            "code" => 0,
+            "data" => isset($list['list'])? $list['list']:[],
+            "count" => isset($list['total'])? $list['total']:0,
+        );
+        return $message;
+    }
+
+    /**
+     * 审核
+     * @return array
+     */
+    public function confirm(MemberValidator $validator)
+    {
+        $params = request()->post();
+        $params = $validator->check($params, 'confirm');
+        if (!is_array($params)) {
+            return message($params, false);
+        }
+
+        if(MemberService::make()->confirm($this->userId,$params)){
+            return message(MemberService::make()->getError(), true);
+        }else{
+            return message(MemberService::make()->getError(), false);
+        }
+    }
+
+
+    /**
+     * 选项列表
+     * @return mixed
+     */
+    public function options(){
+        $result = $this->service->options();
+        return message(1002,true, $result);
+    }
+}

+ 36 - 0
app/Http/Controllers/Admin/MenuController.php

@@ -0,0 +1,36 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\MenuService;
+
+/**
+ * 菜单管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class MenuController
+ * @package App\Http\Controllers
+ */
+class MenuController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * MenuController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new MenuService();
+    }
+}

+ 95 - 0
app/Http/Controllers/Admin/MessageController.php

@@ -0,0 +1,95 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\MessageService;
+
+/**
+ * 消息管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Http\Controllers
+ */
+class MessageController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new MessageService();
+    }
+
+    public function index()
+    {
+        $pageSize = request()->get('limit', 10);
+        $list = $this->service->getDataList(request()->all(), $pageSize);
+        $message = array(
+            "msg" => '操作成功',
+            "code" => 0,
+            "data" => isset($list['list'])? $list['list']:[],
+            "count" => isset($list['total'])? $list['total']:0,
+        );
+        return $message;
+    }
+
+    /**
+     * 历史记录
+     * @return array
+     * @throws \Psr\Container\ContainerExceptionInterface
+     * @throws \Psr\Container\NotFoundExceptionInterface
+     */
+    public function history()
+    {
+        $pageSize = request()->get('limit', 10);
+        $list = $this->service->getDataList(request()->all(), $pageSize);
+        $message = array(
+            "msg" => '操作成功',
+            "code" => 0,
+            "data" => isset($list['list'])? $list['list']:[],
+            "count" => isset($list['total'])? $list['total']:0,
+            "unread" => isset($list['unread'])? $list['unread']:0,
+        );
+        return $message;
+    }
+
+    /**
+     * 聊天列表
+     * @return array
+     * @throws \Psr\Container\ContainerExceptionInterface
+     * @throws \Psr\Container\NotFoundExceptionInterface
+     */
+    public function chatList()
+    {
+        $pageSize = request()->get('limit', 10);
+        $list = $this->service->getChatList(request()->all(), $pageSize);
+        $message = array(
+            "msg" => '操作成功',
+            "code" => 0,
+            "data" => isset($list['list'])? $list['list']:[],
+            "count" => isset($list['total'])? $list['total']:0,
+        );
+        return $message;
+    }
+
+    /**
+     * 选项列表
+     * @return mixed
+     */
+    public function options(){
+        $result = $this->service->options();
+        return message(1002,true, $result);
+    }
+}

+ 49 - 0
app/Http/Controllers/Admin/NoticeController.php

@@ -0,0 +1,49 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\NoticeService;
+
+/**
+ * 通知公告-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class NoticeController
+ * @package App\Http\Controllers
+ */
+class NoticeController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * NoticeController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new NoticeService();
+    }
+
+    /**
+     * 设置置顶
+     * @return mixed
+     * @since 2020/11/21
+     * @author laravel开发员
+     */
+    public function setIsTop()
+    {
+        $result = $this->service->setIsTop();
+        return $result;
+    }
+
+}

+ 110 - 0
app/Http/Controllers/Admin/OrderController.php

@@ -0,0 +1,110 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Http\Validator\OrderValidator;
+use App\Services\Common\OrderService;
+
+/**
+ * 订单管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class OrderController
+ * @package App\Http\Controllers
+ */
+class OrderController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * OrderController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new OrderService();
+    }
+
+    public function index()
+    {
+        $params = request()->all();
+        $pageSize = isset($params['pageSize'])? $params['pageSize'] : 10;
+        $list = OrderService::make()->getDataList($params, $pageSize);
+        $message = array(
+            "msg" => '操作成功',
+            "code" => 0,
+            "data" => isset($list['list'])? $list['list']:[],
+            "count" => isset($list['total'])? $list['total']:0,
+        );
+        return $message;
+    }
+
+    /**
+     * 审核订单
+     * @return array
+     */
+    public function confirm(OrderValidator $validator)
+    {
+        $params = request()->post();
+        $params = $validator->check($params, 'confirm');
+        if (!is_array($params)) {
+            return message($params, false);
+        }
+
+        if(OrderService::make()->confirm($this->userId, $params)){
+            return message(OrderService::make()->getError(), true);
+        }else{
+            return message(OrderService::make()->getError(), false);
+        }
+    }
+
+
+    /**
+     * 取消订单
+     * @return array
+     */
+    public function cancel(OrderValidator $validator)
+    {
+        $params = request()->post();
+        $params = $validator->check($params, 'cancel');
+        if (!is_array($params)) {
+            return message($params, false);
+        }
+
+        if(OrderService::make()->cancel($this->userId, $params)){
+            return message(OrderService::make()->getError(), true);
+        }else{
+            return message(OrderService::make()->getError(), false);
+        }
+    }
+
+    /**
+     * 完成订单
+     * @return array
+     */
+    public function complete(OrderValidator $validator)
+    {
+        $params = request()->post();
+        $params = $validator->check($params, 'complete');
+        if (!is_array($params)) {
+            return message($params, false);
+        }
+
+        if(OrderService::make()->complete($this->userId, $params)){
+            return message(OrderService::make()->getError(), true);
+        }else{
+            return message(OrderService::make()->getError(), false);
+        }
+    }
+
+}

+ 72 - 0
app/Http/Controllers/Admin/RoleController.php

@@ -0,0 +1,72 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\RoleService;
+
+/**
+ * 角色管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class RoleController
+ * @package App\Http\Controllers
+ */
+class RoleController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * RoleController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new RoleService();
+    }
+
+    /**
+     * 获取角色列表
+     * @return mixed
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function getRoleList()
+    {
+        $result = $this->service->getRoleList();
+        return $result;
+    }
+
+    /**
+     * 获取角色权限列表
+     * @author laravel开发员
+     * @since 2020/11/11
+     */
+    public function getPermissionList()
+    {
+        $result = $this->service->getPermissionList();
+        return $result;
+    }
+
+    /**
+     * 保存权限
+     * @return mixed
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function savePermission()
+    {
+        $result = $this->service->savePermission();
+        return $result;
+    }
+
+}

+ 109 - 0
app/Http/Controllers/Admin/UploadController.php

@@ -0,0 +1,109 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use Illuminate\Http\Request;
+
+/**
+ * 上传文件-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class UploadController
+ * @package App\Http\Controllers
+ */
+class UploadController extends Backend
+{
+
+    /**
+     * 上传图片
+     * @param Request $request 网络请求
+     * @return array
+     * @author laravel开发员
+     * @since 2020/11/11
+     */
+    public function uploadImage(Request $request)
+    {
+        // 上传单图统一调取方法
+        $result = upload_image($request, 'file');
+        if (!$result['success']) {
+            return message($result['message'], false);
+        }
+
+        // 文件路径
+        $file_path = $result['data']['img_path'];
+        if (!$file_path) {
+            return message("文件上传失败", false);
+        }
+
+        // 网络域名拼接
+        if ($file_path && strpos($file_path, IMG_URL) === false) {
+            $file_path = get_image_url($file_path, false);
+        }
+
+        // 返回结果
+        return message(MESSAGE_OK, true, ['url'=> $file_path, 'path'=> $result['data']['img_path']]);
+    }
+
+    /**
+     * 上传文件(单个上传)
+     * @param Request $request
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function uploadFile(Request $request)
+    {
+        $result = upload_file($request);
+        if (!$result['success']) {
+            return message(MESSAGE_FAILED, false, $result['message']);
+        }
+        // 文件路径
+        $file_path = $result['data']['file_path'];
+        if (!$file_path) {
+            return message("文件上传失败");
+        }
+
+        // 网络域名拼接
+        if ($file_path && strpos($file_path, IMG_URL) === false) {
+            $file_path = get_image_url($file_path, false);
+        }
+
+        // 返回结果
+        return message(MESSAGE_OK, true, ['url'=> $file_path, 'path'=> $result['data']['file_path']]);
+    }
+
+    /**
+     * 图片上传
+     * @return array
+     */
+    public function uploadBase64()
+    {
+        $base64 = request()->post('base64','');
+        $uuid = request()->post('uuid', '');
+        if ($base64) {
+            $fileDir =  ATTACHMENT_PATH . '/images/base64/' . date('Ymd');
+
+            // 检测文件路径是否存在,不存在则创建
+            if (!file_exists($fileDir)) {
+                mkdir($fileDir, 0777, true);
+            }
+            $fileName = 'image_'.md5($uuid? $uuid : $base64) . '.jpeg';
+            $base64 = str_replace('data:image/jpeg;base64,','',$base64);
+            file_put_contents($fileDir.'/'.$fileName, base64_decode($base64));
+            if(file_exists($fileDir.'/'.$fileName)){
+                $filePath = str_replace(ATTACHMENT_PATH, '', $fileDir) . '/' . $fileName;
+                return message(MESSAGE_OK, true, ['url'=>get_image_url($filePath, false),'path'=>$filePath]);
+            }
+        }
+
+        return message(MESSAGE_FAILED, false);
+    }
+}

+ 49 - 0
app/Http/Controllers/Admin/UserController.php

@@ -0,0 +1,49 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\UserService;
+
+/**
+ * 用户管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class UserController
+ * @package App\Http\Controllers
+ */
+class UserController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     * UserController constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new UserService();
+    }
+
+    /**
+     * 重置密码
+     * @return mixed
+     * @since 2020/11/11
+     * @author laravel开发员
+     */
+    public function resetPwd()
+    {
+        $result = $this->service->resetPwd();
+        return $result;
+    }
+
+}

+ 80 - 0
app/Http/Controllers/Admin/WithdrawController.php

@@ -0,0 +1,80 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Admin;
+
+use App\Services\Common\BalanceLogService;
+
+/**
+ * 提现管理-控制器
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Http\Controllers
+ */
+class WithdrawController extends Backend
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/11
+     */
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = new  BalanceLogService();
+    }
+
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function index()
+    {
+        $pageSize = request()->get('limit', 10);
+        $list = $this->service->getDataList(request()->all(), $pageSize);
+        $message = array(
+            "msg" => '操作成功',
+            "code" => 0,
+            "data" => isset($list['list'])? $list['list']:[],
+            "counts" => isset($list['counts'])? $list['counts']:[],
+            "count" => isset($list['total'])? $list['total']:0,
+        );
+        return $message;
+    }
+
+
+    /**
+     * 审核
+     * @return mixed
+     */
+    public function confirm(){
+        $params = request()->post();
+        if(BalanceLogService::make()->confirm($this->userId,$params)){
+            return message(BalanceLogService::make()->getError(), true);
+        }else{
+            return message(BalanceLogService::make()->getError(), false);
+        }
+    }
+
+    /**
+     * 更新打款状态
+     * @return mixed
+     */
+    public function payment(){
+        $params = request()->post();
+        if(BalanceLogService::make()->payment($this->userId,$params)){
+            return message(BalanceLogService::make()->getError(), true);
+        }else{
+            return message(BalanceLogService::make()->getError(), false);
+        }
+    }
+}

+ 81 - 0
app/Http/Controllers/Api/UploadController.php

@@ -0,0 +1,81 @@
+<?php
+// +----------------------------------------------------------------------
+// | Laravel框架 [ Laravel ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 Laravel研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: wesmiler <12345678@qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Api;
+
+use Illuminate\Http\Request;
+
+/**
+ * 上传文件-控制器
+ * @since 2020/11/11
+ * Class UploadController
+ * @package App\Http\Controllers
+ */
+class UploadController extends webApp
+{
+
+    /**
+     * 上传图片
+     * @param Request $request 网络请求
+     * @return array
+     * @since 2020/11/11
+     */
+    public function uploadImage(Request $request)
+    {
+
+        // 上传单图统一调取方法
+        $result = upload_image($request, 'file', '',$this->userId);
+        if (!$result['success']) {
+            return showJson($result['msg'], false, '');
+        }
+
+        // 文件路径
+        $file_path = $result['data']['img_path'];
+        if (!$file_path) {
+            return showJson('文件上传失败', false, '');
+        }
+
+        // 网络域名拼接
+        if ($file_path && strpos($file_path, IMG_URL) === false) {
+            $file_path = get_image_url($file_path, false);
+        }
+
+        // 返回结果
+        return showJson(MESSAGE_OK, true, ['url'=> $file_path, 'path'=> $result['data']['img_path']]);
+    }
+
+    /**
+     * 上传文件(单个上传)
+     * @param Request $request
+     * @since 2020/11/11
+     */
+    public function uploadFile(Request $request)
+    {
+        $result = upload_file($request,'file','', $this->userId);
+        if (!$result['success']) {
+            return showJson($result['msg'], false, '');
+        }
+        // 文件路径
+        $file_path = isset($result['data']['file_path'])? $result['data']['file_path'] : '';
+        if (!$file_path) {
+            return showJson("文件上传失败",false);
+        }
+
+        // 网络域名拼接
+        if (strpos($file_path, IMG_URL) === false) {
+            $file_path = get_image_url($file_path, false);
+        }
+
+        // 返回结果
+        return showJson(MESSAGE_OK, true, ['url'=> $file_path, 'path'=> $result['data']['img_path']]);
+    }
+
+}

+ 60 - 0
app/Http/Controllers/Api/v1/AccountController.php

@@ -0,0 +1,60 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Services\Api\AccountService;
+use App\Services\Api\BalanceLogService;
+
+/**
+ * 账单明细
+ * Class AccountController
+ * @package App\Http\Controllers\Api
+ */
+class AccountController extends webApp
+{
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function index()
+    {
+        $params =request()->post();
+        $pageSize = request()->post('pageSize', 15);
+        $params['user_id'] = isset($params['user_id'])? $params['user_id'] : $this->userId;
+        $datas = AccountService::make()->getDataList($params, $pageSize);
+        if($datas){
+            return message(1010, true, $datas);
+        }else{
+            return message(1009, false);
+        }
+    }
+
+    /**
+     * 余额明细
+     * @return array
+     */
+    public function balance()
+    {
+        $params =request()->post();
+        $pageSize = request()->post('pageSize', 15);
+        $params['user_id'] = isset($params['user_id'])? $params['user_id'] : $this->userId;
+        $datas = BalanceLogService::make()->getDataList($params, $pageSize);
+        return message(1010, true, $datas);
+    }
+
+    /**
+     * 收入提现
+     * @return array
+     */
+    public function withdraw()
+    {
+        $params = request()->all();
+        if (!$result = BalanceLogService::make()->withdraw($this->userId, $params)) {
+            return showJson(BalanceLogService::make()->getError(), false);
+        } else {
+            return showJson(BalanceLogService::make()->getError(), true, $result);
+        }
+    }
+}

+ 95 - 0
app/Http/Controllers/Api/v1/ArticleController.php

@@ -0,0 +1,95 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Services\Api\ArticleService;
+use App\Services\ConfigService;
+
+/**
+ * 司文章管理
+ * Class ArticleController
+ * @package App\Http\Controllers\Api
+ */
+class ArticleController extends webApp
+{
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function index()
+    {
+        $params =request()->post();
+        $pageSize = request()->post('pageSize', 15);
+        $datas = ArticleService::make()->getDataList($params, $pageSize);
+        return message(1010, true, $datas);
+    }
+
+    /**
+     * 详情
+     */
+    public function info()
+    {
+        $params = request()->all();
+        $id = isset($params['id'])? intval($params['id']) : 0;
+        if(empty($id)){
+            return message(1036, false);
+        }
+
+        if($info = ArticleService::make()->getInfo($id)){
+            return message(1010, true, $info);
+        }else{
+            return message(1009, false);
+        }
+    }
+
+
+    /**
+     * 客服推荐数据
+     */
+    public function customRecommend()
+    {
+        $cateList = ArticleService::make()->getCateList(2);
+        $cateId = isset($cateList[0])? $cateList[0]['id'] : 0;
+        $datas = [
+            'category'=> $cateList,
+            'recommend'=> ArticleService::make()->getCustomRecommend($cateId),
+        ];
+        return message(1010, true, $datas);
+    }
+
+    /**
+     * 客服咨询数据
+     */
+    public function custom()
+    {
+        $type = request()->post('type',0);
+        $keyword = request()->post('keyword','');
+        $num = request()->post('num',6);
+        $datas = ArticleService::make()->getCustomRecommend($type, $num, $keyword, $type==0?true:false);
+        if($datas){
+            return message(1010, true, $datas);
+        }else{
+            return message(1009, false);
+        }
+    }
+
+    /**
+     * 单页数据
+     */
+    public function page()
+    {
+        $params = request()->all();
+        $type = isset($params['type'])? intval($params['type']) : 0;
+        if(empty($type)){
+            return message(1031, false);
+        }
+
+        if($info = ArticleService::make()->getInfoByType($type)){
+            return message(1010, true, $info);
+        }else{
+            return message(1009, false);
+        }
+    }
+}

+ 72 - 0
app/Http/Controllers/Api/v1/DepositController.php

@@ -0,0 +1,72 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Services\Api\DepositService;
+
+/**
+ * 保证金管理
+ * @package App\Http\Controllers\Api
+ */
+class DepositController extends webApp
+{
+
+    /**
+     * 记录
+     */
+    public function index()
+    {
+        $params =request()->post();
+        $pageSize = request()->post('pageSize', 15);
+        $params['user_id'] = isset($params['user_id'])? $params['user_id'] : $this->userId;
+        if($info = DepositService::make()->getDataList($params,$pageSize)){
+            return message(DepositService::make()->getError(), true, $info);
+        }else{
+            return message(DepositService::make()->getError(), false);
+        }
+    }
+
+    /**
+     * 充值
+     */
+    public function pay()
+    {
+        $params = request()->all();
+        if($info = DepositService::make()->pay($this->userId, $params)){
+            return message(DepositService::make()->getError(), true, $info);
+        }else{
+            return message(DepositService::make()->getError(), false);
+        }
+    }
+
+    /**
+     * 退保
+     */
+    public function refund()
+    {
+        $params = request()->all();
+        if($info = DepositService::make()->refund($this->userId, $params)){
+            return message(DepositService::make()->getError(), true, $info);
+        }else{
+            return message(DepositService::make()->getError(), false);
+        }
+    }
+
+    /**
+     * 详情
+     */
+    public function info()
+    {
+        $id = request()->post('id',0);
+        if($id<=0){
+            return message(1036, false);
+        }
+        $info = DepositService::make()->getInfo($id);
+        if($info){
+            return message(1010, true, $info);
+        }else{
+            return message(1009, false);
+        }
+    }
+}

+ 67 - 0
app/Http/Controllers/Api/v1/GoodsController.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Services\Api\GoodsService;
+use App\Services\Api\MemberService;
+
+/**
+ * 商品管理
+ * @package App\Http\Controllers\Api
+ */
+class GoodsController extends webApp
+{
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function index()
+    {
+        $params =request()->post();
+        $pageSize = request()->post('pageSize', 12);
+        $params['picker_status'] = 1;
+        $params['user_id'] = $this->userId;
+        $userInfo = MemberService::make()->getInfo($this->userId,[], true);
+        $confirmStatus = isset($userInfo['confirm_status'])? $userInfo['confirm_status'] : 0;
+        $pickerStatus = isset($userInfo['picker_status'])? $userInfo['picker_status'] : 0;
+        if($confirmStatus != 1){
+            return message(2043, false,[],405);
+        }
+
+        if($pickerStatus!= 1){
+            return message(2063, false,[],406);
+        }
+        $datas = GoodsService::make()->getDataList($params, $pageSize);
+        return message(1010, true, $datas);
+    }
+
+    /**
+     * 详情
+     */
+    public function info()
+    {
+        $params = request()->all();
+        $id = isset($params['id'])? intval($params['id']) : 0;
+        if(empty($id)){
+            return message(1036, false);
+        }
+
+        $userInfo = MemberService::make()->getInfo($this->userId,[], true);
+        $confirmStatus = isset($userInfo['confirm_status'])? $userInfo['confirm_status'] : 0;
+        $pickerStatus = isset($userInfo['picker_status'])? $userInfo['picker_status'] : 0;
+        if($confirmStatus != 1){
+            return message(2043, false,[],405);
+        }
+
+        if($pickerStatus!= 1){
+            return message(2063, false,[],406);
+        }
+        if($info = GoodsService::make()->getInfo($id)){
+            return message(1010, true, $info);
+        }else{
+            return message(1009, false);
+        }
+    }
+}

+ 110 - 0
app/Http/Controllers/Api/v1/IndexController.php

@@ -0,0 +1,110 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Services\Api\AccountService;
+use App\Services\Api\MemberService;
+use App\Services\Api\OrderService;
+use App\Services\Common\NoticeService;
+use App\Services\ConfigService;
+use App\Services\RedisService;
+
+/**
+ * 首页
+ * Class IndexController
+ * @package App\Http\Controllers\Api
+ */
+class IndexController extends webApp
+{
+
+    /**
+     * 配置信息
+     * @return array
+     */
+    public function config()
+    {
+        try {
+            $appSources = request()->post('app_sources', 'ios');
+            $cacheKey = "caches:config:app_{$appSources}";
+            $config = RedisService::get($cacheKey);
+            if (empty($config)) {
+                $depositConfig = ConfigService::make()->getConfigByGroup(5);
+                $config = [
+                    'app_name' => ConfigService::make()->getConfigByCode('app_name'),
+                    'app_logo' => get_image_url(ConfigService::make()->getConfigByCode('app_logo')),
+                    'app_version' => ConfigService::make()->getConfigByCode('app_version'),
+                    'app_android_url' => ConfigService::make()->getConfigByCode('app_android_url'),
+                    'deposit_money' => isset($depositConfig['deposit_money']['value'])? floatval($depositConfig['deposit_money']['value']) : 0,
+                    'deposit_desc' => isset($depositConfig['deposit_desc']['value'])? format_content($depositConfig['deposit_desc']['value']) : '',
+                    'deposit_refund_desc' => isset($depositConfig['deposit_refund_desc']['value'])? format_content($depositConfig['deposit_refund_desc']['value']) : '',
+                    'alipay_open' => ConfigService::make()->getConfigByCode('alipay_open', 1),
+                    'wxpay_open' => ConfigService::make()->getConfigByCode('wxpay_open', 1),
+                    'withdraw_open' => ConfigService::make()->getConfigByCode('withdraw_open', 1),
+                    'withdraw_min' => ConfigService::make()->getConfigByCode('withdraw_min', 0),
+                    'withdraw_fee' => ConfigService::make()->getConfigByCode('withdraw_fee', 0),
+                    'imchat_url' => ConfigService::make()->getConfigByCode('imchat_url', ''),
+                    'img_compress'=> ConfigService::make()->getConfigByCode('preview_img_compress', ''),
+                    'notices' => NoticeService::make()->getRecommandList(),
+                ];
+                RedisService::set($cacheKey, $config, 3600);
+            }
+
+            return showJson(1010, true, $config);
+        } catch (\Exception $exception) {
+            RedisService::set("caches:request:error_config", ['trace' => $exception->getTrace()], 7200);
+            return showJson(1018, false, ['error' => env('APP_DEBUG') ? $exception->getMessage() : '']);
+        }
+    }
+
+    /**
+     * 首页数据
+     * @return array
+     */
+    public function data()
+    {
+        $userInfo = MemberService::make()->getInfo($this->userId);
+        $confirmStatus = isset($userInfo['confirm_status'])? $userInfo['confirm_status'] : 0;
+        $pickerStatus = isset($userInfo['picker_status'])? $userInfo['picker_status'] : 0;
+        if($confirmStatus != 1){
+            return message(2043, false,[],405);
+        }
+
+        if($pickerStatus!= 1){
+            return message(2063, false,[],406);
+        }
+
+        $data = [
+            // 首页数据
+            'counts' => [
+                'dayIncome' => AccountService::make()->getTotalByDay($this->userId, 1),
+                'dayOrder' => OrderService::make()->getCountByDay($this->userId, 3),
+            ],
+        ];
+        return showJson(1010, true, $data);
+    }
+
+    /**
+     * 验证更新
+     * @return array
+     */
+    public function versionCheck()
+    {
+        $version = request()->post('version', '');
+        $appSources = request()->post('app_sources', 'ios');
+        $currentVersion = ConfigService::make()->getConfigByCode('app_version');
+        if (getVersion($version) < getVersion($currentVersion)) {
+            $data = [
+                'has_update' => true,
+                'app_version' => $currentVersion,
+                'app_name' => ConfigService::make()->getConfigByCode('app_name'),
+                'app_url' => ConfigService::make()->getConfigByCode("app_{$appSources}_url"),
+                'is_force' => ConfigService::make()->getConfigByCode("app_force_update"),
+                'auto_update' => false, // 是否APP内自动更新
+            ];
+            return showJson(1010, true, $data);
+        } else {
+            return showJson(1010, false, ['has_update' => false, 'version' => $version]);
+        }
+    }
+}

+ 129 - 0
app/Http/Controllers/Api/v1/LoginController.php

@@ -0,0 +1,129 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Http\Validator\MemberValidator;
+use App\Services\Api\MemberService;
+use App\Services\ConfigService;
+use App\Services\RedisService;
+use App\Services\SmsService;
+use App\Services\WechatService;
+use Illuminate\Http\Request;
+
+/**
+ * 授权登录控制器基类
+ * Class LoginController
+ * @package App\Http\Controllers
+ */
+class LoginController extends webApp
+{
+
+    /**
+     * 账号登录
+     * @return array
+     */
+    public function login(MemberValidator $validator)
+    {
+        $params = request()->all();
+        $params = $validator->check($params, 'login');
+        if (!is_array($params)) {
+            return showJson($params, false);
+        }
+
+        if(!$result = MemberService::make()->login($params)){
+            return showJson(MemberService::make()->getError(), false);
+        }
+
+        return showJson(MemberService::make()->getError(), true, $result);
+    }
+
+    /**
+     * 账号注册
+     * @return array
+     */
+    public function register(MemberValidator $validator)
+    {
+        $params = request()->all();
+        $params = $validator->check($params, 'register');
+        if (!is_array($params)) {
+            return showJson($params, false);
+        }
+
+        if(!$result = MemberService::make()->register($params)){
+            return showJson(MemberService::make()->getError(), false);
+        }
+
+        return showJson(MemberService::make()->getError(), true, $result);
+    }
+
+    /**
+     * 重置密码
+     * @param MemberValidator $validator
+     * @return array
+     */
+    public function forget(MemberValidator $validator)
+    {
+        $params = request()->all();
+        $params = $validator->check($params, 'reset_password');
+        if (!is_array($params)) {
+            return showJson($params, false);
+        }
+
+        if(!MemberService::make()->forget($params)){
+            $error = MemberService::make()->getError();
+            return showJson($error,false,'',$error==1040?405:0);
+        }else{
+            return showJson(MemberService::make()->getError(),true);
+        }
+    }
+
+    /**
+     * 发送短信验证码
+     * @return array
+     */
+    public function smsSend(MemberValidator $validator)
+    {
+        $params = request()->all();
+        $params = $validator->check($params, 'sms');
+        if (!is_array($params)) {
+            return showJson($params, false);
+        }
+
+        // 发送验证码处理
+        $mobile = isset($params['mobile']) ? $params['mobile'] : '';
+        $scene = isset($params['scene']) ? $params['scene'] : '';
+        switch ($scene) {
+            case 'register':
+                if (MemberService::make()->checkExists('mobile', $mobile)) {
+                    return showJson(1040, false);
+                }
+                break;
+            case 'deposit': // 退保
+            case 'reset_password': // 忘记密码
+            case 'login':
+                if (!MemberService::make()->checkExists('mobile',$mobile)) {
+                    return showJson(2001, false);
+                }
+                break;
+        }
+
+        if (!SmsService::make()->send($mobile, $scene)) {
+            return showJson(SmsService::make()->getError(), false);
+        }
+
+        return showJson(1011, true);
+    }
+
+    /**
+     * 退出登录
+     * @return array
+     */
+    public function logout()
+    {
+        RedisService::clear("auths:info:".$this->userId);
+        return showJson(1003, true);
+    }
+
+
+}

+ 133 - 0
app/Http/Controllers/Api/v1/MemberController.php

@@ -0,0 +1,133 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Services\Api\MemberService;
+use App\Services\RedisService;
+use Illuminate\Http\Request;
+
+/**
+ * 会员管理
+ * Class MemberController
+ * @package App\Http\Controllers\Api
+ */
+class MemberController extends webApp
+{
+    /**
+     * 信息
+     * @return array
+     */
+    public function info()
+    {
+        $userId = request()->post('user_id', 0);
+        $info = MemberService::make()->getInfo($userId ? $userId : $this->userId);
+        if ($info) {
+            return showJson(1010, true, $info);
+        } else {
+            return showJson(1004, false, [], '403');
+        }
+    }
+
+    /**
+     * 注册资料
+     * @return array
+     */
+    public function profile()
+    {
+        $userId = request()->post('user_id', 0);
+        $field = ['id', 'user_type', 'realname', 'mobile', 'nickname','balance','deposit','car_type','car_number','driving_license','confirm_at','confirm_remark','confirm_status','drivers_license','create_time', 'code', 'openid', 'status', 'avatar'];
+        $info = MemberService::make()->getInfo($userId ? $userId : $this->userId, $field);
+        if ($info) {
+            return showJson(1010, true, $info);
+        } else {
+            return showJson(1004, false, [], '403');
+        }
+    }
+
+    /**
+     * 注册资料重新提交
+     * @return array
+     */
+    public function profileModify()
+    {
+        $params = request()->all();
+        if (!MemberService::make()->profileModify($this->userId, $params)) {
+            return showJson(MemberService::make()->getError(), false);
+        } else {
+            return showJson(1013, true);
+        }
+    }
+
+    /**
+     * 用户账号列表
+     * @return array
+     */
+    public function index()
+    {
+        $params =request()->post();
+        $pageSize = request()->post('pageSize', 12);
+        $datas = MemberService::make()->getDataList($params, $pageSize);
+        return message(1010, true, $datas);
+    }
+
+    /**
+     * 更新修改头像
+     * @return array
+     */
+    public function setAvatar(Request $request)
+    {
+        // 上传单图统一调取方法
+        ob_clean();
+        $result = upload_image($request, 'file', 'avatar');
+        if (!$result['success']) {
+            return showJson($result['msg'], false, ['url' => '']);
+        }
+
+        // 文件路径
+        $file_path = $result['data']['img_path'];
+        if (!$file_path) {
+            return showJson('上传失败', false, ['url' => '']);
+        }
+
+        // 网络域名拼接
+        if ($file_path && strpos($file_path, IMG_URL) === false) {
+            $file_path = get_image_url($file_path);
+        }
+
+        $avatar = $result['data']['img_path'];
+        if (MemberService::make()->saveAvatar($this->userId, $avatar)) {
+            return showJson(1013, true, ['url' => $file_path, 'path' => $avatar]);
+        } else {
+            return showJson(1014, false, ['url' => '']);
+        }
+    }
+
+    /**
+     * 修改账号信息
+     * @return array
+     */
+    public function modify()
+    {
+        $params = request()->all();
+        if (!MemberService::make()->modify($this->userId, $params)) {
+            return showJson(MemberService::make()->getError(), false);
+        } else {
+            return showJson(1013, true);
+        }
+    }
+
+    /**
+     * 注销账号
+     * @return array
+     */
+    public function logOff()
+    {
+        if (!MemberService::make()->logOff($this->userId)) {
+            return showJson(MemberService::make()->getError(), false);
+        } else {
+            return showJson(MemberService::make()->getError(), true);
+        }
+    }
+
+}

+ 39 - 0
app/Http/Controllers/Api/v1/MessageController.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Services\Api\MessageService;
+
+/**
+ * 消息管理
+ * Class MessageController
+ * @package App\Http\Controllers\Api
+ */
+class MessageController extends webApp
+{
+    /**
+     * 消息记录
+     * @return array
+     */
+    public function index()
+    {
+        $params = request()->post();
+        $pageSize = request()->post('pageSize', 20);
+        $datas = MessageService::make()->getDataList($params,$pageSize);
+        return message(1010, true, $datas);
+    }
+
+    /**
+     * 站内推送消息历史
+     * @return array|mixed
+     */
+    public function history()
+    {
+        $params = request()->post();
+        $pageSize = request()->post('pageSize', 20);
+        $params['user_id'] = $this->userId;
+        $datas = MessageService::make()->getDataList($params, $pageSize);
+        return message(1010, true, $datas);
+    }
+}

+ 112 - 0
app/Http/Controllers/Api/v1/NotifyController.php

@@ -0,0 +1,112 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Services\PaymentService;
+use App\Services\RedisService;
+
+/**
+ * 回调处理
+ * Class NotifyController
+ * @package App\Http\Controllers\Api
+ */
+class NotifyController extends webApp
+{
+
+    /**
+     * 支付回调
+     * @param string $scene 场景,deposit-保证金,depositRefund-保证金退款,withdraw-收入提现
+     * @param int $payType 支付方式:10-微信,20-支付宝
+     * @return array|false|\Psr\Http\Message\ResponseInterface
+     */
+    public function callback($scene, $payType = 10)
+    {
+        $date = date('Y-m-d H:i:s');
+        $result = request()->post();
+        $key = date('YmdHis') . '_' . rand(1000, 9999);
+        $channel = $payType == 10? 'wechat':'alipay';
+        if (empty($result)) {
+            $result = file_get_contents('php://input');
+            $result = $result ? json_decode($result, true) : [];
+        }
+
+        try {
+            RedisService::set("caches:payments:notify_{$scene}:result_".date('YmdHis').rand(10,99), ['all' => request()->all(), 'scene' => $scene, 'payType' => $payType, 'result' => $result], 7200);
+            $pay = PaymentService::make()->createPay($scene, $payType);
+            if (empty($pay) || empty($scene) || empty($payType)) {
+                if (env('APP_DEBUG')) {
+                    logger()->channel($channel)->error("【{$date} 支付回调】参数错误:" . json_encode(['scene' => $scene, 'payType' => $payType, 'data' => $result], 256));
+                }
+
+                RedisService::set("caches:payments:notify_{$scene}:error_" . $key, ['all' => request()->all(), 'scene' => $scene, 'payType' => $payType, 'result' => $result], 7200);
+                return false;
+            }
+
+            // 验签和重组参数
+            $data = $pay->callback();
+            RedisService::set("caches:payments:notify_{$scene}:data_" . $key, ['all' => request()->all(), 'scene' => $scene,'data'=>$data, 'payType' => $payType, 'result' => $result], 7200);
+            if (env('APP_DEBUG')) {
+                logger()->channel($channel)->info("【{$date} 支付回调】验证结果:" . json_encode(['data' => $data,'scene'=>$scene,'payType'=>$payType],256));
+            }
+
+            // 回调处理
+            if (PaymentService::make()->catchNotify($scene, $payType, $data)) {
+                RedisService::set("caches:payments:notify_{$scene}:success_" . $key, ['all' => request()->all(), 'scene' => $scene,'data'=>$data, 'payType' => $payType, 'result' => $result], 7200);
+                logger()->channel('alipay')->info("【{$date} 支付回调】回调成功:" . json_encode(['data' => $data,'scene'=>$scene,'payType'=>$payType],256));
+                return response('success');
+            } else {
+                $msg = PaymentService::make()->getError();
+                logger()->channel($channel)->info("【{$date} 支付回调】回调失败:" . json_encode(['data' => $data,'scene'=>$scene,'payType'=>$payType, 'error' => lang($msg)], 256));
+                return message($msg ? $msg : 2635, false);
+            }
+        } catch (\Exception $exception) {
+            RedisService::set("caches:payments:notify_{$scene}:error_" . $key, ['all' => request()->all(), 'scene' => $scene,'payType' => $payType,'error' => $exception->getMessage(), 'data' => $result], 7200);
+            logger()->channel($channel)->error("【{$date} 支付回调】回调错误:" . json_encode(['data' => $result,'scene'=>$scene,'payType'=>$payType, 'error' => $exception->getMessage()], 256));
+            return message(2635, false, ['error' => $exception->getMessage()]);
+        }
+    }
+
+
+    /**
+     * 退款回调
+     * @param string $scene 场景,deposit-保证金,depositRefund-保证金退款,withdraw-收入提现
+     * @param int $payType 支付方式:10-微信,20-支付宝
+     * @return array|false
+     * @throws \Yansongda\Pay\Exception\ContainerException
+     * @throws \Yansongda\Pay\Exception\InvalidParamsException
+     */
+    public function depositRefund($payType = 10)
+    {
+        $scene = 'depositRefund';
+        $date = date('Y-m-d H:i:s');
+        $result = request()->post();
+        $pay = PaymentService::make()->createPay('depositRefund', $payType);
+        $channel = $payType == 10? 'wechat':'alipay';
+        if (empty($pay) || empty($scene) || empty($payType)) {
+            if (env('APP_DEBUG')) {
+                logger()->channel($channel)->error("【{$date} 退款回调】验证错误:" . json_encode(['scene' => $scene, 'payType' => $payType, 'data' => $result], 256));
+            }
+
+            RedisService::set("caches:refunds:notify_error_" . date('YmdH'), ['all' => request()->all(), 'scene' => $scene, 'payType' => $payType, 'data' => $result], 7200);
+            return false;
+        }
+
+        // 验签和重组参数
+        $data = $pay->callback();
+        RedisService::set("caches:refunds:notify_data_" . date('YmdH'), ['all' => request()->all(), 'scene' => $scene, 'payType' => $payType, 'data' => $result], 7200);
+        if (env('APP_DEBUG')) {
+            logger()->channel($channel)->info("【{$date} 退款回调】验证结果:" . json_encode($data, 256));
+        }
+
+        // 回调处理
+        if (PaymentService::make()->catchNotify($scene, $payType, $data)) {
+            logger()->channel($channel)->info("【{$date} 退款回调】回调成功:" . json_encode(['data' => $data,'scene'=>$scene,'payType'=>$payType],256));
+            return response('success');
+        } else {
+            $msg = PaymentService::make()->getError();
+            logger()->channel($channel)->info("【{$date} 退款回调】回调失败:" . json_encode(['data' => $data,'scene'=>$scene,'payType'=>$payType, 'error' => lang($msg)], 256));
+            return message($msg ? $msg : 2635, false);
+        }
+    }
+}

+ 102 - 0
app/Http/Controllers/Api/v1/OrderController.php

@@ -0,0 +1,102 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Http\Validator\OrderValidator;
+use App\Services\Api\MemberService;
+use App\Services\Api\OrderService;
+
+/**
+ * 订单
+ * @package App\Http\Controllers\Api
+ */
+class OrderController extends webApp
+{
+
+    /**
+     * 列表
+     * @return array
+     */
+    public function index()
+    {
+        $userInfo = MemberService::make()->getInfo($this->userId);
+        $confirmStatus = isset($userInfo['confirm_status'])? $userInfo['confirm_status'] : 0;
+        $pickerStatus = isset($userInfo['picker_status'])? $userInfo['picker_status'] : 0;
+        if($confirmStatus != 1){
+            return message(2043, false,[],405);
+        }
+
+        if($pickerStatus!= 1){
+            return message(2063, false,[],406);
+        }
+
+        $params =request()->post();
+        $pageSize = request()->post('pageSize', 15);
+        $params['user_id'] = $this->userId;
+        $datas = OrderService::make()->getDataList($params, $pageSize);
+
+        return message(1010, true, $datas);
+    }
+
+    /**
+     * 验证订单状态
+     * @return array
+     */
+    public function check()
+    {
+        if($data = OrderService::make()->checkOrderStatus($this->userId))
+        {
+            return showJson(1010, true,$data);
+        } else {
+            return showJson(1009, false);
+        }
+    }
+
+
+    /**
+     * 详情
+     * @return array|mixed
+     */
+    public function info()
+    {
+        $params = request()->all();
+        $validator = new OrderValidator();
+        $params = $validator->check($params, 'info');
+        if (!is_array($params)) {
+            return showJson($params, false);
+        }
+
+        $id = isset($params['order_id'])? intval($params['order_id']) : 0;
+        if($id<=0){
+            return showJson(1036,false);
+        }
+        $data = OrderService::make()->getOrderInfo($id, $this->userId);
+        if(empty($data)){
+            return showJson(1009, false);
+        }
+        return showJson(1010, true, $data);
+    }
+
+    /**
+     * 下单
+     * @param OrderValidator $validator
+     * @return array
+     */
+    public function submit(OrderValidator $validator)
+    {
+        $params = request()->all();
+        $params = $validator->check($params, 'submit');
+        if (!is_array($params)) {
+            return showJson($params, false);
+        }
+
+        if (!$result = OrderService::make()->createOrder($this->userId, $params)) {
+            $error = OrderService::make()->getError();
+            return showJson($error, false,'',$error==2206?'405':-1);
+        } else {
+            return showJson(OrderService::make()->getError(), true, $result);
+        }
+    }
+
+}

+ 23 - 0
app/Http/Controllers/Api/v1/TestController.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace App\Http\Controllers\Api\v1;
+
+use App\Http\Controllers\Api\webApp;
+use App\Services\Api\MessageService;
+use App\Services\MapService;
+use App\Services\RedisService;
+
+/**
+ * 测试
+ * Class TestController
+ * @package App\Http\Controllers\Api
+ */
+class TestController extends webApp
+{
+
+
+    public function check()
+    {
+
+    }
+}

+ 184 - 0
app/Http/Controllers/Api/webApp.php

@@ -0,0 +1,184 @@
+<?php
+// +----------------------------------------------------------------------
+// | Laravel框架 [ Laravel ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 Laravel研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: wesmiler <12345678@qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers\Api;
+
+use App\Helpers\Jwt;
+use App\Http\Controllers\BaseController;
+use App\Models\MemberModel;
+use App\Services\ConfigService;
+use App\Services\RedisService;
+use Illuminate\Support\Facades\DB;
+
+/**
+ * 控制器基类
+ * @since 2020/11/10
+ * Class BaseController
+ * @package App\Http\Controllers
+ */
+class webApp extends BaseController
+{
+    // 模型
+    protected $model;
+    // 服务
+    protected $service;
+    // 校验
+    protected $validate;
+    // 登录ID
+    protected $userId = 0;
+
+    // 用户类型
+    protected $userType = 1;
+
+    // 仓库ID
+    protected $stockId = 1;
+
+    // 登录信息
+    protected $userInfo = [];
+
+    /**
+     * 构造函数
+     * @author wesmiler
+     * @since 2020/11/10
+     * Backend constructor.
+     */
+    public function __construct()
+    {
+        parent::__construct();
+
+        // 初始化分页参数
+        $this->initConfig();
+
+        // 登录检测中间件
+//        $this->middleware('web.login');
+
+
+        // 初始化登录信息
+        $this->middleware(function ($request, $next) {
+            // 授权用户数据
+            $userId = $request->headers->get('token_uid');
+            $userId = $userId? $userId : 0;
+            // 登录验证
+            $userInfo = RedisService::get("auths:info:{$userId}");
+            if(empty($userInfo) && $userId){
+                $this->initLogin($userId);
+            }else{
+                $this->userId = $userId;
+                $this->stockId = isset($userInfo['stock_id'])? $userInfo['stock_id'] : 0;
+                $this->userType = isset($userInfo['user_type']) && $userInfo['user_type']? $userInfo['user_type'] : 1;
+                $this->userInfo = $userInfo;
+            }
+
+            return $next($request);
+        });
+    }
+
+    /**
+     * 初始化配置
+     * @author laravel开发员
+     * @since 2020/11/10
+     */
+    public function initConfig()
+    {
+        // 请求参数
+        $this->param = \request()->input();
+
+        // 分页基础默认值
+        defined('PERPAGE') or define('PERPAGE', isset($this->param['limit']) ? $this->param['limit'] : 20);
+        defined('PAGE') or define('PAGE', isset($this->param['page']) ? $this->param['page'] : 1);
+    }
+
+    /**
+     * 登录验证
+     * @param $userId 用户ID
+     * @return
+     * @author wesmiler
+     * @since 2020/8/31
+     */
+    public function initLogin($userId)
+    {
+        // 登录用户ID
+        $this->userId = $userId;
+
+        // 登录用户信息
+        if ($userId) {
+            $memberModel = new MemberModel();
+            $userInfo = $memberModel->getInfo($this->userId);
+            $this->userInfo = $userInfo;
+            $this->stockId = isset($userInfo['stock_id'])? $userInfo['stock_id'] : 0;
+            $this->userType = isset($userInfo['user_type']) && $userInfo['user_type']? $userInfo['user_type'] : 1;
+            RedisService::set("auths:info:{$userId}", $this->userInfo, 7*24*3600);
+        }
+
+    }
+
+
+    /**
+     * 获取数据列表
+     * @return mixed
+     * @since 2020/11/11
+     * @author wesmiler
+     */
+    public function index()
+    {
+        $result = $this->service->getList();
+        return $result;
+    }
+
+    /**
+     * 获取数据详情
+     * @return mixed
+     * @since 2020/11/11
+     * @author wesmiler
+     */
+    public function info()
+    {
+        $result = $this->service->info();
+        return $result;
+    }
+
+    /**
+     * 添加或编辑
+     * @return mixed
+     * @since 2020/11/11
+     * @author wesmiler
+     */
+    public function edit()
+    {
+        $result = $this->service->edit();
+        return $result;
+    }
+
+    /**
+     * 删除数据
+     * @return mixed
+     * @since 2020/11/11
+     * @author wesmiler
+     */
+    public function delete()
+    {
+        $result = $this->service->delete();
+        return $result;
+    }
+
+    /**
+     * 设置状态
+     * @return mixed
+     * @since 2020/11/21
+     * @author wesmiler
+     */
+    public function status()
+    {
+        $result = $this->service->status();
+        return $result;
+    }
+
+}

+ 97 - 0
app/Http/Controllers/BaseController.php

@@ -0,0 +1,97 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Controllers;
+use Illuminate\Support\Facades\DB;
+
+/**
+ * 控制器基类
+ */
+class BaseController extends \Illuminate\Routing\Controller
+{
+    /**
+     * 构造函数
+     * @author laravel开发员
+     * @since 2020/11/10
+     * BaseController constructor.
+     */
+    public function __construct()
+    {
+        // 初始化网络请求配置
+        $this->initRequestConfig();
+
+        // 初始化系统常量
+        $this->initSystemConst();
+    }
+
+    /**
+     * 初始化请求配置
+     * @since 2020/11/10
+     * @author laravel开发员
+     */
+    private function initRequestConfig()
+    {
+        // 定义是否GET请求
+        defined('IS_GET') or define('IS_GET', \request()->isMethod('GET'));
+
+        // 定义是否POST请求
+        defined('IS_POST') or define('IS_POST', \request()->isMethod('POST'));
+
+        // 定义是否AJAX请求
+        defined('IS_AJAX') or define('IS_AJAX', \request()->ajax());
+
+        // 定义是否PAJAX请求
+        defined('IS_PJAX') or define('IS_PJAX', \request()->pjax());
+
+        // 定义是否PUT请求
+        defined('IS_PUT') or define('IS_PUT', \request()->isMethod('PUT'));
+
+        // 定义是否DELETE请求
+        defined('IS_DELETE') or define('IS_DELETE', \request()->isMethod('DELETE'));
+
+        // 请求方式
+        defined('REQUEST_METHOD') or define('REQUEST_METHOD', \request()->method());
+    }
+
+    /**
+     * 初始化系统常量
+     * @author laravel开发员
+     * @since 2020/11/10
+     */
+    private function initSystemConst()
+    {
+        // 项目根目录
+        defined('ROOT_PATH') or define('ROOT_PATH', base_path());
+
+        // 文件上传目录
+        defined('ATTACHMENT_PATH') or define('ATTACHMENT_PATH', base_path('public/uploads'));
+
+        // 图片上传目录
+        defined('IMG_PATH') or define('IMG_PATH', base_path('public/uploads/images'));
+
+        // 临时存放目录
+        defined('UPLOAD_TEMP_PATH') or define('UPLOAD_TEMP_PATH', ATTACHMENT_PATH . "/temp");
+
+        // 定义普通图片域名
+        defined('IMG_URL') or define('IMG_URL', env('IMG_URL'));
+
+        // 数据表前缀
+        defined('DB_PREFIX') or define('DB_PREFIX', DB::connection()->getTablePrefix());
+
+        // 系统全称
+        define('SITE_NAME', env('SITE_NAME'));
+        // 系统简称
+        define('NICK_NAME', env('NICK_NAME'));
+        // 系统版本号
+        define('VERSION', env('VERSION'));
+    }
+
+}

+ 74 - 0
app/Http/Kernel.php

@@ -0,0 +1,74 @@
+<?php
+
+namespace App\Http;
+
+use App\Http\Middleware\EnableCrossRequestMiddleware;
+use Illuminate\Foundation\Http\Kernel as HttpKernel;
+
+class Kernel extends HttpKernel
+{
+    /**
+     * The application's global HTTP middleware stack.
+     *
+     * These middleware are run during every request to your application.
+     *
+     * @var array
+     */
+    protected $middleware = [
+        // \App\Http\Middleware\TrustHosts::class,
+        \App\Http\Middleware\TrustProxies::class,
+        \Fruitcake\Cors\HandleCors::class,
+        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
+        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
+        \App\Http\Middleware\TrimStrings::class,
+        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
+        \App\Http\Middleware\EnableCrossRequestMiddleware::class,
+    ];
+
+    /**
+     * The application's route middleware groups.
+     *
+     * @var array
+     */
+    protected $middlewareGroups = [
+        'web' => [
+            \App\Http\Middleware\EncryptCookies::class,
+            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
+            \Illuminate\Session\Middleware\StartSession::class,
+            // \Illuminate\Session\Middleware\AuthenticateSession::class,
+            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
+//            \App\Http\Middleware\VerifyCsrfToken::class,
+            \Illuminate\Routing\Middleware\SubstituteBindings::class,
+        ],
+
+        'api' => [
+            \Illuminate\Routing\Middleware\SubstituteBindings::class,
+            \Illuminate\Session\Middleware\StartSession::class,
+        ],
+    ];
+
+    /**
+     * The application's route middleware.
+     *
+     * These middleware may be assigned to groups or used individually.
+     *
+     * @var array
+     */
+    protected $routeMiddleware = [
+        'auth' => \App\Http\Middleware\Authenticate::class,
+        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
+        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
+        'can' => \Illuminate\Auth\Middleware\Authorize::class,
+        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
+        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
+        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
+        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
+        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
+        // 后台
+        'user.login' => \App\Http\Middleware\UserLogin::class,
+        // app端
+        'web.login' => \App\Http\Middleware\WebLogin::class,
+        // 司机端
+        'driver.login' => \App\Http\Middleware\DriverLogin::class,
+    ];
+}

+ 24 - 0
app/Http/Middleware/ActionLog.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Models\ActionLogModel;
+use Closure;
+
+class ActionLog
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param \Illuminate\Http\Request $request
+     * @param \Closure $next
+     * @return mixed
+     */
+    public function handle($request, Closure $next)
+    {
+        if ($request->isMethod('post')) {
+            ActionLogModel::record();
+        }
+        return $next($request);
+    }
+}

+ 21 - 0
app/Http/Middleware/Authenticate.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Auth\Middleware\Authenticate as Middleware;
+
+class Authenticate extends Middleware
+{
+    /**
+     * Get the path the user should be redirected to when they are not authenticated.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return string|null
+     */
+    protected function redirectTo($request)
+    {
+        if (! $request->expectsJson()) {
+            return route('login');
+        }
+    }
+}

+ 54 - 0
app/Http/Middleware/EnableCrossRequestMiddleware.php

@@ -0,0 +1,54 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Http\Middleware;
+
+use Closure;
+use Illuminate\Http\Request;
+
+/**
+ * 跨域解决方案
+ * @author laravel开发员
+ * @since 2021/1/10
+ * Class EnableCrossRequestMiddleware
+ * @package App\Http\Middleware
+ */
+class EnableCrossRequestMiddleware
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param \Illuminate\Http\Request $request
+     * @param \Closure $next
+     * @return mixed
+     */
+    public function handle(Request $request, Closure $next)
+    {
+        $response = $next($request);
+        $origin = $request->server('HTTP_ORIGIN') ? $request->server('HTTP_ORIGIN') : '';
+        $allow_origin = [];
+        if (empty($allow_origin) || in_array($origin, $allow_origin)) {
+            //允许所有资源跨域
+            $response->header('Access-Control-Allow-Origin', $origin);
+            // 允许通过的响应报头
+            $response->header('Access-Control-Allow-Headers', 'Origin, Content-Type, Cookie, X-CSRF-TOKEN, Accept, Authorization, X-XSRF-TOKEN');
+            // 允许axios获取响应头中的Authorization
+            $response->header('Access-Control-Expose-Headers', 'Authorization, authenticated');
+            // 允许的请求方法
+            $response->header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS, DELETE');
+            //允许的请求方法
+            $response->header('Allow', 'GET, POST, PATCH, PUT, OPTIONS, delete');
+            // 运行客户端携带证书式访问
+            $response->header('Access-Control-Allow-Credentials', 'true');
+        }
+        return $response;
+    }
+}

+ 17 - 0
app/Http/Middleware/EncryptCookies.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
+
+class EncryptCookies extends Middleware
+{
+    /**
+     * The names of the cookies that should not be encrypted.
+     *
+     * @var array
+     */
+    protected $except = [
+        //
+    ];
+}

+ 17 - 0
app/Http/Middleware/PreventRequestsDuringMaintenance.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
+
+class PreventRequestsDuringMaintenance extends Middleware
+{
+    /**
+     * The URIs that should be reachable while maintenance mode is enabled.
+     *
+     * @var array
+     */
+    protected $except = [
+        //
+    ];
+}

+ 32 - 0
app/Http/Middleware/RedirectIfAuthenticated.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Providers\RouteServiceProvider;
+use Closure;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+
+class RedirectIfAuthenticated
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure  $next
+     * @param  string|null  ...$guards
+     * @return mixed
+     */
+    public function handle(Request $request, Closure $next, ...$guards)
+    {
+        $guards = empty($guards) ? [null] : $guards;
+
+        foreach ($guards as $guard) {
+            if (Auth::guard($guard)->check()) {
+                return redirect(RouteServiceProvider::HOME);
+            }
+        }
+
+        return $next($request);
+    }
+}

+ 18 - 0
app/Http/Middleware/TrimStrings.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
+
+class TrimStrings extends Middleware
+{
+    /**
+     * The names of the attributes that should not be trimmed.
+     *
+     * @var array
+     */
+    protected $except = [
+        'password',
+        'password_confirmation',
+    ];
+}

+ 20 - 0
app/Http/Middleware/TrustHosts.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Http\Middleware\TrustHosts as Middleware;
+
+class TrustHosts extends Middleware
+{
+    /**
+     * Get the host patterns that should be trusted.
+     *
+     * @return array
+     */
+    public function hosts()
+    {
+        return [
+            $this->allSubdomainsOfApplicationUrl(),
+        ];
+    }
+}

+ 23 - 0
app/Http/Middleware/TrustProxies.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Fideloper\Proxy\TrustProxies as Middleware;
+use Illuminate\Http\Request;
+
+class TrustProxies extends Middleware
+{
+    /**
+     * The trusted proxies for this application.
+     *
+     * @var array|string|null
+     */
+    protected $proxies;
+
+    /**
+     * The headers that should be used to detect proxies.
+     *
+     * @var int
+     */
+    protected $headers = Request::HEADER_X_FORWARDED_ALL;
+}

+ 50 - 0
app/Http/Middleware/UserLogin.php

@@ -0,0 +1,50 @@
+<?php
+
+
+namespace App\Http\Middleware;
+
+use App\Helpers\Jwt;
+use App\Services\RedisService;
+use Closure;
+use Illuminate\Auth\Middleware\Authenticate as Middleware;
+
+class UserLogin extends Middleware
+{
+    /**
+     * 执行句柄
+     * @param \Illuminate\Http\Request $request
+     * @param Closure $next
+     * @param mixed ...$guards
+     * @return mixed
+     * @throws \Illuminate\Auth\AuthenticationException
+     * @since 2020/8/31
+     * @author laravel开发员
+     */
+    public function handle($request, Closure $next, ...$guards)
+    {
+        $response = $next($request);
+
+        $action = app('request')->route()->getAction();
+        $controller = class_basename($action['controller']);
+        list($controller, $action) = explode('@', $controller);
+        $noLoginActs = ['LoginController'];
+        $token = $request->headers->get('Authorization');
+        if (strpos($token, 'Bearer ') !== false) {
+            $token = str_replace("Bearer ", null, $token);
+            // JWT解密token
+            $jwt = new Jwt();
+            $userId = $jwt->verifyToken($token);
+
+        } else {
+            $userId = 0;
+        }
+
+        if (!$userId && !in_array($controller, $noLoginActs)) {
+            // 判断用户未登录就跳转至登录页面
+            // 在这里可以定制你想要的返回格式, 亦或者是 JSON 编码格式
+            return response()->json(message("请登录", false, null, 401));
+        }
+        //如果已登录则执行正常的请求
+        return $response;
+    }
+}

+ 17 - 0
app/Http/Middleware/VerifyCsrfToken.php

@@ -0,0 +1,17 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
+
+class VerifyCsrfToken extends Middleware
+{
+    /**
+     * The URIs that should be excluded from CSRF verification.
+     *
+     * @var array
+     */
+    protected $except = [
+        //
+    ];
+}

+ 82 - 0
app/Http/Middleware/WebLogin.php

@@ -0,0 +1,82 @@
+<?php
+
+
+namespace App\Http\Middleware;
+
+use App\Helpers\Jwt;
+use App\Services\ConfigService;
+use App\Services\RedisService;
+use Closure;
+use Illuminate\Auth\Middleware\Authenticate as Middleware;
+
+class WebLogin extends Middleware
+{
+    /**
+     * 执行句柄
+     * @param \Illuminate\Http\Request $request
+     * @param Closure $next
+     * @param mixed ...$guards
+     * @return mixed
+     * @throws \Illuminate\Auth\AuthenticationException
+     * @since 2020/8/31
+     * @author wesmiler
+     */
+    public function handle($request, Closure $next, ...$guards)
+    {
+        $action = app('request')->route()->getAction();
+        $controller = class_basename($action['controller']);
+        list($controller, $action) = explode('@', $controller);
+        $noLoginActs = ['LoginController','UploadController'];
+        $token = $request->headers->get('Authorization');
+        if (strpos($token, 'Bearer ') !== false) {
+            $token = str_replace("Bearer ", null, $token);
+            $token = trim($token);
+            if($token){
+                // JWT解密token
+                $jwt = new Jwt('jwt_jd_app');
+                $userId = $jwt->verifyToken($token);
+            }else{
+                return response()->json(message(1035, false, [], 403))->setEncodingOptions(256);
+            }
+
+        } else {
+            $userId = 0;
+        }
+
+        // 接口验证
+        $url = $request->get('s');
+        $url = empty($url)? $request->path() : $url;
+        $params = $request->except('s');
+        $sign = $request->header('sign');
+        if(empty($sign)){
+            $sign = isset($params['sign'])? $params['sign'] : '';
+        }
+
+        if($action != 'setAvatar'){
+            $system = isset($params['system']) ? $params['system'] : '';
+            $system = $system && !is_array($system)? json_decode($system,true) : $system;
+            $ctime = isset($system['sys_time'])? $system['sys_time'] : 0;
+            $uuid = isset($system['uuid'])? $system['uuid'] : 0;
+            $url = '/'.ltrim($url,'/');
+            $checkSign = getSign("{$url}&{$uuid}&{$ctime}");
+            if ($ctime < time() - 30 && !in_array($controller, $noLoginActs)) {
+                return response()->json(message(1012, false, null))->setEncodingOptions(256);
+            }
+
+            if ((empty($sign) || $sign != $checkSign) && !in_array($controller, $noLoginActs)) {
+                return response()->json(message(1005, false, null))->setEncodingOptions(256);
+            }
+        }
+
+        // 接口加密验证
+        $userInfo = RedisService::get("auths:info:{$userId}");
+        if (($userId<=0 || empty($userInfo))&& !in_array($controller, $noLoginActs)) {
+            // 在这里可以定制你想要的返回格式, 亦或者是 JSON 编码格式
+            return response()->json(message(1035, false, [], 403))->setEncodingOptions(256);
+        }
+
+        $request->headers->set('token_uid' , $userId);
+        //如果已登录则执行正常的请求
+        return $next($request);
+    }
+}

+ 48 - 0
app/Http/Validator/AccountValidator.php

@@ -0,0 +1,48 @@
+<?php
+namespace App\Http\Validator;
+class AccountValidator extends BaseValidator
+{
+    // 当前模型所有验证规则
+    public static $rules = [
+        'id' => 'required',
+        'user_id'=> 'required|min:1|max:10',
+        'money'=> 'required',
+        'type'=> 'required',
+    ];
+
+    // 当前模型所有错误提示信息
+    public static $msgs = [
+        'required' => ':attribute不能为空',
+        'string' => ':attribute必须是字符串',
+        'min' => ':attribute长度不能小于:min位',
+        'max' => ':attribute长度不能大于:max位',
+        'exists' => ':attribute不存在',
+        'rule' => ':attribute格式不正确',
+    ];
+
+    // 当前模型所有验证字段
+    public static $fields = [
+        'id' => 'ID',
+        'user_id' => '用户ID',
+        'money' => '金额',
+        'type' => '操作类型',
+    ];
+
+    // 当前模型所有验证场景
+    public static $scenes = [
+        'info'=> ['id'],
+        'change'=> ['user_id','money','type'],
+        'del'=> ['id'],
+    ];
+
+    /**
+     * 验证
+     * @param $request
+     * @param string $scene
+     * @return int|mixed
+     */
+    public static function check($request, $scene=''){
+        $validator = new BaseValidator(self::$rules, self::$msgs, self::$fields, self::$scenes);
+        return $validator->checkParams($request, $scene);
+    }
+}

+ 56 - 0
app/Http/Validator/BaseValidator.php

@@ -0,0 +1,56 @@
+<?php
+namespace App\Http\Validator;
+use Illuminate\Support\Facades\Validator;
+class BaseValidator extends Validator
+{
+    // 当前模型所有验证规则
+    public static $rules = [];
+
+    // 当前模型所有错误提示信息
+    public static $msgs = [];
+
+    // 当前模型所有验证字段
+    public static $fields = [];
+
+    // 当前模型所有验证场景
+    public static $scenes = [];
+
+    public function __construct($rules=[], $msgs=[], $fields=[], $scens=[])
+    {
+        self::$rules = $rules;
+        self::$msgs = $msgs;
+        self::$fields = $fields;
+        self::$scenes = $scens;
+    }
+
+    /**
+     * 验证表单或请求参数
+     * @param $request 请求数据
+     * @param string $scene 场景,为空则全部验证
+     * @return int|mixed
+     */
+    public function checkParams($request, $scene=''){
+        // 存在验证场景
+        if($scene){
+            $sceneFields = isset(self::$scenes[$scene])? self::$scenes[$scene] : [];
+            if(empty($sceneFields)){
+                return 1008;
+            }
+
+            foreach (self::$rules as $key => $rule){
+                if(!in_array($key, $sceneFields)){
+                    unset(self::$rules[$key]);
+                    unset(self::$fields[$key]);
+                }
+            }
+        }
+
+        // 验证数据
+        $validator = Validator::make($request, self::$rules, self::$msgs, self::$fields);
+        if ($validator->fails()) {
+            return getValidatorError($validator);
+        }
+
+        return $request;
+    }
+}

+ 75 - 0
app/Http/Validator/MemberValidator.php

@@ -0,0 +1,75 @@
+<?php
+namespace App\Http\Validator;
+class MemberValidator extends BaseValidator
+{
+    // 当前模型所有验证规则
+    public static $rules = [
+        'id' => 'required',
+        'code' => 'required',
+        'avatar' => 'required',
+        'nickname' => 'required|min:2|max:14',
+        'mobile' => 'required|mobile',
+        'sms_code' => 'required|min:4|max:6',
+        'password' => 'required|pwd|min:6|max:30',
+        'realname' => 'required|min:2|max:30',
+        'car_number' => 'required|min:2|max:30',
+        'car_type' => 'required|min:2|max:50',
+        'driving_license' => 'required',
+        'drivers_license' => 'required',
+        'scene' => 'required',
+        'access_token' => 'required',
+
+    ];
+    public static $msgs = [
+        'required' => ':attribute不能为空',
+        'string' => ':attribute必须是字符串',
+        'min' => ':attribute长度不能小于:min位',
+        'max' => ':attribute长度不能大于:max位',
+        'exists' => ':attribute不存在',
+        'rule' => ':attribute格式不正确',
+        'mobile' => ':attribute格式不正确',
+        'pwd' => ':attribute格式不正确,必须包含字母数字且6-20位',
+    ];
+
+    // 当前模型所有验证字段
+    public static $fields = [
+        'id' => 'ID',
+        'code' => '微信授权码',
+        'access_token' => 'access_token',
+        'avatar' => '头像',
+        'gender' => '性别',
+        'nickname' => '昵称',
+        'password' => '密码',
+        'username' => '登录账号',
+        'mobile' => '手机账号',
+        'realname' => '姓名',
+        'sms_code' => '验证码',
+        'car_number' => '车牌号码',
+        'car_type' => '车型',
+        'driving_license' => '驾驶证',
+        'drivers_license' => '行驶证',
+    ];
+
+    // 当前模型所有验证场景
+    public static $scenes = [
+        'info'=> ['id'],
+        'wx_login'=> ['openid','access_token'],
+        'login'=> ['mobile','password'],
+        'register'=> ['mobile','sms_code','password','realname','car_number','car_type','driving_license','drivers_license'],
+        'confirm'=> ['mobile','realname','car_number','car_type','driving_license','drivers_license'],
+        'modify'=> ['id'],
+        'sms'=> ['mobile','scene'],
+        'reset_password'=> ['mobile','password','sms_code'],
+    ];
+
+    /**
+     * 验证
+     * @param $request
+     * @param string $scene
+     * @return int|mixed
+     */
+    public static function check($request, $scene=''){
+        $validator = new BaseValidator(self::$rules, self::$msgs, self::$fields, self::$scenes);
+        return $validator->checkParams($request, $scene);
+    }
+}

+ 49 - 0
app/Http/Validator/OrderValidator.php

@@ -0,0 +1,49 @@
+<?php
+namespace App\Http\Validator;
+class OrderValidator extends BaseValidator
+{
+    // 当前模型所有验证规则
+    public static $rules = [
+        'id' => 'required',
+        'goods_id' => 'required',
+        'remark' => 'required|max:10',
+    ];
+
+    // 当前模型所有错误提示信息
+    public static $msgs = [
+        'required' => ':attribute不能为空',
+        'string' => ':attribute必须是字符串',
+        'min' => ':attribute长度不能小于:min位',
+        'max' => ':attribute长度不能大于:max位',
+        'exists' => ':attribute不存在',
+        'rule' => ':attribute格式不正确',
+        'mobile' => ':attribute格式不正确',
+    ];
+
+    // 当前模型所有验证字段
+    public static $fields = [
+        'id' => '订单ID',
+        'goods_id' => '接单信息',
+        'remark' => '备注说明',
+    ];
+
+    // 当前模型所有验证场景
+    public static $scenes = [
+        'info'=> ['id'],
+        'cancel'=> ['id','remark'],
+        'confirm'=> ['id'],
+        'complete'=> ['id'],
+        'submit'=> ['goods_id'],
+    ];
+
+    /**
+     * 验证
+     * @param $request
+     * @param string $scene
+     * @return int|mixed
+     */
+    public static function check($request, $scene=''){
+        $validator = new BaseValidator(self::$rules, self::$msgs, self::$fields, self::$scenes);
+        return $validator->checkParams($request, $scene);
+    }
+}

+ 2 - 0
app/Lib/phpqrcode/.gitignore

@@ -0,0 +1,2 @@
+.idea/
+temp/*.png

+ 38 - 0
app/Lib/phpqrcode/CHANGELOG

@@ -0,0 +1,38 @@
+* 1.0.0 build 2010031920 
+
+  - first public release
+  - help in readme, install
+  - cleanup ans separation of QRtools and QRspec
+  - now TCPDF binding requires minimal changes in TCPDF, having most of job
+    done in QRtools tcpdfBarcodeArray
+  - nicer QRtools::timeBenchmark output
+  - license and copyright notices in files
+  - indent cleanup - from tab to 4spc, keep it that way please :)
+  - sf project, repository, wiki
+  - simple code generator in index.php
+  
+* 1.1.0 build 2010032113
+
+  - added merge tool wich generate merged version of code
+    located in phpqrcode.php
+  - splited qrconst.php from qrlib.php
+  
+* 1.1.1 build 2010032405
+
+  - patch by Rick Seymour allowing saving PNG and displaying it at the same time
+  - added version info in VERSION file
+  - modified merge tool to include version info into generated file
+  - fixed e-mail in almost all head comments
+  
+* 1.1.2 build 2010032722
+
+  - full integration with TCPDF thanks to Nicola Asuni, it's author
+  - fixed bug with alphanumeric encoding detection
+  
+* 1.1.3 build 2010081807
+
+  - short opening tags replaced with standard ones
+  
+* 1.1.4 build 2010100721
+
+  - added missing static keyword QRinput::check (found by Luke Brookhart, Onjax LLC)

+ 165 - 0
app/Lib/phpqrcode/LICENSE

@@ -0,0 +1,165 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 3719 - 0
app/Lib/phpqrcode/QRcode.php


+ 61 - 0
app/Lib/phpqrcode/README

@@ -0,0 +1,61 @@
+This is PHP implementation of QR Code 2-D barcode generator. It is pure-php
+LGPL-licensed implementation based on C libqrencode by Kentaro Fukuchi.
+
+== UPDATE ==
+Added support for eps export
+Usage : QRcode::eps('arguments');
+
+Added support for SVG export
+Usage : QRcode::svg('arguments');
+
+Added support for color export :
+example : 
+$back_color = 0xFFFF00;
+$fore_color = 0xFF00FF;
+QRcode::png('some othertext 1234', false, 'h', 20, 1, false, $back_color, $fore_color);
+
+
+Copyright (C) 2012 by Alexandre Assouad 
+
+== LICENSING ==
+
+Copyright (C) 2010 by Dominik Dzienia 
+
+This library is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free
+Software Foundation; either version 3 of the License, or any later version.
+
+This library is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License (LICENSE file)
+for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this library; if not, write to the Free Software Foundation, Inc., 51
+Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+== INSTALATION AND USAGE ==
+
+ * INSTALL file
+ * http://sourceforge.net/apps/mediawiki/phpqrcode/index.php?title=Main_Page
+
+== CONTACT ==
+
+Fell free to contact me via e-mail (deltalab at poczta dot fm) or using
+folowing project pages:
+
+ * http://sourceforge.net/projects/phpqrcode/
+ * http://phpqrcode.sourceforge.net/
+  
+== ACKNOWLEDGMENTS ==
+
+Based on C libqrencode library (ver. 3.1.1) 
+Copyright (C) 2006-2010 by Kentaro Fukuchi
+http://megaui.net/fukuchi/works/qrencode/index.en.html
+
+QR Code is registered trademarks of DENSO WAVE INCORPORATED in JAPAN and other
+countries.
+
+Reed-Solomon code encoder is written by Phil Karn, KA9Q.
+Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
+ 

+ 2 - 0
app/Lib/phpqrcode/VERSION

@@ -0,0 +1,2 @@
+1.1.4
+2010100721

+ 34 - 0
app/Models/AccountLogModel.php

@@ -0,0 +1,34 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 账户明细-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Models
+ */
+class AccountLogModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'account_logs';
+
+    /**
+     * 用户
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function member()
+    {
+        return $this->hasOne(MemberModel::class, 'id','user_id')
+            ->select(['id','mobile','nickname','status']);
+    }
+}

+ 169 - 0
app/Models/ActionLogModel.php

@@ -0,0 +1,169 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+use Illuminate\Support\Facades\DB;
+
+/**
+ * 行为日志-模型
+ * @author laravel开发员
+ * @since 2020/11/10
+ * Class ActionLogModel
+ * @package App\Models
+ */
+class ActionLogModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = null;
+    // 自定义日志标题
+
+    protected static $recordUserId = 0;
+
+    protected static $recordType = 1;
+
+    protected static $module = 'admin';
+
+    protected static $title = '';
+    // 自定义日志内容
+    protected static $content = '';
+
+    public function __construct()
+    {
+        // 设置表名
+        $this->table = 'action_log_' . date('Y') . '_' . date('m');
+        // 初始化行为日志表
+        $this->initTable();
+    }
+
+    /**
+     * 初始化行为日志表
+     * @return string|null
+     * @since 2020/11/10
+     * @author laravel开发员
+     */
+    private function initTable()
+    {
+        $tbl = DB_PREFIX . $this->table;
+        if (!$this->tableExists($tbl)) {
+            $sql = "CREATE TABLE `{$tbl}` (
+                  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '唯一性标识',
+                  `username` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '操作人用户名',
+                  `method` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '请求类型',
+                  `module` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '模型',
+                  `action` varchar(255) NOT NULL COMMENT '操作方法',
+                  `url` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '操作页面',
+                  `param` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '请求参数(JSON格式)',
+                  `title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '日志标题',
+                  `type` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT '操作类型:1-后台 2-APP',
+                  `content` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '内容',
+                  `ip` varchar(18) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'IP地址',
+                  `user_agent` varchar(360) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'User-Agent',
+                  `create_user` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '添加人',
+                  `create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '添加时间',
+                  `update_user` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新人',
+                  `update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
+                  `mark` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '有效标识:1正常 0删除',
+                  PRIMARY KEY (`id`) USING BTREE
+                ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COMMENT='系统行为日志表';";
+            DB::select($sql);
+        }
+        return $tbl;
+    }
+
+    /**
+     * 设置标题
+     * @param $title 标题
+     * @since 2020/11/10
+     * @author laravel开发员
+     */
+    public static function setTitle($title)
+    {
+        self::$title = $title;
+    }
+
+    /**
+     * 设置内容
+     * @param $content 内容
+     * @since 2020/11/10
+     * @author laravel开发员
+     */
+    public static function setContent($content)
+    {
+        self::$content = $content;
+    }
+
+    /**
+     * 设置内容
+     * @param $content 内容
+     * @since 2020/11/10
+     * @author laravel开发员
+     */
+    public static function setRecord($userId, $params)
+    {
+        self::$recordUserId = $userId;
+        self::$module = isset($params['module']) && $params['module']? $params['module'] : 'app';
+        self::$recordType = isset($params['type']) && $params['type']? $params['type'] : 1;
+        self::$title = isset($params['title'])? $params['title'] : '';
+        self::$content = isset($params['content'])? $params['content'] : '';
+    }
+
+    /**
+     * 创建行为日志
+     * @author laravel开发员
+     * @since 2020/11/10
+     */
+    public static function record($username='')
+    {
+        if (!self::$title) {
+            // 操作控制器名
+            $menuModel = new MenuModel();
+            $info = $menuModel->getOne([
+                ['url', '=', request()->url()],
+            ]);
+            if ($info) {
+                if ($info['type'] == 1) {
+                    $menuInfo = $menuModel->getInfo($info['pid']);
+                    self::$title = $menuInfo['title'];
+                } else {
+                    self::$title = $info['title'];
+                }
+            }
+        }
+
+        // 登录用户ID
+        if(self::$recordUserId){
+            $userInfo = MemberModel::where(['id'=>self::$recordUserId])->select(['id','nickname as username'])->first();
+        }else{
+            $userId = session('userId');
+            $userInfo = UserModel::where(['id'=> $userId])->select(['id','username'])->first();
+        }
+
+        // 日志数据
+        $data = [
+            'username' => $username? $username : (isset($userInfo['username']) ? $userInfo['username'] : '未知'),
+            'module' => self::$module? self::$module : 'admin',
+            'action' => request()->path(),
+            'method' => request()->method(),
+            'url' => request()->url(true), // 获取完成URL
+            'param' => request()->all() ? json_encode(request()->all()) : '',
+            'title' => self::$title ? self::$title : '操作日志',
+            'type' => self::$recordType,
+            'content' => self::$content,
+            'ip' => request()->ip(),
+            'user_agent' => request()->server('HTTP_USER_AGENT'),
+            'create_user' => empty(session('userId')) ? 0 : session('userId'),
+            'create_time' => time(),
+        ];
+        // 日志入库
+        self::insert($data);
+    }
+}

+ 53 - 0
app/Models/AdModel.php

@@ -0,0 +1,53 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 广告管理-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class AdModel
+ * @package App\Models
+ */
+class AdModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'ad';
+
+    /**
+     * 获取广告信息
+     * @param int $id
+     * @return array|string
+     * @author laravel开发员
+     * @since 2020/11/11
+     */
+    public function getInfo($id)
+    {
+        $info = parent::getInfo($id); // TODO: Change the autogenerated stub
+        if ($info) {
+            // 广告封面
+            if ($info['cover']) {
+                $info['cover'] = get_image_url($info['cover']);
+            }
+            // 开始时间
+            if ($info['start_time']) {
+                $info['start_time'] = datetime($info['start_time']);
+            }
+            // 结束时间
+            if ($info['end_time']) {
+                $info['end_time'] = datetime($info['end_time']);
+            }
+        }
+        return $info;
+    }
+
+}

+ 25 - 0
app/Models/ArticleCateModel.php

@@ -0,0 +1,25 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 文章类型-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Models
+ */
+class ArticleCateModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'article_cates';
+
+}

+ 25 - 0
app/Models/ArticleModel.php

@@ -0,0 +1,25 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 文章资讯-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Models
+ */
+class ArticleModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'article';
+
+}

+ 34 - 0
app/Models/BalanceLogModel.php

@@ -0,0 +1,34 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 余额明细-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Models
+ */
+class BalanceLogModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'balance_logs';
+
+    /**
+     * 用户
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function member()
+    {
+        return $this->hasOne(MemberModel::class, 'id','user_id')
+            ->select(['id','mobile','nickname','balance','status']);
+    }
+}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1253 - 0
app/Models/BaseModel.php


+ 291 - 0
app/Models/CacheModel.php

@@ -0,0 +1,291 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\Cache;
+
+/**
+ * 缓存模型
+ * @author zongjl
+ * @date 2019/5/23
+ * Class CacheModel
+ * @package App\Models
+ */
+class CacheModel extends Model
+{
+    // 是否启用缓存
+    protected $is_cache = true;
+
+    /**
+     * 重置缓存
+     * @param int $id 记录ID
+     * @param array $data 数据源
+     * @param bool $is_edit 是否编辑
+     * @return bool 返回结果
+     * @author zongjl
+     * @date 2019/5/23
+     */
+    public function cacheReset($id, $data = [], $is_edit = false)
+    {
+        if (!$data) {
+            $this->resetCacheFunc('info', $id);
+        }
+        $info = [];
+        if ($is_edit) {
+            $info = $this->getCacheFunc("info", $id);
+        }
+        if (is_array($data)) {
+            $info = array_merge($info, $data);
+        } else {
+            $info = $data;
+        }
+        $cache_key = $this->getCacheKey('info', $id);
+        $result = $this->setCache($cache_key, $info);
+        return $result;
+    }
+
+    /**
+     * 删除缓存
+     * @param int $id 删除缓存ID
+     * @return bool 返回true或false
+     * @author zongjl
+     * @date 2019/5/23
+     */
+    public function cacheDelete($id)
+    {
+        $cache_key = $this->getCacheKey("info", $id);
+        $result = $this->deleteCache($cache_key);
+        return $result;
+    }
+
+    /**
+     * 设置单条数据缓存
+     * @param int $id 记录ID
+     * @return array 返回结果
+     * @author zongjl
+     * @date 2019/5/23
+     */
+    public function cacheInfo($id)
+    {
+        if (!$id) {
+            return false;
+        }
+        $data = $this->find((int)$id);
+        return $data ? $data->toArray() : [];
+    }
+
+    /**
+     * 获取缓存KEY
+     * @return string 缓存KEY
+     * @author zongjl
+     * @date 2019/5/23
+     */
+    public function getCacheKey()
+    {
+        $arg_list = func_get_args();
+        if ($this->table) {
+            array_unshift($arg_list, $this->table);
+        }
+        foreach ($arg_list as $key => $val) {
+            if (is_array($val)) {
+                unset($arg_list[$key]);
+            }
+        }
+        $cache_key = implode("_", $arg_list);
+        return $cache_key;
+    }
+
+    /**
+     * 设置缓存
+     * @param string $cache_key 缓存KEY
+     * @param array $data 缓存数据
+     * @param int $ttl 过期时间
+     * @return bool 返回结果
+     * @author zongjl
+     * @date 2019/5/23
+     */
+    public function setCache($cache_key, $data, $ttl = 0)
+    {
+        if (isset($GLOBALS['trans']) && $GLOBALS['trans'] === true) {
+            $GLOBALS['trans_keys'][] = $cache_key;
+        }
+
+        // 不设置缓存,直接返回
+        if (!$this->is_cache) {
+            return true;
+        }
+        if (!$data) {
+            return Cache::put($cache_key, null, $ttl);
+        }
+        $isGzcompress = gzcompress(json_encode($data));
+        if ($isGzcompress) {
+            $result = Cache::put($cache_key, $isGzcompress);
+        }
+        return $result;
+    }
+
+    /**
+     * 获取缓存
+     * @param string $cache_key 缓存KEY
+     * @return mixed 返回缓存数据
+     * @author zongjl
+     * @date 2019/5/23
+     */
+    public function getCache($cache_key)
+    {
+        $data = Cache::get($cache_key);
+        if ($data) {
+            $data = json_decode(gzuncompress($data), true);
+        }
+        return $data;
+    }
+
+    /**
+     * 删除缓存
+     * @param string $cache_key 缓存KEY
+     * @return bool 返回结果true或false
+     * @author zongjl
+     * @date 2019/5/23
+     */
+    public function deleteCache($cache_key)
+    {
+        // 判断缓存键值是否存在,存在则删除
+        if (Cache::has($cache_key)) {
+            return Cache::forget($cache_key);
+        }
+        return false;
+    }
+
+    /**
+     * 设置缓存函数
+     * @param string $funcName 方法名
+     * @param string $id 缓存数据ID
+     * @return bool 返回结果true或false
+     * @author zongjl
+     * @date 2019/5/23
+     */
+    public function resetCacheFunc($funcName, $id = '')
+    {
+        // 获取缓存KEY
+        $cache_key = $this->getCacheKey($funcName, $id);
+        // 删除缓存
+        $result = $this->deleteCache($cache_key);
+
+        // 设置缓存
+        $arg_list = func_get_args();
+        if ($this->table) {
+            array_shift($arg_list);
+        }
+        $act = "cache" . ucfirst($funcName);
+        $data = call_user_func_array(array($this, $act), $arg_list);
+        return $this->setCache($cache_key, $data);
+    }
+
+    /**
+     * 获取缓存函数
+     * @param string $funcName 方法名
+     * @param string $id 缓存数据ID
+     * @return mixed 返回结果
+     * @author zongjl
+     * @date 2019/5/23
+     */
+    public function getCacheFunc($funcName, $id = '')
+    {
+        $cache_key = $this->getCacheKey($funcName, $id);
+        $data = $this->getCache($cache_key);
+        if (!$data) {
+            $arg_list = func_get_args();
+            if ($this->table) {
+                array_shift($arg_list);
+            }
+            $act = "cache" . ucfirst($funcName);
+            $data = call_user_func_array(array($this, $act), $arg_list);
+            $this->setCache($cache_key, $data, rand(5, 10));
+        }
+        return $data;
+    }
+
+    /**
+     * 获取整表缓存
+     * @param array $map 查询条件
+     * @param bool $is_pri 是否只缓存主键true或false
+     * @param bool $pri_key 是否以主键作为键值true或false
+     * @return mixed 返回结果
+     * @author zongjl
+     * @date 2019/6/5
+     */
+    public function getAll($map = [], $is_pri = false, $pri_key = false)
+    {
+        $list = $this->getCacheFunc('all', $map, $is_pri, $pri_key);
+        return $list;
+    }
+
+    /**
+     * 设置整表缓存
+     * @param array $map 查询条件
+     * @param bool $is_pri 是否只缓存主键true或false
+     * @param bool $pri_key 是否以主键作为键值true或false
+     * @return mixed 返回结果
+     * @author zongjl
+     * @date 2019/6/5
+     */
+    public function cacheAll($map = [], $is_pri = false, $pri_key = false)
+    {
+        // 必备查询条件
+        $map[] = ['mark', '=', 1];
+
+        // 格式化查询条件
+        if (method_exists($this, 'formatQuery')) {
+            $query = $this->formatQuery($this, $map);
+        }
+
+        // 是否缓存主键
+        if ($is_pri) {
+            if (is_array($is_pri)) {
+                // 字段数组
+                $query->select($is_pri);
+            } elseif (is_string($is_pri)) {
+                // 字段字符串
+                $fields = explode(',', $is_pri);
+                $query->select($fields);
+            } else {
+                // 默认主键ID
+                $query->select('id');
+            }
+        }
+
+        // 查询数据并转数组
+        $list = $query->get()->toArray();
+
+        // 设置主键ID为数组键值
+        if ($pri_key) {
+            $list = array_column($list, null, 'id');
+        }
+
+        return $list;
+    }
+
+    /**
+     * 重置全表缓存
+     * @param array $map 查询条件
+     * @param bool $is_pri 是否只缓存主键true或false
+     * @param bool $pri_key 是否以主键作为键值true或false
+     * @return bool 返回结果true(重置成功)或false(重置失败)
+     * @author zongjl
+     * @date 2019/6/5
+     */
+    public function cacheResetAll($map = [], $is_pri = false, $pri_key = false)
+    {
+        return $this->resetCacheFunc('all', $map, $is_pri, $pri_key);
+    }
+}

+ 25 - 0
app/Models/CityModel.php

@@ -0,0 +1,25 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 城市-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class CityModel
+ * @package App\Models
+ */
+class CityModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'city';
+}

+ 25 - 0
app/Models/ConfigGroupModel.php

@@ -0,0 +1,25 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 配置分组-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class ConfigGroupModel
+ * @package App\Models
+ */
+class ConfigGroupModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'config_group';
+}

+ 41 - 0
app/Models/ConfigModel.php

@@ -0,0 +1,41 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 配置管理-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class ConfigModel
+ * @package App\Models
+ */
+class ConfigModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'config';
+    public function getInfo($id)
+    {
+        $info =  parent::getInfo($id); // TODO: Change the autogenerated stub
+        if($info){
+            $type = isset($info['type'])? $info['type'] : 'text';
+            if(isset($info['value']) && $type=='image'){
+                $info['value'] = get_image_url($info['value']);
+            }
+
+            if(isset($info['value']) && $type=='daterange'){
+                $info['value'] = json_decode($info['value'], true);
+            }
+
+        }
+        return $info;
+    }
+}

+ 35 - 0
app/Models/DepositModel.php

@@ -0,0 +1,35 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 保证金-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class CityModel
+ * @package App\Models
+ */
+class DepositModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'deposit_orders';
+
+    /**
+     * 用户
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function user()
+    {
+        return $this->hasOne(MemberModel::class, 'id','user_id')
+            ->select(['id','mobile','nickname','realname','status']);
+    }
+}

+ 101 - 0
app/Models/GoodsModel.php

@@ -0,0 +1,101 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 商品管理-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Models
+ */
+class GoodsModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'goods';
+
+    // 封面图
+    public function getThumbAttribute($value)
+    {
+        $thumb = $value? get_image_url($value) : get_image_url('/images/goods/goods.jpeg');
+        return $thumb;
+    }
+
+    public function setThumbAttribute($value)
+    {
+
+        return $value? get_image_path($value) : '';
+    }
+
+    public function getInfo($id)
+    {
+        $info = parent::getInfo($id); // TODO: Change the autogenerated stub
+        if($info){
+
+            $info['shipper_area'][] = isset($info['shipper_province_id'])? $info['shipper_province_id'] : 0;
+            $info['shipper_area'][] = isset($info['shipper_city_id'])? $info['shipper_city_id'] : 0;
+            $info['shipper_area'][] = isset($info['shipper_district_id'])? $info['shipper_district_id'] : 0;
+
+            $info['receiver_area'][] = isset($info['receiver_province_id'])? $info['receiver_province_id'] : 0;
+            $info['receiver_area'][] = isset($info['receiver_city_id'])? $info['receiver_city_id'] : 0;
+            $info['receiver_area'][] = isset($info['receiver_district_id'])? $info['receiver_district_id'] : 0;
+        }
+
+        return $info;
+    }
+
+    /**
+     * 订单信息
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function order()
+    {
+        return $this->hasOne(OrderModel::class, 'goods_id','id')
+            ->where(['mark'=>1])
+            ->whereIn('status',[2,3]);
+    }
+
+    /**
+     * 寄货城市
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function shipperCity()
+    {
+        return $this->hasOne(CityModel::class, 'citycode','shipper_city_id');
+    }
+
+    /**
+     * 寄货县/区
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function shipperDistrict()
+    {
+        return $this->hasOne(CityModel::class, 'citycode','shipper_district_id');
+    }
+
+    /**
+     * 收货城市
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function receiverCity()
+    {
+        return $this->hasOne(CityModel::class, 'citycode','receiver_city_id');
+    }
+
+    /**
+     * 收货县/区
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function receiverDistrict()
+    {
+        return $this->hasOne(CityModel::class, 'citycode','receiver_district_id');
+    }
+}

+ 98 - 0
app/Models/MemberModel.php

@@ -0,0 +1,98 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 会员-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class MemberModel
+ * @package App\Models
+ */
+class MemberModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'member';
+
+    /**
+     * 仓库
+     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+     */
+    public function stock()
+    {
+        return $this->belongsTo(StockModel::class, 'stock_id','stock_id')
+            ->where(['mark'=>1])
+            ->select(['stock_id','stock_name','status']);
+    }
+
+    /**
+     * 线路
+     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+     */
+    public function line()
+    {
+        return $this->belongsTo(LineModel::class, 'line_id','line_id')
+            ->where(['mark'=>1])
+            ->select(['line_id','line_name','status']);
+    }
+
+    /**
+     * 推荐人
+     */
+    public function parent()
+    {
+        return $this->hasOne(MemberModel::class, 'id','parent_id')
+            ->where(['status'=>1,'mark'=>1])
+            ->select(['id', 'nickname', 'username', 'mobile', 'status']);
+    }
+
+    /**
+     * 订单
+     * @return \Illuminate\Database\Eloquent\Relations\HasMany
+     */
+    public function order1()
+    {
+        return $this->hasMany(OrderModel::class, 'user_id','id')
+            ->where(['mark'=>1])->where('status','>=', 1);
+    }
+
+    /**
+     * 待捡货订单
+     * @return \Illuminate\Database\Eloquent\Relations\hasMany
+     */
+    public function order2()
+    {
+        return $this->hasMany(OrderModel::class, 'user_id','id')
+            ->where(['mark'=>1])->where('status', 2);
+    }
+
+
+    /**
+     * 获取会员信息
+     * @param int $id 会员ID
+     * @return array|string
+     * @author laravel开发员
+     * @since 2020/11/11
+     */
+    public function getInfo($id)
+    {
+        $info = parent::getInfo($id); // TODO: Change the autogenerated stub
+        if ($info) {
+            // 头像
+            if ($info['avatar']) {
+                $info['avatar'] = get_image_url($info['avatar']);
+            }
+        }
+        return $info;
+    }
+
+}

+ 64 - 0
app/Models/MenuModel.php

@@ -0,0 +1,64 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+
+use Ramsey\Uuid\Type\Integer;
+
+/**
+ * 菜单管理-模型
+ * @author laravel开发员
+ * @since 2020/11/10
+ * Class MenuModel
+ * @package App\Models
+ */
+class MenuModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'menu';
+
+
+    /**
+     * 获取子级菜单列表
+     * @param $pid 父级ID
+     * @return mixed
+     * @author laravel开发员
+     * @since 2020/11/11
+     */
+    public function getChilds($pid)
+    {
+        // 查询条件
+        $map = [];
+        // 父级ID
+        $map[] = ['pid', '=', $pid];
+        // 菜单状态
+        $map[] = ['status', '=', 1];
+        // 只取菜单
+        $map[] = ['type', '=', 0];
+        // 有效标识
+        $map[] = ['mark', '=', 1];
+
+        // 屏蔽菜单设置
+        if(!env('SHOW_MENU_MANAGE', false)){
+            $map[] = ['id','!=', 20];
+        }
+
+        $list = $this->where($map)->orderBy("sort", "asc")->get()->toArray();
+        if (!empty($list)) {
+            foreach ($list as &$val) {
+                $val['children'] = $this->getChilds($val['id']);
+            }
+        }
+        return $list;
+    }
+
+}

+ 56 - 0
app/Models/MessageModel.php

@@ -0,0 +1,56 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 消息管理-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Models
+ */
+class MessageModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'message';
+
+    /**
+     * 发送用户
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function fromUser()
+    {
+        return $this->hasOne(MemberModel::class, 'id','from_uid')
+            ->select(['id','avatar','nickname','realname','status']);
+    }
+
+    /**
+     * 接收用户
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function toUser()
+    {
+        return $this->hasOne(MemberModel::class, 'id','to_uid')
+            ->select(['id','avatar','nickname','realname','status']);
+    }
+
+    /**
+     * 最新消息
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function last()
+    {
+        return $this->hasOne(MessageModel::class, 'chat_key','chat_key')
+            ->where(['type'=>1,'mark'=>1])
+            ->select(['id','title','type','msg_type','content','from_uid','chat_key','to_uid','create_time','is_read','status'])
+            ->orderBy('create_time','desc');
+    }
+}

+ 30 - 0
app/Models/NoticeModel.php

@@ -0,0 +1,30 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 通知公告-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class NoticeModel
+ * @package App\Models
+ */
+class NoticeModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'notice';
+
+    protected function serializeDate(\DateTimeInterface $date): string
+    {
+        return $date->format('Y-m-d H:i:s');
+    }
+}

+ 70 - 0
app/Models/OrderModel.php

@@ -0,0 +1,70 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 订单管理-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Models
+ */
+class OrderModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'orders';
+
+
+
+    /**
+     * 接单人员
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function user()
+    {
+        return $this->hasOne(MemberModel::class, 'id','user_id')
+            ->select(['id','mobile','nickname','realname','balance','picker_order_num','picker_status','confirm_status','status']);
+    }
+
+    /**
+     * 经手人
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function adminUser()
+    {
+        return $this->hasOne(UserModel::class, 'id','confirm_admin_id')
+            ->select(['id','nickname','mobile','realname','status']);
+    }
+
+    /**
+     * 已审核
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function confirm()
+    {
+        return $this->hasOne(OrderModel::class, 'goods_id','goods_id')
+            ->with(['user'])
+            ->whereIn('status',[2,3])
+            ->where(['mark'=>1])
+            ->select(['id','order_no','goods_id','confirm_at','status']);
+    }
+
+    /**
+     * 订单商品
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function goods()
+    {
+        return $this->hasOne(GoodsModel::class, 'id','goods_id')->with(['shipperCity','shipperDistrict','receiverCity','receiverDistrict']);
+    }
+
+
+}

+ 34 - 0
app/Models/PaymentModel.php

@@ -0,0 +1,34 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 支付-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * @package App\Models
+ */
+class PaymentModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'payment_logs';
+
+    /**
+     * 用户
+     * @return \Illuminate\Database\Eloquent\Relations\HasOne
+     */
+    public function user()
+    {
+        return $this->hasOne(MemberModel::class, 'id','user_id')
+            ->select(['id','mobile','nickname','status']);
+    }
+}

+ 25 - 0
app/Models/RoleMenuModel.php

@@ -0,0 +1,25 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 角色菜单-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class RoleMenuModel
+ * @package App\Models
+ */
+class RoleMenuModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'role_menu';
+}

+ 25 - 0
app/Models/RoleModel.php

@@ -0,0 +1,25 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 角色-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class RoleModel
+ * @package App\Models
+ */
+class RoleModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'role';
+}

+ 52 - 0
app/Models/User.php

@@ -0,0 +1,52 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+use Illuminate\Contracts\Auth\MustVerifyEmail;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Foundation\Auth\User as Authenticatable;
+use Illuminate\Notifications\Notifiable;
+
+class User extends Authenticatable
+{
+    use HasFactory, Notifiable;
+
+    /**
+     * The attributes that are mass assignable.
+     *
+     * @var array
+     */
+    protected $fillable = [
+        'name',
+        'email',
+        'password',
+    ];
+
+    /**
+     * The attributes that should be hidden for arrays.
+     *
+     * @var array
+     */
+    protected $hidden = [
+        'password',
+        'remember_token',
+    ];
+
+    /**
+     * The attributes that should be cast to native types.
+     *
+     * @var array
+     */
+    protected $casts = [
+        'email_verified_at' => 'datetime',
+    ];
+}

+ 56 - 0
app/Models/UserModel.php

@@ -0,0 +1,56 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+use App\Services\Common\UserRoleService;
+
+/**
+ * 会员管理-模型
+ * @author laravel开发员
+ * @since 2020/11/10
+ * Class AdminModel
+ * @package App\Models
+ */
+class UserModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'user';
+
+    /**
+     * 获取数据信息
+     * @param int $id 用户ID
+     * @return array|string
+     * @author laravel开发员
+     * @since 2020/11/10
+     */
+    public function getInfo($id)
+    {
+        $info = parent::getInfo($id); // TODO: Change the autogenerated stub
+        if ($info) {
+            // 头像
+            if ($info['avatar']) {
+                $info['avatar'] = get_image_url($info['avatar']);
+            }
+
+            // 性别
+            if ($info['gender']) {
+                $info['gender_name'] = config('admin.gender_list')[$info['gender']];
+            }
+
+            // 获取用户角色列表
+            $userRoleService = new UserRoleService();
+            $roleList = $userRoleService->getUserRoleList($id);
+            $info['roles'] = $roleList;
+        }
+        return $info;
+    }
+}

+ 26 - 0
app/Models/UserRoleModel.php

@@ -0,0 +1,26 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Models;
+
+/**
+ * 用户角色-模型
+ * @author laravel开发员
+ * @since 2020/11/11
+ * Class UserRoleModel
+ * @package App\Models
+ */
+class UserRoleModel extends BaseModel
+{
+    // 设置数据表
+    protected $table = 'user_role';
+
+}

+ 66 - 0
app/Providers/AppServiceProvider.php

@@ -0,0 +1,66 @@
+<?php
+// +----------------------------------------------------------------------
+// | LARAVEL8.0 框架 [ LARAVEL ][ RXThinkCMF ]
+// +----------------------------------------------------------------------
+// | 版权所有 2017~2021 LARAVEL研发中心
+// +----------------------------------------------------------------------
+// | 官方网站: http://www.laravel.cn
+// +----------------------------------------------------------------------
+// | Author: laravel开发员 <laravel.qq.com>
+// +----------------------------------------------------------------------
+
+namespace App\Providers;
+
+use App\Services\RedisService;
+use Illuminate\Support\Facades\Validator;
+use Illuminate\Support\ServiceProvider;
+
+class AppServiceProvider extends ServiceProvider
+{
+    /**
+     * Register any application services.
+     *
+     * @return void
+     */
+    public function register()
+    {
+        //
+        \DB::listen(function ($query) {
+            $bindings = $query->bindings;
+            $sql = $query->sql;
+            foreach ($bindings as $replace) {
+                $value = is_numeric($replace) ? $replace : "'" . $replace . "'";
+                $sql = preg_replace('/\?/', $value, $sql, 1);
+            }
+        });
+    }
+
+    /**
+     * Bootstrap any application services.
+     *
+     * @return void
+     */
+    public function boot()
+    {
+        //验证手机号码
+        Validator::extend('mobile', function ($attribute, $value, $parameters, $validator) {
+            // 返回true/false
+            $reg='/^1[2-9]\d{9}$/';
+            return preg_match($reg,$value);
+        });
+
+        // 身份证号码
+        Validator::extend('idcard', function ($attribute, $value, $parameters, $validator) {
+            // 返回true/false
+            $reg='/(^\d{15}$)|(^\d{17}([0-9]|X))$/isu';
+            return preg_match($reg,$value);
+        });
+
+        // 登录密码
+        Validator::extend('pwd', function ($attribute, $value, $parameters, $validator) {
+            // 返回true/false
+            $reg='/^(?=.*[a-zA-Z])(?=.*\d)[A-Za-z\d@$!%*?&]{6,20}$/';
+            return preg_match($reg,$value);
+        });
+    }
+}

+ 30 - 0
app/Providers/AuthServiceProvider.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
+use Illuminate\Support\Facades\Gate;
+
+class AuthServiceProvider extends ServiceProvider
+{
+    /**
+     * The policy mappings for the application.
+     *
+     * @var array
+     */
+    protected $policies = [
+        // 'App\Models\Model' => 'App\Policies\ModelPolicy',
+    ];
+
+    /**
+     * Register any authentication / authorization services.
+     *
+     * @return void
+     */
+    public function boot()
+    {
+        $this->registerPolicies();
+
+        //
+    }
+}

+ 21 - 0
app/Providers/BroadcastServiceProvider.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Support\Facades\Broadcast;
+use Illuminate\Support\ServiceProvider;
+
+class BroadcastServiceProvider extends ServiceProvider
+{
+    /**
+     * Bootstrap any application services.
+     *
+     * @return void
+     */
+    public function boot()
+    {
+        Broadcast::routes();
+
+        require base_path('routes/channels.php');
+    }
+}

+ 32 - 0
app/Providers/EventServiceProvider.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Auth\Events\Registered;
+use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
+use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
+use Illuminate\Support\Facades\Event;
+
+class EventServiceProvider extends ServiceProvider
+{
+    /**
+     * The event listener mappings for the application.
+     *
+     * @var array
+     */
+    protected $listen = [
+        Registered::class => [
+            SendEmailVerificationNotification::class,
+        ],
+    ];
+
+    /**
+     * Register any events for your application.
+     *
+     * @return void
+     */
+    public function boot()
+    {
+        //
+    }
+}

+ 63 - 0
app/Providers/RouteServiceProvider.php

@@ -0,0 +1,63 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Cache\RateLimiting\Limit;
+use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\RateLimiter;
+use Illuminate\Support\Facades\Route;
+
+class RouteServiceProvider extends ServiceProvider
+{
+    /**
+     * The path to the "home" route for your application.
+     *
+     * This is used by Laravel authentication to redirect users after login.
+     *
+     * @var string
+     */
+    public const HOME = '/home';
+
+    /**
+     * The controller namespace for the application.
+     *
+     * When present, controller route declarations will automatically be prefixed with this namespace.
+     *
+     * @var string|null
+     */
+    // protected $namespace = 'App\\Http\\Controllers';
+
+    /**
+     * Define your route model bindings, pattern filters, etc.
+     *
+     * @return void
+     */
+    public function boot()
+    {
+        $this->configureRateLimiting();
+
+        $this->routes(function () {
+            Route::prefix('api')
+                ->middleware('api')
+                ->namespace($this->namespace)
+                ->group(base_path('routes/api.php'));
+
+            Route::middleware('web')
+                ->namespace($this->namespace)
+                ->group(base_path('routes/web.php'));
+        });
+    }
+
+    /**
+     * Configure the rate limiters for the application.
+     *
+     * @return void
+     */
+    protected function configureRateLimiting()
+    {
+        RateLimiter::for('api', function (Request $request) {
+            return Limit::perMinute(env('API_RATE_LIMIT',120))->by(optional($request->user())->id ?: $request->ip());
+        });
+    }
+}

+ 0 - 0
app/Services/Api/AccountService.php


Vissa filer visades inte eftersom för många filer har ändrats