feat(calls): 语音通话列表列布局全面对齐云客(头像/多行标签/结束时间/时长格式)
- 客户信息/员工微信列:加头像+微信号用脱敏alias+客户加备注名 - 通话信息:改多行标签式(状态/微信语音/来源),去「xx:」前缀 - 员工信息:改纯文本(云客不可点) - 通话录音:接通时显示时长+播放 - 通话时长列:显示endTime+MM'SS"格式 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -254,6 +254,20 @@ const staffDrawerSections = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
/** 把通话类型(voice_call/wa_voice_call)映射到聊天渠道(wechat/whatsapp)。电话返回 null。 */
|
/** 把通话类型(voice_call/wa_voice_call)映射到聊天渠道(wechat/whatsapp)。电话返回 null。 */
|
||||||
|
function callSourceText(row: PhoneCall): string {
|
||||||
|
const v = cell(row, 'callFrom') ?? cell(row, 'dataFrom')
|
||||||
|
if (v === 1 || v === '1') return '手机'
|
||||||
|
return '--'
|
||||||
|
}
|
||||||
|
|
||||||
|
function callDurationText(row: PhoneCall): string {
|
||||||
|
const sec = row.call_duration ?? 0
|
||||||
|
if (!sec) return '--'
|
||||||
|
const m = Math.floor(sec / 60)
|
||||||
|
const s = sec % 60
|
||||||
|
return `${String(m).padStart(2, '0')}'${String(s).padStart(2, '0')}"'
|
||||||
|
}
|
||||||
|
|
||||||
function chatChannel(ch: CallChannel): 'wechat' | 'whatsapp' | null {
|
function chatChannel(ch: CallChannel): 'wechat' | 'whatsapp' | null {
|
||||||
return ch === 'voice_call' ? 'wechat' : ch === 'wa_voice_call' ? 'whatsapp' : null
|
return ch === 'voice_call' ? 'wechat' : ch === 'wa_voice_call' ? 'whatsapp' : null
|
||||||
}
|
}
|
||||||
@@ -398,52 +412,67 @@ onMounted(() => {
|
|||||||
@row-click="openDrawer"
|
@row-click="openDrawer"
|
||||||
>
|
>
|
||||||
<template v-if="callType === 'voice_call'">
|
<template v-if="callType === 'voice_call'">
|
||||||
<el-table-column label="通话信息" min-width="150">
|
<el-table-column label="通话信息" min-width="140">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div>通话状态:{{ callStatusLabel(row.call_status, row.channel) }}</div>
|
<div>{{ callStatusLabel(row.call_status, row.channel) }}</div>
|
||||||
<div class="yk-cell__sub">类型:{{ callTypeLabel(row.channel) }}</div>
|
<div class="yk-cell__sub">微信语音</div>
|
||||||
<div class="yk-cell__sub">来源:{{ cell(row, 'from') || '--' }}</div>
|
<div class="yk-cell__sub">{{ callSourceText(row) }}</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 客户信息(好友 scope) / 群信息(群 scope) — 云客微信好友/微信群两 tab 各自的列 -->
|
<el-table-column :label="voiceScope === 'group' ? '群信息' : '客户信息'" min-width="180">
|
||||||
<el-table-column :label="voiceScope === 'group' ? '群信息' : '客户信息'" min-width="150">
|
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<template v-if="voiceScope === 'group'">
|
<template v-if="voiceScope === 'group'">
|
||||||
<div>{{ cell(row, 'roomName') || cell(row, 'talker') || '--' }}</div>
|
<div>{{ cell(row, 'roomName') || cell(row, 'talker') || '--' }}</div>
|
||||||
<div class="yk-cell__sub">{{ cell(row, 'roomId') || '--' }}</div>
|
<div class="yk-cell__sub">{{ cell(row, 'roomId') || '--' }}</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-button v-if="cell(row, 'talkerNickName')" link type="primary" size="small" @click.stop="viewCallCustomer(row)">{{ cell(row, 'talkerNickName') }}</el-button>
|
<div class="yk-call-person">
|
||||||
<span v-else>--</span>
|
<el-avatar v-if="cell(row, 'talkerHeadImg')" :size="32" :src="String(cell(row, 'talkerHeadImg'))" shape="square" />
|
||||||
<div class="yk-cell__sub">{{ row.call_number || cell(row, 'talker') || '--' }}</div>
|
<div class="yk-call-person__meta">
|
||||||
|
<el-button v-if="cell(row, 'talkerNickName')" link type="primary" size="small" @click.stop="viewCallCustomer(row)">{{ cell(row, 'talkerNickName') }}</el-button>
|
||||||
|
<span v-else>--</span>
|
||||||
|
<div class="yk-cell__sub">{{ cell(row, 'talkerAlias') || cell(row, 'talker') || '--' }}</div>
|
||||||
|
<div v-if="cell(row, 'friendRemark')" class="yk-cell__sub">备注名 {{ cell(row, 'friendRemark') }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="员工微信" min-width="150">
|
<el-table-column label="员工微信" min-width="180">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button v-if="cell(row, 'userWeChatNickName')" link type="primary" size="small" @click.stop="viewCallStaff(row)">{{ cell(row, 'userWeChatNickName') }}</el-button>
|
<div class="yk-call-person">
|
||||||
<span v-else>--</span>
|
<el-avatar v-if="cell(row, 'userWeChatHeadImg')" :size="32" :src="String(cell(row, 'userWeChatHeadImg'))" shape="square" />
|
||||||
<div class="yk-cell__sub">{{ cell(row, 'userWeChatAlias') || cell(row, 'weChatId') || '--' }}</div>
|
<div class="yk-call-person__meta">
|
||||||
|
<el-button v-if="cell(row, 'userWeChatNickName')" link type="primary" size="small" @click.stop="viewCallStaff(row)">{{ cell(row, 'userWeChatNickName') }}</el-button>
|
||||||
|
<span v-else>--</span>
|
||||||
|
<div class="yk-cell__sub">{{ cell(row, 'userWeChatAlias') || cell(row, 'weChatId') || '--' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="员工信息" min-width="130">
|
<el-table-column label="员工信息" min-width="130">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button v-if="row.user_id_name" link type="primary" size="small" @click.stop="goToStaffDetail(row)">{{ row.user_id_name }}</el-button>
|
<div>{{ row.user_id_name || cell(row, 'userName') || '--' }}</div>
|
||||||
<span v-else>--</span>
|
|
||||||
<div class="yk-cell__sub">{{ cell(row, 'userPhone') || '--' }}</div>
|
<div class="yk-cell__sub">{{ cell(row, 'userPhone') || '--' }}</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="通话录音" width="140" align="center">
|
<el-table-column label="通话录音" width="150" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button v-if="row.record_media_hash || row.record_file || cell(row, 'recordFile')" size="small" type="primary" link @click.stop="playRecord(row)">播放</el-button>
|
<template v-if="row.record_media_hash || row.record_file || cell(row, 'recordFile')">
|
||||||
|
<div class="yk-cell__sub">{{ callDurationText(row) }}</div>
|
||||||
|
<el-button size="small" type="primary" link @click.stop="playRecord(row)">播放</el-button>
|
||||||
|
</template>
|
||||||
<span v-else style="color:#c0c4cc">--</span>
|
<span v-else style="color:#c0c4cc">--</span>
|
||||||
<div style="margin-top:2px">
|
<div style="margin-top:2px">
|
||||||
<el-button size="small" type="primary" link @click.stop="openVoiceClip(row)">查看长语音</el-button>
|
<el-button size="small" type="primary" link @click.stop="openVoiceClip(row)">查看长语音</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="通话时长" width="100" align="right">
|
<el-table-column label="通话时长" min-width="170">
|
||||||
<template #default="{ row }">{{ formatCallDuration(row.call_duration) }}</template>
|
<template #default="{ row }">
|
||||||
|
<div>{{ cell(row, 'endTime') || '--' }}</div>
|
||||||
|
<div class="yk-cell__sub">{{ callDurationText(row) }}</div>
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="callType === 'wa_voice_call'">
|
<template v-if="callType === 'wa_voice_call'">
|
||||||
@@ -769,4 +798,12 @@ onMounted(() => {
|
|||||||
.yk-drawer__empty {
|
.yk-drawer__empty {
|
||||||
color: #c0c4cc;
|
color: #c0c4cc;
|
||||||
}
|
}
|
||||||
|
.yk-call-person {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.yk-call-person__meta {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user