Files
zyt/server/app/adminapi/lists/qywx/MsgArchiveLists.php
T
2026-04-21 09:49:44 +08:00

160 lines
5.4 KiB
PHP

<?php
declare(strict_types=1);
namespace app\adminapi\lists\qywx;
use app\adminapi\lists\BaseAdminDataLists;
use app\common\lists\ListsSearchInterface;
use app\common\model\auth\Admin;
use app\common\model\QywxExternalContact;
use app\common\model\QywxMsgArchive;
use app\common\model\QywxMsgArchiveMedia;
/**
* 单会话消息历史
*
* 两种查询模式,二选一:
* 1) session_id 传 QywxMsgSession.id(推荐)
* 2) staff_userid + external_userid(单聊)/ roomid(群聊)
*
* 消息默认按 send_time 升序,便于前端从下往上追加。
* 支持 before_time / after_time 游标翻页。
*/
class MsgArchiveLists extends BaseAdminDataLists implements ListsSearchInterface
{
public function setSearch(): array
{
return [
'=' => ['roomid', 'msgtype'],
];
}
private function resolveScope(): array
{
$sessionId = (int) ($this->params['session_id'] ?? 0);
if ($sessionId > 0) {
$session = \app\common\model\QywxMsgSession::find($sessionId);
if ($session) {
return [
'staff_userid' => (string) $session['staff_userid'],
'external_userid' => (string) $session['external_userid'],
'roomid' => (string) $session['roomid'],
];
}
}
return [
'staff_userid' => trim((string) ($this->params['staff_userid'] ?? '')),
'external_userid' => trim((string) ($this->params['external_userid'] ?? '')),
'roomid' => trim((string) ($this->params['roomid'] ?? '')),
];
}
private function baseQuery()
{
$scope = $this->resolveScope();
$query = QywxMsgArchive::where($this->searchWhere);
if ($scope['roomid'] !== '') {
$query->where('roomid', $scope['roomid']);
} else {
// 单聊:两端顺序不定,from_user/tolist 都可能为员工或客户
$staff = $scope['staff_userid'];
$external = $scope['external_userid'];
if ($staff === '' && $external === '') {
$query->where('id', 0);
} else {
$query->where('roomid', '');
if ($staff !== '' && $external !== '') {
$query->where(function ($q) use ($staff, $external) {
$q->where(function ($sub) use ($staff, $external) {
$sub->where('from_user', $staff)->whereLike('to_list', '%"' . $external . '"%');
})->whereOr(function ($sub) use ($staff, $external) {
$sub->where('from_user', $external)->whereLike('to_list', '%"' . $staff . '"%');
});
});
} elseif ($staff !== '') {
$query->where(function ($q) use ($staff) {
$q->where('from_user', $staff)->whereOr('to_list', 'like', '%"' . $staff . '"%');
});
} else {
$query->where(function ($q) use ($external) {
$q->where('from_user', $external)->whereOr('to_list', 'like', '%"' . $external . '"%');
});
}
}
}
if (!empty($this->params['before_time'])) {
$query->where('send_time', '<', (int) $this->params['before_time']);
}
if (!empty($this->params['after_time'])) {
$query->where('send_time', '>', (int) $this->params['after_time']);
}
return $query;
}
public function lists(): array
{
$rows = $this->baseQuery()
->order('send_time', 'desc')
->order('id', 'desc')
->limit($this->limitOffset, $this->limitLength)
->select()
->toArray();
if (empty($rows)) {
return [];
}
$rows = array_reverse($rows); // 前端按时间升序渲染
$users = [];
foreach ($rows as $r) {
$users[$r['from_user']] = true;
$toList = $r['to_list'];
if (is_array($toList)) {
foreach ($toList as $to) {
$users[$to] = true;
}
}
}
$users = array_keys(array_filter($users, fn ($_, $k) => $k !== '', ARRAY_FILTER_USE_BOTH));
$adminMap = [];
$extMap = [];
if ($users) {
$adminMap = Admin::whereIn('work_wechat_userid', $users)
->column('id,name,avatar,work_wechat_userid', 'work_wechat_userid');
$extMap = QywxExternalContact::whereIn('external_userid', $users)
->column('external_userid,name,avatar,type,unionid', 'external_userid');
}
$msgIds = array_column($rows, 'msgid');
$mediaMap = [];
if ($msgIds) {
$mediaList = QywxMsgArchiveMedia::whereIn('msgid', $msgIds)->select()->toArray();
foreach ($mediaList as $m) {
$mediaMap[$m['msgid']][] = $m;
}
}
foreach ($rows as &$r) {
$fromId = (string) $r['from_user'];
$r['from_is_staff'] = isset($adminMap[$fromId]);
$r['from_profile'] = $adminMap[$fromId] ?? ($extMap[$fromId] ?? null);
$r['media'] = $mediaMap[$r['msgid']] ?? [];
}
unset($r);
return $rows;
}
public function count(): int
{
return $this->baseQuery()->count();
}
}