feat(api): GET /api/staff-stats 7类计数+分型明细(voice走user_id join,新客户add_time兜底,红包金额提取)
计数模式(无kind)返回 new_customers/new_groups/red_transfer/del_customers/
blocked_customers/voice_calls/sensitive_words(恒0,spec占位);明细模式
(?kind=)返回{kind,rows},每kind字段不同,前端按kind配列。start/end
缺省近7天。
口径(spec §4.5,全本地聚合):
- new_customers: add_time窗内;IS NULL行用该对话首条消息min(timestamp)兜底
- new_groups: chat_group.create_time窗内(复合PK按owner过滤)
- red_transfer: wechat type IN (red_packet,transfer)窗内;金额三路正则
(红包XML feedesc/转账纯文本/totalamount),实测真库转账399/399全提取
- del/blocked_customers: 现存量口径忽略窗口,明细time=updated_at毫秒
- voice_calls: phone_call.user_id存员工userId(32HEX)非wxId——先经
wechat_account.user_id换算,账号无uid返回空防跨员工串数
- voice明细字段语义对齐CallList.vue(connected=call_status==1,
media_url本地/api/media/{hash}优先OSS兜底)
真机smoke(yunke-mysql):voice 61条/新客67/删除29/拉黑1均通过;
转账金额100%提取。真库chat_group列与message.type回填滞后(运维项,另报)。
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -403,6 +403,39 @@ class StaffChatStatsOut(BaseModel):
|
||||
customers: list[StaffChatCustomerOut]
|
||||
|
||||
|
||||
class StaffStatsCountsOut(BaseModel):
|
||||
"""GET /api/staff-stats 计数模式(无 kind)——云客员工聊天窗口 7 类汇总数字。
|
||||
|
||||
口径见 :mod:`app.api.routers.staff_stats`(spec §4.5):new_customers 含
|
||||
「首条消息时间」兜底;del/blocked 是现存量(不受窗口约束);voice_calls
|
||||
走 wechat_account.user_id 换算。``sensitive_words`` 为敏感词占位,恒 0。
|
||||
"""
|
||||
|
||||
new_customers: int
|
||||
new_groups: int
|
||||
red_transfer: int
|
||||
del_customers: int
|
||||
blocked_customers: int
|
||||
voice_calls: int
|
||||
sensitive_words: int = 0
|
||||
|
||||
|
||||
class StaffStatsDetailOut(BaseModel):
|
||||
"""GET /api/staff-stats 明细模式(``?kind=``)——rows 字段随 kind 不同。
|
||||
|
||||
统一 ``list[dict]``,前端按 kind 配置列(字段清单见 router docstring):
|
||||
new_customers {talker_id, nickname, avatar, remark, time} /
|
||||
new_groups {room_id, room_name, time} /
|
||||
red_transfer {op_type, talker_id, room_id, nickname, amount, time, msg_id} /
|
||||
del|blocked_customers {talker_id, nickname, time} /
|
||||
voice_calls {id, peer, incoming, connected, duration, start_time, media_url}
|
||||
(语义对齐 CallList.vue / PhoneCallOut)。
|
||||
"""
|
||||
|
||||
kind: str
|
||||
rows: list[dict[str, Any]]
|
||||
|
||||
|
||||
class SessionOut(BaseModel):
|
||||
"""账号会话列表的一行(好友或群)。"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user