You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
383 lines
14 KiB
383 lines
14 KiB
10 months ago
|
<?php
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | 天诚科技 [ 刘海东 17600099397赋能开发者,助力企业发展 ]
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | Copyright (c) 2016~2020 https://www.tczxkj.com All rights reserved.
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | Licensed 该系统并不是自由软件,未经许可不能去掉相关版权
|
||
|
// +----------------------------------------------------------------------
|
||
|
// | Author: CRMEB Team <admin@crmeb.com>
|
||
|
// +----------------------------------------------------------------------
|
||
|
|
||
|
namespace app\kefu\services;
|
||
|
|
||
|
use app\kefu\controller\AuthController;
|
||
|
use app\kefu\model\KefuModel;
|
||
|
use service\FormBuilder as Form;
|
||
|
use service\JsonService as Json;
|
||
|
use service\UploadService as Upload;
|
||
|
use think\exception\ValidateException;
|
||
|
use think\Request;
|
||
|
use think\Url;
|
||
|
use app\admin\model\article\ArticleCategory as ArticleCategoryModel;
|
||
|
use app\admin\model\article\Article as ArticleModel;
|
||
|
use think\Session;
|
||
|
use service\JwtService;
|
||
|
use app\kefu\model\KefuChatLogModel;
|
||
|
use app\kefu\model\KefuUserRecordModel;
|
||
|
use app\admin\model\user\User as UserModel;
|
||
|
use app\admin\model\special\Special as SpecialModel;
|
||
|
use app\admin\model\special\SpecialTask;
|
||
|
use app\admin\model\store\StoreProduct;
|
||
|
use app\admin\model\download\DataDownload;
|
||
|
use app\wap\model\material\DataDownloadOrder;
|
||
|
use service\BaseService;
|
||
|
use app\admin\model\order\StoreOrder as StoreOrderModel;
|
||
|
use app\admin\model\order\StoreOrderCartInfo;
|
||
|
use think\Log;
|
||
|
|
||
|
class KefuChatService extends BaseService
|
||
|
{
|
||
|
const MSN_TYPE_TEXT = 1;
|
||
|
const MSN_TYPE_EMOJI = 2;
|
||
|
const MSN_TYPE_IMG = 3;
|
||
|
const MSN_TYPE_VOICE = 4;
|
||
|
const MSN_TYPE_GOOD = 5;
|
||
|
const MSN_TYPE_ORDER = 21;
|
||
|
const MSN_TYPE_TRANSFER = 24;
|
||
|
|
||
|
private $model;
|
||
|
|
||
|
public function __construct()
|
||
|
{
|
||
|
$this->model = new KefuChatLogModel;
|
||
|
}
|
||
|
|
||
|
public function getServiceList($where)
|
||
|
{
|
||
|
return (new KefuModel)->where($where)->select()->toArray();
|
||
|
}
|
||
|
|
||
|
public function tidyChat(array $list)
|
||
|
{
|
||
|
$guestUserInfo = null;
|
||
|
$kefuUserInfo = null;
|
||
|
|
||
|
$specialModel = (new SpecialModel);
|
||
|
$specialTaskModel = (new SpecialTask);
|
||
|
$storeProductModel = (new StoreProduct);
|
||
|
$dataDownloadModel = (new DataDownload);
|
||
|
$storeOrderModel = (new StoreOrderModel);
|
||
|
$storeOrderInfoModel = (new StoreOrderCartInfo);
|
||
|
$dataDownloadOrderModel = (new DataDownloadOrder);
|
||
|
|
||
|
foreach ($list as &$item) {
|
||
|
if ($item['is_kefu_send']) {
|
||
|
// 客服发送的消息
|
||
|
if (is_null($kefuUserInfo)) {
|
||
|
$kefuUserInfo = KefuModel::get($item['uid']);
|
||
|
}
|
||
|
|
||
|
if (!is_null($kefuUserInfo)) {
|
||
|
$item['avatar'] = $kefuUserInfo->avatar;
|
||
|
}
|
||
|
} else {
|
||
|
// 用户发送的消息
|
||
|
if (is_null($guestUserInfo)) {
|
||
|
$guestUserInfo = UserModel::get($item['uid']);
|
||
|
}
|
||
|
|
||
|
if (!is_null($guestUserInfo)) {
|
||
|
$item['avatar'] = $guestUserInfo->avatar;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($item['msn_type'] == self::MSN_TYPE_GOOD && $item['good_type'] > 0) {
|
||
|
// 商品类型消息
|
||
|
$type = $item['good_type'];
|
||
|
if ($type == 1) {
|
||
|
// 课程商品
|
||
|
$info = $specialModel->field('id, fake_sales as sales, image, banner as slider_image, abstract as description, title as store_name, money as price, member_money as vip_price')->find($item['msn']);
|
||
|
|
||
|
$info->type_name = "课程";
|
||
|
|
||
|
$info->stock = "0";
|
||
|
|
||
|
$item['productInfo'] = $info;
|
||
|
} else if ($type == 2) {
|
||
|
// 商城商品
|
||
|
$info = $storeProductModel->field('id, sales, stock, image, slider_image, description, store_name, price, ot_price, vip_price')->find($item['msn']);
|
||
|
|
||
|
$info->slider_image = json_decode($info->slider_image);
|
||
|
|
||
|
$info->type_name = "商品";
|
||
|
|
||
|
$item['productInfo'] = $info;
|
||
|
} else if ($type == 3) {
|
||
|
// 会员商品
|
||
|
} else if ($type == 4) {
|
||
|
// 报名商品
|
||
|
} else if ($type == 5) {
|
||
|
// 资料商品
|
||
|
$info = $dataDownloadModel->field('id, sales, image, abstract as description, title as store_name, money as price, member_money as vip_price')->find($item['msn']);
|
||
|
|
||
|
$info->slider_image = [$info->image];
|
||
|
|
||
|
$info->type_name = "资料";
|
||
|
|
||
|
$info->stock = "0";
|
||
|
|
||
|
$item['productInfo'] = $info;
|
||
|
} else if ($type == 6) {
|
||
|
// 考试商品
|
||
|
} else if ($type == 7) {
|
||
|
// 充值商品
|
||
|
} else if ($type == 8) {
|
||
|
// 素材类型
|
||
|
$info = $specialTaskModel->field('id, image, detail as description, title as store_name')->find($item['msn']);
|
||
|
$info->slider_image = [$info->image];
|
||
|
|
||
|
$info->sales = 0;
|
||
|
|
||
|
$info->price = 0;
|
||
|
|
||
|
$info->vip_price = 0;
|
||
|
|
||
|
$info->type_name = "资料";
|
||
|
|
||
|
$info->stock = "0";
|
||
|
|
||
|
$item['productInfo'] = $info;
|
||
|
}
|
||
|
} else if ($item['msn_type'] == self::MSN_TYPE_ORDER && $item['order_type'] > 0) {
|
||
|
// 订单类型消息
|
||
|
|
||
|
$type = $item['order_type'];
|
||
|
if ($type == 1) {
|
||
|
// 课程订单
|
||
|
$orderInfo = $storeOrderModel->field('id, order_id, real_name, user_phone, user_address, cart_id, total_num, total_price, total_postage, pay_price, paid, pay_time, pay_type, add_time, status, refund_status ,delivery_type, delivery_id, coupon_price, pay_postage, spread_uid')->find($item['msn']);
|
||
|
|
||
|
$specialInfo = $specialModel->find($orderInfo->cart_id);
|
||
|
|
||
|
$orderInfo->cartInfo = [
|
||
|
[
|
||
|
'productInfo' => [
|
||
|
'image' => $specialInfo->image,
|
||
|
'id' => $specialInfo->id,
|
||
|
'store_name' => $specialInfo->title,
|
||
|
'price' => $specialInfo->money
|
||
|
]
|
||
|
]
|
||
|
];
|
||
|
$orderInfo->type_name = "课程";
|
||
|
|
||
|
$item['orderInfo'] = $orderInfo;
|
||
|
} else if ($type == 2) {
|
||
|
// 商城商品订单
|
||
|
|
||
|
$orderInfo = $storeOrderModel->field('id, order_id, real_name, user_phone, user_address, cart_id, total_num, total_price, total_postage, pay_price, paid, pay_time, pay_type, add_time, status, refund_status, delivery_type, delivery_id, coupon_price, pay_postage, spread_uid')->find($item['msn']);
|
||
|
|
||
|
$orderCartInfo = $storeOrderInfoModel->where('oid', $item['msn'])->select()->each(function ($item) {
|
||
|
$item->cart_info = json_decode($item->cart_info);
|
||
|
})->toArray();
|
||
|
|
||
|
$orderInfo->cartInfo = array_column($orderCartInfo, "cart_info");
|
||
|
$orderInfo->type_name = "商城商品";
|
||
|
|
||
|
$item['orderInfo'] = $orderInfo;
|
||
|
} else if ($type == 3) {
|
||
|
// 会员商品订单
|
||
|
} else if ($type == 4) {
|
||
|
// 报名商品订单
|
||
|
} else if ($type == 5) {
|
||
|
// 资料订单
|
||
|
$orderInfo = $dataDownloadOrderModel->field("id, order_id, data_id, total_num, total_price, pay_price, paid, pay_time, pay_type,status, refund_status, add_time")->find($item['msn']);
|
||
|
|
||
|
$dataInfo = $dataDownloadModel->find($orderInfo->data_id);
|
||
|
|
||
|
$orderInfo->cartInfo = [
|
||
|
[
|
||
|
'productInfo' => [
|
||
|
'image' => $dataInfo->image,
|
||
|
'id' => $dataInfo->id,
|
||
|
'store_name' => $dataInfo->title,
|
||
|
'price' => $dataInfo->money
|
||
|
]
|
||
|
]
|
||
|
];
|
||
|
$orderInfo->type_name = "资料";
|
||
|
|
||
|
$item['orderInfo'] = $orderInfo;
|
||
|
} else if ($type == 6) {
|
||
|
// 考试订单
|
||
|
} else if ($type == 7) {
|
||
|
// 充值订单
|
||
|
}
|
||
|
|
||
|
$item['orderInfo']->add_time = date("Y/m/d H:i:s", $item['orderInfo']->add_time);
|
||
|
$item['orderInfo']->pay_time = date("Y/m/d H:i:s", $item['orderInfo']->pay_time);
|
||
|
|
||
|
if (isset($item['spread_uid']) && $item['spread_uid']) {
|
||
|
$spreadUserInfo = UserModel::get($item['spread_uid']);
|
||
|
if ($spreadUserInfo) {
|
||
|
$item['spread_name'] = $spreadUserInfo->nickname;
|
||
|
}
|
||
|
}
|
||
|
} else if ($item['msn_type'] == self::MSN_TYPE_TRANSFER && $item['msn']) {
|
||
|
$kefuInfo = (new KefuModel)->field('id, avatar, nickname')->find($item['msn']);
|
||
|
if ($kefuInfo) {
|
||
|
$item['kefu_info'] = $kefuInfo;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $list;
|
||
|
}
|
||
|
|
||
|
public function getChatList($uid, $toUid, $upperId, $is_tourist = 0, $is_kefu_send = 1)
|
||
|
{
|
||
|
[$page, $limit] = $this->getPageValue();
|
||
|
|
||
|
$result = $this
|
||
|
->model
|
||
|
->where(
|
||
|
function ($q) use ($uid, $toUid, $is_tourist, $upperId, $is_kefu_send) {
|
||
|
$q->where('is_tourist', $is_tourist);
|
||
|
if ($upperId) {
|
||
|
$q->where('id', '<', $upperId);
|
||
|
}
|
||
|
|
||
|
$q->where(function ($q) use ($uid, $toUid, $is_kefu_send) {
|
||
|
$q
|
||
|
->where(function ($q) use ($uid, $toUid, $is_kefu_send) {
|
||
|
$q->where('uid', $uid)
|
||
|
->where('to_uid', $toUid)
|
||
|
->where('is_kefu_send', $is_kefu_send);
|
||
|
})
|
||
|
->whereOr(function ($q) use ($uid, $toUid, $is_kefu_send) {
|
||
|
$q->where('uid', $toUid)
|
||
|
->where('to_uid', $uid)
|
||
|
->where('is_kefu_send', $is_kefu_send ? 0 : 1);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
)
|
||
|
->limit($limit)
|
||
|
->order('id DESC')
|
||
|
->select()
|
||
|
->toArray();
|
||
|
|
||
|
return array_reverse($this->tidyChat($result));
|
||
|
}
|
||
|
|
||
|
public function saveChatLog($msn, $uid, $to_uid, $is_tourist, $is_kefu_send, $msn_type = self::MSN_TYPE_TEXT, $type = 0, $attach_type = 0)
|
||
|
{
|
||
|
$saveData = compact("msn", "uid", "to_uid", "is_tourist", "is_kefu_send", "msn_type", "type");
|
||
|
|
||
|
$saveData = array_merge($saveData, [
|
||
|
'add_time' => time()
|
||
|
]);
|
||
|
|
||
|
if ($msn_type == self::MSN_TYPE_GOOD) {
|
||
|
$saveData['good_type'] = $attach_type;
|
||
|
} else if ($msn_type == self::MSN_TYPE_ORDER) {
|
||
|
$saveData['order_type'] = $attach_type;
|
||
|
}
|
||
|
|
||
|
$record = KefuChatLogModel::create($saveData);
|
||
|
|
||
|
$record = $this->tidyChat([$record])[0];
|
||
|
|
||
|
$this->saveChatUser($uid, $to_uid, $is_tourist, $msn_type, $msn, $is_kefu_send);
|
||
|
|
||
|
return $record;
|
||
|
}
|
||
|
|
||
|
public function saveChatUser($uid, $to_uid, $is_tourist, $msn_type, $msn, $is_kefu_send)
|
||
|
{
|
||
|
$where = [
|
||
|
'user_id' => $uid,
|
||
|
'to_uid' => $to_uid
|
||
|
];
|
||
|
$record = (new KefuUserRecordModel)->where($where)->find();
|
||
|
$avatar = "";
|
||
|
$nickname = "";
|
||
|
if (!$is_kefu_send) {
|
||
|
$user = KefuModel::get($to_uid);
|
||
|
if ($user) {
|
||
|
$avatar = $user->avatar;
|
||
|
$nickname = $user->nickname;
|
||
|
}
|
||
|
} else {
|
||
|
$user = UserModel::get($to_uid);
|
||
|
if ($user) {
|
||
|
$avatar = $user->avatar;
|
||
|
$nickname = $user->nickname;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($record) {
|
||
|
// 更新
|
||
|
|
||
|
$record->update([
|
||
|
'message' => $msn,
|
||
|
'message_type' => $msn_type,
|
||
|
'update_time' => time(),
|
||
|
'avatar' => $avatar,
|
||
|
'nickname' => $nickname
|
||
|
], $where);
|
||
|
} else {
|
||
|
// 保存
|
||
|
KefuUserRecordModel::create([
|
||
|
'user_id' => $uid,
|
||
|
'to_uid' => $to_uid,
|
||
|
'nickname' => $nickname,
|
||
|
'avatar' => $avatar,
|
||
|
'is_tourist' => $is_tourist,
|
||
|
'add_time' => time(),
|
||
|
'update_time' => time(),
|
||
|
'message' => $msn,
|
||
|
'message_type' => $msn_type,
|
||
|
'is_kefu_send' => $is_kefu_send
|
||
|
]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function getUserSupportInfo($uidTo, $limit, $toUid, $uid,$mer_id)
|
||
|
{
|
||
|
if (!$toUid && !$mer_id) {
|
||
|
// 没有指定客服人员
|
||
|
$serviceInfoList = $this->getServiceList(['status' => 1, 'online' => 1]);
|
||
|
if (!count($serviceInfoList)) throw new ValidateException("暂无客服人员在线,请稍后联系");
|
||
|
|
||
|
$kefuIds = array_column($serviceInfoList, "id");
|
||
|
|
||
|
$toUid = (new KefuRecordService)->getLatelyMsgByUid($uid);
|
||
|
|
||
|
//如果上次聊天的客不在当前在线客服中,则随机选择一个客服
|
||
|
if (!in_array($toUid, $kefuIds)) {
|
||
|
$toUid = 0;
|
||
|
}
|
||
|
if (!$toUid) {
|
||
|
$toUid = $kefuIds[array_rand($kefuIds)] ?: 0;
|
||
|
}
|
||
|
if (!$toUid) {
|
||
|
throw new ValidateException('暂无客服人员在线,请稍后联系');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$kefuInfo = KefuModel::get($toUid ? $toUid : $mer_id);
|
||
|
if($kefuInfo['online'] == 0){
|
||
|
throw new ValidateException('暂无客服人员在线,请稍后联系');
|
||
|
}
|
||
|
$result = [
|
||
|
'uid' => $toUid ? $toUid : $mer_id,
|
||
|
'nickname' => $kefuInfo->nickname,
|
||
|
'avatar' => $kefuInfo->avatar,
|
||
|
'serviceList' => $this->getChatList($uid, $toUid ? $toUid : $mer_id, $uidTo, 0, 0)
|
||
|
];
|
||
|
|
||
|
return $result;
|
||
|
}
|
||
|
}
|