all(); if (!empty($param['size'])) { $param['pageSize'] = $param['size']; } $param['openid'] = $request->user['openid']; $list = $this->service->setModel()->getList($param,null,true,['last','avatar'],['last' => function($data,$resp) use($param){ $last = (new SaasChatMsg)->where("poi_id",$resp['poi_id'])->where("openid",$param['openid'])->order("create_at desc")->field("content,create_at,type")->findOrEmpty(); if ($last->isEmpty()) { return ['type' => "text","content"=>"无",'num' => 0,"create_at"=> formatTime(date("Y-m-d H:i:s",time()))]; } return ["content"=> $last['content'],'num' => 0,"create_at"=> formatTime($last['create_at']),'type' => $last['type']]; },'avatar' => function(){ return "https://washmy.oss-cn-guangzhou.aliyuncs.com/storage/20260511/23627b2cb8f73a8a90b95c31d726e6ecad0cbb9a.png"; }]); return successTrans("success.data",pageFormat($list)); } catch (\Throwable $throwable) { return error($throwable->getMessage()); } } /** * 分配客服 * @param Request $request * @return Response */ #[PostMapping("shareout")] public function shareUser2Mer(Request $request): Response { try { $param = $request->all(); $store = (new SaasStore)->where("poi_id",$param['poi'])->findOrEmpty(); if ($store->isEmpty()) return error("店铺不存在"); $chatStore = (new SaasChatStore)->where(['poi_id'=> $store['poi_id'],"openid" => $request->user['openid']])->findOrEmpty(); $userAvatar = $request->user['avatar']; // 获取最新的10条聊天记录 $msg = (new SaasChatMsg)->where(['openid' => $request->user['openid'],'poi_id' => $store['poi_id']])->append(['avatar','time'])->withAttr(['avatar' => function($data,$resp) use($userAvatar){ if ($resp['source'] == 1) { // 用户 return $userAvatar??''; } else { return "https://washmy.oss-cn-guangzhou.aliyuncs.com/storage/20260511/23627b2cb8f73a8a90b95c31d726e6ecad0cbb9a.png"; } },'time' => function($resp,$data){ return strtotime($data['create_at']) * 1000; }])->order("id","desc")->paginate([ "list_rows" => 10, "page" => 1 ]); // 获取在线客服 $service = (new SystemUser)->where("store_id",$param['poi'])->where("type",3)->where("is_line",1)->findOrEmpty(); if ($service->isEmpty()) return $this->encode("ok",['store' => $store,'code' => 3,'sendId' => $request->user['openid'],'msg' => pageFormatMsg($msg),"serviceId" => 0]); // 无客服在线 if ($chatStore->isEmpty()) { $chatStore->insertGetId([ "poi_id" => $store['poi_id'], "poi_name" => $store['poi_name'], "openid" => $request->user['openid'], "service_id" => $service['id'], "order" => $param['order']??'', "goods" => $param['goods']??'', "last_at" => getDateFull() ]); } else { $chatStore->service_id = $service['id']; $chatStore->order = $param['order']??''; $chatStore->goods = $param['goods']??''; $chatStore->last_at = getDateFull(); $chatStore->save(); } return $this->encode("ok",['store' => $store,'code' => 1,'sendId' => $request->user['openid'],'msg' => pageFormatMsg($msg),"serviceId" => $service['id'],'avatar' => $userAvatar]); // 客服在线 } catch (\Throwable $throwable) { echo $throwable->getMessage()."\n"; echo $throwable->getFile()."\n"; echo $throwable->getLine()."\n"; return error($throwable->getMessage()); } } #[GetMapping("msg")] public function getMessageList(Request $request): Response { try { $param = $this->_valid([ "poi.require" => trans("empty.require"), "page.default" => 1, "size.default" => 10 ],$request->method()); if (!is_array($param)) return error($param); $userAvatar = $request->user['avatar']; $msg = (new SaasChatMsg)->where(['openid' => $request->user['openid'],'poi_id' => $param['poi']])->append(['avatar','time'])->withAttr(['avatar' => function($data,$resp) use($userAvatar){ if ($resp['source'] == 1) { return $userAvatar??''; } else { return "https://washmy.oss-cn-guangzhou.aliyuncs.com/storage/20260511/23627b2cb8f73a8a90b95c31d726e6ecad0cbb9a.png"; } },'time' => function($resp,$data){ return strtotime($data['create_at']) * 1000; }])->order("id","desc")->paginate([ "list_rows" => $param['size']??10, "page" => $param['page']??1, ]); return $this->encode("ok",pageFormat($msg)); } catch (\Throwable $throwable) { return error($throwable->getMessage()); } } /** * 发送消息 * @param Request $request * @return Response */ #[PostMapping("send")] public function sendMsg(Request $request): Response { try { $param = $this->_valid([ "content.require" => trans("empty.require"), "groupId.require" => trans("empty.require"), "type.require" => trans("empty.require"), "sendId.require" => trans("empty.require"), ],"post"); if (!is_array($param)) return error($param); (new SaasChatMsg)->insertGetId([ "source" => 1, "openid" => $request->user['openid'], "content" => is_array($param['content'])?json_encode($param['content']):$param['content'], "type" => $param['type'], "msgId" => time(), "poi_id" => $param['groupId'], "service_id" => $param['sendId'], ]); $chatStore = (new SaasChatStore)->where(['openid' => $request->user['openid'],"service_id" => $param['sendId']])->with(['user' => function($query){ $query->field("openid,nickname,avatar,mobile,create_at"); }])->append(['last','avatar'])->withAttr(['last' => function($data,$resp) use($param){ $last = (new SaasChatMsg)->where(["poi_id" => $resp['poi_id'],"service_id" => $param['sendId'],"openid" => $resp['openid']])->order("create_at desc")->field("content,create_at,type")->findOrEmpty(); if ($last->isEmpty()) { return ['type' => "text","content"=>"无",'num' => 0,'time' => time(),"create_at"=> formatTime(date("Y-m-d H:i:s",time()))]; } $total = (new SaasChatMsg)->where(["poi_id" => $resp['poi_id'],"service_id" => $param['sendId'],"openid" => $resp['openid'],'is_read' => 0])->count(); return ["content"=> str_cut_ellipsis($last['content']),'num' => ($total),"create_at"=> formatTime($last['create_at']),"time"=> strtotime($last['create_at']),'type' => $last['type']]; },'avatar' => function(){ return "https://washmy.oss-cn-guangzhou.aliyuncs.com/storage/20260511/23627b2cb8f73a8a90b95c31d726e6ecad0cbb9a.png"; }])->findOrEmpty(); if (!$chatStore->isEmpty()) { $chatStore->save(['last_at' => getDateFull()]); } $chatStore['last_at'] = getDateFull(); $api = new Api('http://127.0.0.1:3232', config('plugin.webman.push.app.app_key'),config('plugin.webman.push.app.app_secret')); $api->trigger("service-{$param['sendId']}","message",[ "type" => $param['type'], "time" => time() * 1000, "msgId" => time(), "content" => is_array($param['content'])?json_encode($param['content']):$param['content'], "source" => 1, "avatar" => "https://washmy.oss-cn-guangzhou.aliyuncs.com/storage/20260511/23627b2cb8f73a8a90b95c31d726e6ecad0cbb9a.png", "poi_id" => $param['groupId'], "openid" => $request->user['openid'], "service_id" => $param['sendId'], "create_at" => formatTime(time()), "last_at" => getDateFull(), "user" => [ "nickname" => $request->user['nickname'], "avatar" => $request->user['avatar'] ], "item" => $chatStore->toArray() ]); return successTrans("success.data"); } catch (\Throwable $throwable) { echo $throwable->getMessage()."\n"; return error($throwable->getMessage()); } } /** * 发送图片消息 * @param Request $request * @return Response */ #[PostMapping("send/img")] public function sendImgMsg(Request $request): Response { try { $resp = UploadExtend::uploadFile(); if (!isset($resp[0]['url'])) return error("发送失败"); $param = $this->_valid([ "groupId.require" => trans("empty.require"), "type.require" => trans("empty.require"), "sendId.require" => trans("empty.require"), ],"post"); if (!is_array($param)) return error($param); $param['content'] = $resp[0]['url']; $state = (new SaasChatMsg)->insertGetId([ "source" => 1, "openid" => $request->user['openid'], "content" => is_array($param['content'])?json_encode($param['content']):$param['content'], "type" => $param['type'], "msgId" => time(), "poi_id" => $param['groupId'], "service_id" => $param['sendId'], ]); $api = new Api('http://127.0.0.1:3232', config('plugin.webman.push.app.app_key'),config('plugin.webman.push.app.app_secret')); $api->trigger("service-{$param['sendId']}","message",[ "type" => $param['type'], "time" => time() * 1000, "msgId" => time(), "content" => is_array($param['content'])?json_encode($param['content']):$param['content'], "source" => 1, "avatar" => "https://washmy.oss-cn-guangzhou.aliyuncs.com/storage/20260511/23627b2cb8f73a8a90b95c31d726e6ecad0cbb9a.png", "poi_id" => $param['groupId'], "openid" => $request->user['openid'], "service_id" => $param['sendId'], "create_at" => formatTime(time()), "user" => [ "nickname" => $request->user['nickname'] ] ]); return successTrans("success.data",['path' => $param['content']],200); } catch (\Throwable $throwable) { echo $throwable->getMessage()."\n"; return error($throwable->getMessage()); } } /** * 收集完善用户收货地址 * @param Request $request * @return Response */ #[PostMapping("send/address")] public function setOrderAddress(Request $request): Response { try { $param = $this->_valid([ "city.require" => trans("empty.require"), "mobile.require" => trans("empty.require"), "mobile.mobile" => trans("error.mobile"), "address.require" => trans("empty.require"), "nickname.require" => trans("empty.require"), "order.require" => trans("empty.require"), ],$request->method()); if (!is_array($param)) return error($param); $cityJson = json_decode($param['city'],true); $cityCode = []; foreach ($cityJson as $k => $v){ $cityCode[$k] = $v['value']; $param['city_text'] .= $v['text']; } $param['city_code'] = json_encode($cityCode); $orderData = json_decode($param['order'],true); $order = (new SaasOrder)->where("out_trade_no",$orderData["order"])->with(['poi'])->findOrEmpty(); if ($order->isEmpty()) return error("关联订单错误"); if ($order['openid'] <> $request->user['openid']) return error("关联订单错误"); if ($order['status'] <> 1) return error("关联订单错误"); $startTime = $order['poi']['order_start']??'09:00'; $endTime = $order['poi']['order_end']??'22:30'; $startTimeStamp = strtotime("Y-m-d {$startTime}:00"); $endTimeStamp = strtotime("Y-m-d {$endTime}:00"); $address = (new SaasOrderAddress)->where(['openid' => $request->user['openid'],'order_sn' => $orderData['order']])->findOrEmpty(); if (!$address->isEmpty()) return error("请勿重复提交"); $address->insertGetId([ "openid" => $request->user['openid'], "order_sn" => $orderData['order'], "city_code" => $param['city_code'], "city_text" => $param['city_text'], "mobile" => $param['mobile'], "address" => $param['address'], "nickname" => $param['nickname'], ]); // 判断是否在核销范围 if (time() > $startTimeStamp && time() < $endTimeStamp) { // 自动核销,订单状态改成待发货 Redis::send("order-done",['order' => $orderData['order']]); } else { // 写入待核销定时任务队列中 (new SaasOrderDelay)->insertGetId([ "order_sn" => $orderData['order'], ]); } return success("提交成功"); } catch (\Throwable $throwable) { echo $throwable->getMessage()."\n"; return error($throwable->getMessage()); } } }