fix(groups): 微信群排序复刻云客+群详情去掉重复的「成员列表」字段

用户报:①群详情有成员墙后「成员列表」原始串字段重复;②排序与云客不一致。

- 排序:云客「微信群统计」真机判别=员工分组(云客员工列表序)+
  组内 chatRoomId 字符串升序——/api/groups 微信路径改 JOIN
  wechat_account 按 list_order(NULL 垫底按 owner asc)+room_id asc;
  WA 保持最近活跃优先
- 群详情:memberIds 从「其他字段」兜底区排除(成员墙已替代,不再
  以原始 wxid 串重复出现)

726 测试绿(默认排序断言更新为员工分组序)。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-10 14:11:13 +08:00
parent e00d399195
commit 253be99eca
3 changed files with 37 additions and 11 deletions
+26 -7
View File
@@ -101,14 +101,33 @@ async def list_groups(
list_stmt = sa.select(ChatGroup)
if conditions:
list_stmt = list_stmt.where(*conditions)
list_stmt = (
list_stmt.order_by(
sa.nullslast(ChatGroup.last_chat_time.desc()),
ChatGroup.room_id.asc(),
if (channel or "wechat") == "wechat":
# 云客「微信群统计」同款排序(2026-09-10 真机判别):员工分组——
# 按云客员工列表序(wechat_account.list_order,NULL 垫底按 wx_id)、
# 组内按 room_id(chatRoomId)字符串升序。WA 保持最近活跃优先。
list_stmt = (
list_stmt.outerjoin(
WechatAccount,
WechatAccount.wx_id == ChatGroup.owner_account_id,
)
.order_by(
WechatAccount.list_order.is_(None),
WechatAccount.list_order.asc(),
ChatGroup.owner_account_id.asc(),
ChatGroup.room_id.asc(),
)
.limit(page_size)
.offset((page - 1) * page_size)
)
else:
list_stmt = (
list_stmt.order_by(
sa.nullslast(ChatGroup.last_chat_time.desc()),
ChatGroup.room_id.asc(),
)
.limit(page_size)
.offset((page - 1) * page_size)
)
.limit(page_size)
.offset((page - 1) * page_size)
)
rows = (await session.execute(list_stmt)).scalars().all()
# ---- 员工微信/员工信息列(wechat_account/staff 关联,本页行集) ----
+6 -3
View File
@@ -64,17 +64,20 @@ async def _seed(session: AsyncSession) -> None:
async def test_default_list_returns_all_ordered_desc(make_client):
"""No filters -> 3 groups, ordered by ``last_chat_time desc`` (nulls last)."""
"""No filters -> 3 groups;微信排序=员工分组(list_order NULL 按 owner asc)
+组内 room_id 字符串升序(云客群统计同款,2026-09-10)。
seed 无 wechat_account 行 → list_order 全 NULL → owner 字符串序:
wa_owner_1 < wx_owner_1 < wx_owner_2 → [wa_room_x, room_a, room_b]。
"""
client = await make_client(_seed)
r = await client.get("/api/groups")
assert r.status_code == 200
body = r.json()
assert body["total"] == 3
# 2000, 1000, null -> [room_a, room_b, wa_room_x]
assert [it["room_id"] for it in body["items"]] == [
"wa_room_x@s.whatsapp.net",
"room_a@chatroom",
"room_b@chatroom",
"wa_room_x@s.whatsapp.net",
]
for key in (
"room_id",
+5 -1
View File
@@ -105,7 +105,11 @@ export const GROUP_FIELD_GROUPS: GroupFieldGroup[] = [
]
/** Every key already surfaced via a group (so 其他 can skip duplicates). */
const KNOWN_KEYS = new Set(GROUP_FIELD_GROUPS.flatMap((g) => g.keys))
const KNOWN_KEYS = new Set([
...GROUP_FIELD_GROUPS.flatMap((g) => g.keys),
// 原始 wxid 串由群详情成员墙替代,不在任何区(含「其他」)显示(2026-09-10)
'memberIds',
])
/** Resolve the 中文 label for a raw_json key (falls back to the key). */
export function fieldLabel(key: string): string {