feat: full-field display for message/staff/accounts (raw_json + drawers)
Replicates the Customer all-fields pattern across the remaining three entities. Backend now exposes `raw_json` on MessageOut / StaffOut / AccountOut so the frontend can render every 云客 source field without a second endpoint. Each entity gains a Chinese-label field utility + an el-drawer surfacing all fields (structured-first, raw_json fallback, unknown keys under 其他). Backend: - schemas.py: add `raw_json: dict | None` to MessageOut / StaffOut / AccountOut. MessageOut/StaffOut pick the column up via from_attributes; AccountOut is built explicitly in the router, which now threads `raw_json` through from both WechatAccount and WhatsappAccount rows. - tests: new raw_json serialization tests for messages, staff, accounts (assert populated dict round-trips verbatim + NULL serializes as null). Frontend (yunkes/): - New utils: messageFields.ts, staffFields.ts, accountFields.ts — each with a 中文 label map, ordered groups, structured-column preference, and an 其他 fallback for unknown raw_json keys. - Message: clicking a chat bubble opens an all-fields drawer (referMsg renders as pretty-printed JSON). Image preview + file download links stopPropagation so their own interactions still work. - Staff: row click → drawer; columns relabeled (员工ID, 销售手机). - Accounts: new AccountList.vue at /accounts with a 账号 nav item, unified WeChat/WhatsApp table (渠道/账号ID/昵称/微信号/归属员工/好友数/ 群数/收发/在职/最后更新), channel filter, pagination, row-click drawer. - api: add Account type + getAccounts(); add raw_json to Message/Staff. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
// (the backend treats missing as "no filter").
|
||||
import { getJson } from './client'
|
||||
import type {
|
||||
Account,
|
||||
CallChannel,
|
||||
Channel,
|
||||
Customer,
|
||||
@@ -102,6 +103,24 @@ export function getStaff(query: StaffQuery = {}): Promise<Page<Staff>> {
|
||||
)
|
||||
}
|
||||
|
||||
export interface AccountQuery {
|
||||
/** channel filter; `'all'` (default) drops the param so both channels union. */
|
||||
channel?: Channel | 'all'
|
||||
page?: number
|
||||
page_size?: number
|
||||
}
|
||||
|
||||
export function getAccounts(query: AccountQuery = {}): Promise<Page<Account>> {
|
||||
return getJson<Page<Account>>(
|
||||
'/accounts',
|
||||
clean({
|
||||
channel: query.channel === 'all' ? undefined : query.channel,
|
||||
page: query.page ?? 1,
|
||||
page_size: query.page_size ?? 20,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Chat groups
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -197,6 +216,7 @@ export function getSyncStatus(): Promise<SyncStatus> {
|
||||
}
|
||||
|
||||
export type {
|
||||
Account,
|
||||
CallChannel,
|
||||
Channel,
|
||||
Customer,
|
||||
|
||||
@@ -55,6 +55,30 @@ export interface Staff {
|
||||
sale_phone?: string | null
|
||||
dept_id?: string | null
|
||||
is_on_job?: boolean | null
|
||||
/**
|
||||
* Verbatim upstream staff record (camelCase keys). Surfaced so the
|
||||
* all-fields drawer can render every column without enumerating each.
|
||||
*/
|
||||
raw_json?: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
/**
|
||||
* Unified staff messaging account (mirrors backend AccountOut). The two source
|
||||
* tables (wechat_account / whatsapp_account) are projected onto this single
|
||||
* shape keyed by `channel` + `account_id`. `raw_json` carries the verbatim
|
||||
* upstream record (wechatId/alias/sendNum/receiveNum/dbSize/...).
|
||||
*/
|
||||
export interface Account {
|
||||
channel: Channel
|
||||
account_id: string
|
||||
nickname?: string | null
|
||||
user_id?: string | null
|
||||
user_name?: string | null
|
||||
phone?: string | null
|
||||
contacts_num?: number | null
|
||||
group_num?: number | null
|
||||
is_on_job?: boolean | null
|
||||
raw_json?: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
/** Chat group summary row (mirrors backend GroupOut). */
|
||||
@@ -187,4 +211,11 @@ export interface Message {
|
||||
/** ms-epoch */
|
||||
timestamp?: number | null
|
||||
is_del?: boolean | null
|
||||
/**
|
||||
* Verbatim upstream message record (camelCase keys: msgSvrId/keyId, type,
|
||||
* file/fileTh/fileHd, md5/md5Th/md5Hd, paymsgid, referMsg, talker/oriTalker,
|
||||
* name/headUrl, wechatId, roomid, ...). Surfaced so the all-fields drawer
|
||||
* can render every column the 云客 chat detail page shows.
|
||||
*/
|
||||
raw_json?: Record<string, unknown> | null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user