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,
|
||||
|
||||
Reference in New Issue
Block a user