From 05cc1dfcc4449565c87d1a8739c264c33fab773b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Fri, 7 Aug 2026 16:55:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(calls):=20=E5=89=8D=E7=AB=AF=E5=BD=95?= =?UTF-8?q?=E9=9F=B3=E6=92=AD=E6=94=BE=E6=9C=AC=E5=9C=B0=E4=BC=98=E5=85=88?= =?UTF-8?q?(/api/media/{hash})=20+=20OSS=20=E5=9B=9E=E9=80=80=20+=20drawer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude --- yunkes/src/api/types.ts | 2 ++ yunkes/src/utils/callFields.ts | 8 ++++++++ yunkes/src/views/CallList.vue | 13 +++++++------ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/yunkes/src/api/types.ts b/yunkes/src/api/types.ts index ce49ede..e76c648 100644 --- a/yunkes/src/api/types.ts +++ b/yunkes/src/api/types.ts @@ -136,6 +136,8 @@ export interface PhoneCall { sim_phone?: string | null /** OSS URL of the recording — present only when a recording exists. */ record_file?: string | null + /** sha256 media_hash of the localized recording (NULL until downloaded). */ + record_media_hash?: string | null /** * Verbatim upstream call record (camelCase keys: id/startCallTime, * callDuration/callSeconds/ringTime, callStatus/incomingCall, userId/ diff --git a/yunkes/src/utils/callFields.ts b/yunkes/src/utils/callFields.ts index b8cbddc..79c0338 100644 --- a/yunkes/src/utils/callFields.ts +++ b/yunkes/src/utils/callFields.ts @@ -211,6 +211,14 @@ export function toDisplayField(c: PhoneCall, camelKey: string): DisplayField { if (value === null || value === undefined || value === '') { return { key: camelKey, label, value, render: 'empty', text: '' } } + // 录音:优先本地化的 media_hash(/api/media/{hash}),否则原 OSS URL + if (camelKey === 'recordFile') { + const local = c.record_media_hash ? `/api/media/${c.record_media_hash}` : null + const url = local ?? (typeof value === 'string' && value ? value : null) + if (url) { + return { key: camelKey, label, value: url, render: 'audio', text: '' } + } + } if (AUDIO_KEYS.has(camelKey) && typeof value === 'string') { return { key: camelKey, label, value, render: 'audio', text: '' } } diff --git a/yunkes/src/views/CallList.vue b/yunkes/src/views/CallList.vue index 6177988..07513ab 100644 --- a/yunkes/src/views/CallList.vue +++ b/yunkes/src/views/CallList.vue @@ -90,10 +90,11 @@ function timeCell(row: PhoneCall, camelKey: string): number | undefined { } function playRecord(row: PhoneCall): void { + const local = row.record_media_hash ? `/api/media/${row.record_media_hash}` : null const file = - (typeof cell(row, 'recordFile') === 'string' - ? (cell(row, 'recordFile') as string) - : null) ?? row.record_file + local ?? + (typeof cell(row, 'recordFile') === 'string' ? (cell(row, 'recordFile') as string) : null) ?? + row.record_file if (!file) { ElMessage.info('该通话无录音文件') return @@ -185,7 +186,7 @@ onMounted(load) @@ -215,7 +216,7 @@ onMounted(load) @@ -251,7 +252,7 @@ onMounted(load)