fix(export+calls): 同类owner错位问题全面修复(群导出不按owner过滤+群语音客户点击走群聊路由)
- /api/export/chat-html: room 查询忽略 owner(chat_group owner 错位同 ChatTimeline,群列表/聊天页的导出按钮原来会导出空文件) - CallList viewCallCustomer: talker 以 @chatroom 结尾→group-chat 路由 (原走 1:1 路由按 talker_id 查@chatroom 恒空) - TDD: 群消息在 ownerB 名下用 ownerA+room 导出仍能拿到;428 测试绿 - 实测:错位 owner 导出 43304 群返回 15002 个消息元素 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -128,21 +128,22 @@ async def export_chat_html(
|
||||
start: Annotated[int | None, Query(ge=0)] = None,
|
||||
end: Annotated[int | None, Query(ge=0)] = None,
|
||||
) -> Response:
|
||||
q = (
|
||||
sa.select(Message)
|
||||
.where(Message.channel == channel)
|
||||
.where(Message.owner_account_id == owner_account_id)
|
||||
)
|
||||
# 群聊(room_id)不按 owner 过滤:chat_group 表按 room 去重、owner 被末位
|
||||
# 员工覆盖,与消息实际归属 owner 错位会导出空文件(同 ChatTimeline 修复,
|
||||
# 2026-08-22);room 全局唯一且消息只在单一 owner 名下。
|
||||
q = sa.select(Message).where(Message.channel == channel)
|
||||
peer = ""
|
||||
if room_id:
|
||||
q = q.where(Message.room_id == room_id)
|
||||
peer = room_id
|
||||
elif talker_id:
|
||||
# DM:限定 room_id 为空,避免误捞群消息
|
||||
q = q.where(Message.talker_id == talker_id).where(
|
||||
(Message.room_id == None) | (Message.room_id == "") # noqa: E711
|
||||
)
|
||||
peer = talker_id
|
||||
else:
|
||||
q = q.where(Message.owner_account_id == owner_account_id)
|
||||
if talker_id:
|
||||
# DM:限定 room_id 为空,避免误捞群消息
|
||||
q = q.where(Message.talker_id == talker_id).where(
|
||||
(Message.room_id == None) | (Message.room_id == "") # noqa: E711
|
||||
)
|
||||
peer = talker_id
|
||||
if start is not None:
|
||||
q = q.where(Message.timestamp >= start)
|
||||
if end is not None:
|
||||
|
||||
@@ -137,3 +137,26 @@ async def test_export_no_warning_below_cap(make_client):
|
||||
assert r.status_code == 200
|
||||
# No warning DIV (the CSS class still lives in <style> — that's fine).
|
||||
assert '<div class="export-warning">' not in r.text
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 群导出 owner 错位修复(2026-08-22): room 查询不带 owner
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
async def test_export_group_ignores_owner_mismatch(make_client):
|
||||
"""群消息在 owner B 名下,用 owner A + room 导出仍能拿到(不按 owner 过滤)。"""
|
||||
from app.db.models import Customer as _C # noqa: F401 (对齐既有 seed 风格)
|
||||
|
||||
async def seed(session):
|
||||
session.add_all([
|
||||
Message(msg_id="gm1", channel="wechat", owner_account_id="ownerB", talker_id=None, room_id="gX@chatroom", text="群消息1", timestamp=100),
|
||||
Message(msg_id="gm2", channel="wechat", owner_account_id="ownerB", talker_id=None, room_id="gX@chatroom", text="群消息2", timestamp=200),
|
||||
])
|
||||
await session.commit()
|
||||
|
||||
client = await make_client(seed)
|
||||
r = await client.get("/api/export/chat-html", params={
|
||||
"channel": "wechat", "owner_account_id": "ownerA", "room_id": "gX@chatroom"})
|
||||
assert r.status_code == 200
|
||||
assert "群消息1" in r.text
|
||||
assert "群消息2" in r.text
|
||||
|
||||
@@ -249,12 +249,27 @@ function viewCallCustomer(row: PhoneCall): void {
|
||||
const owner = cell(row, 'weChatId')
|
||||
const talker = cell(row, 'talker')
|
||||
if (!owner || !talker) return
|
||||
const t = String(talker)
|
||||
// 群语音的 talker 是 @chatroom ID → 走群聊路由(1:1 路由按 talker_id 查会
|
||||
// 查空,同 chat_group owner 错位类问题,2026-08-22)
|
||||
if (t.endsWith('@chatroom')) {
|
||||
router.push({
|
||||
name: 'group-chat',
|
||||
params: {
|
||||
channel: chatChannel(row.channel) ?? 'wechat',
|
||||
ownerId: String(owner),
|
||||
roomId: t,
|
||||
},
|
||||
query: row.start_call_time ? { start: String(row.start_call_time) } : undefined,
|
||||
})
|
||||
return
|
||||
}
|
||||
router.push({
|
||||
name: 'chat',
|
||||
params: {
|
||||
channel: chatChannel(row.channel) ?? 'wechat',
|
||||
ownerId: String(owner),
|
||||
talkerId: String(talker),
|
||||
talkerId: t,
|
||||
},
|
||||
// 对齐云客:带通话时间定位(?start=),聊天窗滚动到该通通话附近
|
||||
query: row.start_call_time ? { start: String(row.start_call_time) } : undefined,
|
||||
|
||||
Reference in New Issue
Block a user