| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- <?php
- // +----------------------------------------------------------------------
- // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
- // +----------------------------------------------------------------------
- // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
- // +----------------------------------------------------------------------
- // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
- // +----------------------------------------------------------------------
- // | Author: CRMEB Team <admin@crmeb.com>
- // +----------------------------------------------------------------------
- namespace app\common\repositories\store\service;
- use app\common\dao\store\service\StoreServiceLogDao;
- use app\common\model\store\service\StoreServiceLog;
- use app\common\repositories\BaseRepository;
- use app\common\repositories\store\order\StoreOrderRepository;
- use app\common\repositories\store\order\StoreRefundOrderRepository;
- use app\common\repositories\store\product\ProductGroupRepository;
- use app\common\repositories\store\product\ProductPresellRepository;
- use app\common\repositories\store\product\ProductRepository;
- use think\exception\ValidateException;
- use think\facade\Cache;
- /**
- * 客户用户对话记录
- */
- class StoreServiceLogRepository extends BaseRepository
- {
- /**
- * StoreServiceLogRepository constructor.
- * @param StoreServiceLogDao $dao
- */
- public function __construct(StoreServiceLogDao $dao)
- {
- $this->dao = $dao;
- }
- /**
- * 获取用户列表
- *
- * 本函数用于根据商家ID(merId)、用户ID(uid)、页码(page)和每页数量(limit)
- * 查询用户的详细信息列表。列表数据按照服务日志ID降序排列。
- * 同时,本函数还会处理首次加载时的数据标记读取操作,以更新数据的读取状态。
- * 最后,函数返回包含用户列表数量和详细信息的数据结构。
- *
- * @param string $merId 商家ID,用于限定查询的商家范围
- * @param string $uid 用户ID,用于限定查询的用户范围
- * @param int $page 当前页码,用于分页查询
- * @param int $limit 每页数量,用于分页查询
- * @return array 返回包含用户列表数量和详细信息的数据结构
- */
- public function userList($merId, $uid, $page, $limit)
- {
- // 根据商家ID和用户ID查询符合条件的记录,并按照服务日志ID降序排列
- $query = $this->search(['mer_id' => $merId, 'uid' => $uid])->order('service_log_id DESC');
- // 统计查询结果的总数量
- $count = $query->count();
- // 分页查询用户详细信息,并加载关联数据(用户、服务信息),同时追加发送时间和日期字段
- $list = $query->page($page, $limit)->with(['user', 'service'])->select()->append(['send_time', 'send_date']);
- // 如果是第一页,则标记数据为已读,更新读取状态
- if ($page == 1) {
- $this->dao->userRead($merId, $uid);
- app()->make(StoreServiceUserRepository::class)->read($merId, $uid);
- }
- // 反转列表顺序,可能是为了满足特定的展示需求
- $list = array_reverse($this->getSendDataList($list)->toArray());
- // 返回查询结果的总数量和分页后的用户详细信息列表
- return compact('count', 'list');
- }
- /**
- * 获取服务商列表
- *
- * 本函数用于根据指定的条件获取服务商列表。它首先验证当前用户是否有权限访问指定的服务商,
- * 然后调用内部函数获取满足条件的服务商列表。
- *
- * @param int $merId 商家ID,用于指定要查询的服务商所属的商家。
- * @param int $toUid 接收方用户ID,表示列表是为这个用户展示的。
- * @param int $uid 当前操作的用户ID,用于权限验证和查询条件。
- * @param int $page 当前页码,用于分页查询。
- * @param int $limit 每页记录数,用于分页查询。
- * @return array 返回符合查询条件的服务商列表。
- * @throws ValidateException 如果当前用户无权访问指定的服务商,则抛出异常。
- */
- public function merList($merId, $toUid, $uid, $page, $limit)
- {
- // 通过商家ID和用户ID获取服务商信息,并验证服务商是否存在且处于激活状态
- $service = app()->make(StoreServiceRepository::class)->getService($uid, $merId);
- if (!$service || !$service['status']) {
- throw new ValidateException('没有权限');
- }
- // 调用内部函数获取服务商列表,传入商家ID、服务商ID、接收方用户ID、当前页码和每页记录数
- return $this->serviceList($merId, $service->service_id, $toUid, $page, $limit);
- }
- /**
- * 获取服务列表
- *
- * 根据商家ID、服务ID、接收用户ID、页码和每页数量,查询服务记录。
- * 可选地,可以通过最后一个ID来获取新的服务记录,以实现分页和数据流的无限滚动。
- * 对于第一页的数据查询,会标记服务为已读,以更新用户和商家的服务状态。
- * 返回服务记录的总数和分页后的服务列表。
- *
- * @param string $merId 商家ID
- * @param int $service_id 服务ID
- * @param int $toUid 接收服务的用户ID
- * @param int $page 当前页码
- * @param int $limit 每页数量
- * @param string $last_id 上一次查询的最后一条ID,用于获取新数据
- * @return array 返回包含服务总数和列表的数据数组
- */
- public function serviceList($merId, $service_id, $toUid, $page, $limit, $last_id = '')
- {
- // 根据条件构造查询
- $query = $this->search(['mer_id' => $merId, 'uid' => $toUid, 'last_id' => $last_id])->order('service_log_id DESC');
- // 计算满足条件的服务总数
- $count = $query->count();
- // 执行分页查询,并加载关联数据(用户和服务信息)
- $list = $query->page($page, $limit)->with(['user', 'service'])->select()->append(['send_time', 'send_date']);
- // 如果是第一页,标记服务为已读
- if ($page == 1) {
- $this->dao->serviceRead($merId, $toUid, $service_id);
- app()->make(StoreServiceUserRepository::class)->read($merId, $toUid, true);
- }
- // 反转服务列表顺序,通常用于展示最新的服务在列表顶部
- $list = array_reverse($this->getSendDataList($list)->toArray());
- // 返回服务总数和列表的数组
- return compact('count', 'list');
- }
- /**
- * 根据不同的类型检查MSN的有效性。
- *
- * 该方法用于在不同的业务场景下,验证给定的MSN(可能代表商品ID、订单ID、退款单ID等)是否有效。
- * 通过传入的类型参数来决定检查的逻辑,如果MSN无效,则抛出ValidateException异常。
- *
- * @param string $merId 商家ID,用于限定查询的范围。
- * @param string $uid 用户ID,用于限定查询的范围。
- * @param int $type 类型标识,决定后续检查的逻辑和对应的业务实体。
- * @param string $msn 待检查的MSN,根据类型的不同,可能代表不同的ID。
- * @throws ValidateException 如果MSN无效,则抛出该异常。
- */
- public function checkMsn($merId, $uid, $type, $msn)
- {
- // 检查类型为4时,对应的商品是否存在
- if ($type == 4 && !app()->make(ProductRepository::class)->merExists($merId, $msn))
- throw new ValidateException('商品不存在');
- // 检查类型为5时,对应的订单是否存在
- else if ($type == 5 && !app()->make(StoreOrderRepository::class)->existsWhere(['uid' => $uid, 'mer_id' => $merId, 'order_id' => $msn]))
- throw new ValidateException('订单不存在');
- // 检查类型为6时,对应的退款单是否存在
- else if ($type == 6 && !app()->make(StoreRefundOrderRepository::class)->existsWhere(['uid' => $uid, 'mer_id' => $merId, 'refund_order_id' => $msn]))
- throw new ValidateException('退款单不存在');
- // 检查类型为7时,对应的预售商品是否存在
- else if ($type == 7 && !app()->make(ProductPresellRepository::class)->existsWhere(['product_presell_id' => $msn, 'mer_id' => $merId]))
- throw new ValidateException('商品不存在');
- // 检查类型为8时,对应的拼团商品是否存在
- else if ($type == 8 && !app()->make(ProductGroupRepository::class)->existsWhere(['product_group_id' => $msn, 'mer_id' => $merId]))
- throw new ValidateException('商品不存在');
- }
- /**
- * 根据日志的类型获取相应的发送数据。
- *
- * 本函数旨在根据服务日志中记录的不同类型(msn_type),提取出相应的数据。
- * msn_type 的不同值对应着不同的数据对象,包括产品、订单、退款订单、预售和产品组等信息。
- * 通过判断日志的类型,直接返回对应类型的数据对象,便于后续处理和使用。
- *
- * @param StoreServiceLog $log 服务日志对象,包含各种类型的数据信息。
- * @return StoreServiceLog 返回经过筛选后的服务日志对象,数据对象根据日志类型有所不同。
- */
- public function getSendData(StoreServiceLog $log)
- {
- // 根据日志的类型,提取相应的数据对象
- if ($log->msn_type == 4) {
- $log->product;
- } else if ($log->msn_type == 5) {
- $log->orderInfo;
- } else if ($log->msn_type == 6) {
- $log->refundOrder;
- } else if ($log->msn_type == 7) {
- $log->presell;
- } else if ($log->msn_type == 8) {
- $log->productGroup;
- }
- return $log;
- }
- /**
- * 根据日志列表中的MSN类型和号码,将相关数据存储在缓存中,以减少重复数据的存储。
- * 对于特定类型的日志,将其相关数据设置到日志对象中。
- *
- * @param array $list 日志对象的列表。
- * @return array 处理后的日志对象列表。
- */
- public function getSendDataList($list)
- {
- // 初始化缓存数组,用于存储按MSN类型和号码组合的唯一数据。
- $cache = [];
- foreach ($list as $log) {
- // 忽略非指定类型的日志,以减少后续处理的负担。
- if (!in_array($log->msn_type, [4, 5, 6, 7, 8])) continue;
- // 创建键,用于根据MSN类型和号码查找缓存数据。
- $key = $log->msn_type . $log->msn;
- // 如果缓存中已存在该键的数据,则直接从缓存中获取数据并设置到日志对象中。
- if (isset($cache[$key])) {
- if ($log->msn_type == 4)
- $log->set('product', $cache[$key]);
- else if ($log->msn_type == 5)
- $log->set('orderInfo', $cache[$key]);
- else if ($log->msn_type == 6)
- $log->set('refundOrder', $cache[$key]);
- else if ($log->msn_type == 8)
- $log->set('productGroup', $cache[$key]);
- else
- $log->set('presell', $cache[$key]);
- } else {
- // 如果缓存中不存在该键的数据,则从日志对象中获取数据并存储到缓存中。
- if ($log->msn_type == 4)
- $cache[$key] = $log->product;
- else if ($log->msn_type == 5)
- $cache[$key] = $log->orderInfo;
- else if ($log->msn_type == 6)
- $cache[$key] = $log->refundOrder;
- else if ($log->msn_type == 8)
- $cache[$key] = $log->productGroup;
- else
- $cache[$key] = $log->presell;
- }
- }
- return $list;
- }
- /**
- * 根据用户ID和是否为服务聊天获取聊天记录
- *
- * 本函数用于从缓存中获取指定用户的聊天记录。它可以根据用户是否是服务聊天来选择不同的缓存键,
- * 这样可以区分普通用户聊天记录和服务聊天记录,避免混淆。
- *
- * @param int $uid 用户ID,用于指定要获取聊天记录的用户。
- * @param bool $isService 指示是否为服务聊天,用于区分普通聊天和服务聊天。
- * @return mixed 返回从缓存中获取的聊天记录,如果不存在则返回null。
- */
- public function getChat($uid, $isService = false)
- {
- // 根据$isService的值决定缓存键的前缀,如果是服务聊天则为's_chat',否则为'u_chat'。
- // 然后拼接上$uid作为完整的缓存键。
- $key = ($isService ? 's_chat' : 'u_chat') . $uid;
- // 使用Cache类的get方法尝试获取缓存中存储的聊天记录。
- return Cache::get($key);
- }
- /**
- * 获取某个客服的用户列表
- * @param $service_id
- * @param $page
- * @param $limit
- * @return array
- * @author Qinii
- * @day 2020-06-18
- */
- public function getServiceUserList($service_id, $page, $limit)
- {
- $query = $this->dao->getUserListQuery($service_id)->with(['user'])->group('uid');
- $count = $query->count();
- $list = $query->setOption('field', [])->field('uid,mer_id,create_time,type')
- ->page($page, $limit)
- ->select();
- return compact('count', 'list');
- }
- /**
- * 获取商户的聊天用户列表
- * @param $merId
- * @param $page
- * @param $limit
- * @return array
- * @author Qinii
- * @day 2020-06-19
- */
- public function getMerchantUserList($merId, $page, $limit)
- {
- $query = $this->dao->getMerchantUserList($merId)->with(['user'])->group('uid');
- $count = $query->count();
- $list = $query->setOption('field', [])->field('uid,mer_id,create_time,type')->page($page, $limit)->select();
- return compact('count', 'list');
- }
- /**
- * 根据用户ID和条件获取用户的MSN信息
- *
- * 本函数用于查询指定用户ID的MSN相关信息。支持根据商家ID和服務ID进行过滤查询,
- * 提供分页功能,以满足前端或业务需求的分批获取数据。
- *
- * @param int $uid 用户ID,用于指定查询哪个用户的MSN信息。
- * @param string $page 分页参数,指定当前页码。
- * @param string $limit 分页参数,指定每页显示的记录数。
- * @param int|null $merId 商家ID,可选参数,用于过滤属于特定商家的MSN信息。
- * @param int|null $serviceId 服务ID,可选参数,用于过滤属于特定服务的MSN信息。
- * @return array 返回包含记录总数和用户MSN信息列表的数组。
- */
- public function getUserMsn(int $uid, $page, $limit, ?int $merId = null, ?int $serviceId = null)
- {
- // 初始化查询条件
- $where['uid'] = $uid;
- // 如果提供了商家ID,则添加到查询条件中
- if ($merId) $where['mer_id'] = $merId;
- // 如果提供了服务ID,则添加到查询条件中
- if ($serviceId) $where['service_id'] = $serviceId;
- // 构建查询对象,并设置排序方式
- $query = $this->search($where)->order('service_log_id DESC');
- // 计算符合条件的记录总数
- $count = $query->count();
- // 执行分页查询,并加载关联数据(用户、服务信息)以及附加MSN信息
- $list = $query->page($page, $limit)->with(['user', 'service'])->append(['msn_info'])->select();
- // 返回记录总数和查询结果列表
- return compact('count', 'list');
- }
- }
|