feat(calls): VoiceClipModal 只读长语音列表+播放,接入 CallList(微信+WA语音)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
浅念
2026-08-10 18:37:29 +08:00
parent d9060b6920
commit f1b5861b35
4 changed files with 406 additions and 1 deletions
+38
View File
@@ -22,6 +22,7 @@ import type {
SyncRun,
SyncState,
SyncStatus,
VoiceClip,
} from './types'
/** Drop entries whose value is `undefined`, `null`, or `''`. */
@@ -191,6 +192,42 @@ export function getCalls(query: CallQuery = {}): Promise<Page<PhoneCall>> {
)
}
// ---------------------------------------------------------------------------
// Voice clips (长语音片段 — read-only mirror of 云客 /wechatweb/call/list)
// ---------------------------------------------------------------------------
export interface VoiceClipQuery {
/** 员工 userId 精确过滤(modal 从 CallList 行打开时传)。 */
user_id?: string
/** 员工姓名模糊过滤(云客 modal 的「员工姓名」筛选项)。 */
user_real_name?: string
/** 本地通道标记(wechat / whatsapp),非上游筛选。 */
channel?: string
/** ms-epoch inclusive 窗口,与 end_time 比较(录音结束时间)。 */
start?: number
end?: number
/** 企业串码。 */
company_code?: string
page?: number
page_size?: number
}
export function getVoiceClips(query: VoiceClipQuery = {}): Promise<Page<VoiceClip>> {
return getJson<Page<VoiceClip>>(
'/voice-clips',
clean({
user_id: query.user_id,
user_real_name: query.user_real_name,
channel: query.channel,
start: query.start,
end: query.end,
company_code: query.company_code,
page: query.page ?? 1,
page_size: query.page_size ?? 10,
}),
)
}
// ---------------------------------------------------------------------------
// SMS
// ---------------------------------------------------------------------------
@@ -324,4 +361,5 @@ export type {
SyncRun,
SyncState,
SyncStatus,
VoiceClip,
}
+31
View File
@@ -148,6 +148,37 @@ export interface PhoneCall {
raw_json?: Record<string, unknown> | null
}
/**
* Voice clip (长语音片段) row — mirrors backend VoiceClipOut. Source: 云客
* `/wechatweb/call/list`, shared by 微信/WA voice tabs. Read-only in the mirror
* (no matching/ASR yet). `oss_file_name` is the OSS recording URL (played
* directly from the 云客 CDN — see spec §7.3, known 全本地 gap).
*/
export interface VoiceClip {
voice_clip_id: number
user_id: string
user_real_name?: string | null
wx_id?: string | null
talker?: string | null
status?: string | null
is_send?: boolean | null
company_code?: string | null
/** ms-epoch */
start_time?: number | null
/** ms-epoch */
end_time?: number | null
/** OSS recording URL (aliyun OSS 直链). */
oss_file_name?: string | null
/** seconds */
mp3_duration?: number | null
/** `HH:MM:SS` formatted duration from upstream. */
duration_format?: string | null
/** `wechat` / `whatsapp` — local tag set at scrape time (not sent upstream). */
channel: string
/** Verbatim upstream call/list record (camelCase keys). */
raw_json?: Record<string, unknown> | null
}
/** SMS log row (mirrors backend SmsOut). */
export interface Sms {
sms_id: string