feat(calls): CallList 改 el-tabs(微信语音/WA 语音/电话)+ CallChannel 加 wa_voice_call
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -116,9 +116,9 @@ export interface GroupMember {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Phone / voice call record (mirrors backend PhoneCallOut). `channel` here is
|
* Phone / voice call record (mirrors backend PhoneCallOut). `channel` here is
|
||||||
* the call-type in {phone_call, voice_call}, not a messaging channel.
|
* the call-type in {phone_call, voice_call, wa_voice_call}, not a messaging channel.
|
||||||
*/
|
*/
|
||||||
export type CallChannel = 'phone_call' | 'voice_call'
|
export type CallChannel = 'phone_call' | 'voice_call' | 'wa_voice_call'
|
||||||
|
|
||||||
export interface PhoneCall {
|
export interface PhoneCall {
|
||||||
call_id: string
|
call_id: string
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage, type TabPaneName } from 'element-plus'
|
||||||
import { getCalls } from '@/api'
|
import { getCalls } from '@/api'
|
||||||
import type { CallChannel, PhoneCall } from '@/api/types'
|
import type { CallChannel, PhoneCall } from '@/api/types'
|
||||||
import {
|
import {
|
||||||
@@ -13,9 +13,9 @@ import {
|
|||||||
import { buildCallSections, readField } from '@/utils/callFields'
|
import { buildCallSections, readField } from '@/utils/callFields'
|
||||||
|
|
||||||
// Calls aren't tied to a messaging channel — `channel` on a call is the call
|
// Calls aren't tied to a messaging channel — `channel` on a call is the call
|
||||||
// type (phone_call / voice_call). We keep a LOCAL filter so it doesn't fight
|
// type (phone_call / voice_call / wa_voice_call). We keep a LOCAL filter so it
|
||||||
// the shared top-bar wechat/whatsapp store used by customers/groups.
|
// doesn't fight the shared top-bar wechat/whatsapp store used by customers/groups.
|
||||||
const callType = ref<CallChannel | 'all'>('all')
|
const callType = ref<CallChannel>('voice_call')
|
||||||
|
|
||||||
const calls = ref<PhoneCall[]>([])
|
const calls = ref<PhoneCall[]>([])
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
@@ -33,17 +33,12 @@ const recordTitle = ref('')
|
|||||||
const drawerOpen = ref(false)
|
const drawerOpen = ref(false)
|
||||||
const drawerCall = ref<PhoneCall | null>(null)
|
const drawerCall = ref<PhoneCall | null>(null)
|
||||||
|
|
||||||
const typeOptions: { value: CallChannel | 'all'; label: string }[] = [
|
const tabs: { value: CallChannel; label: string }[] = [
|
||||||
{ value: 'all', label: '全部类型' },
|
{ value: 'voice_call', label: '微信语音' },
|
||||||
|
{ value: 'wa_voice_call', label: 'WA 语音' },
|
||||||
{ value: 'phone_call', label: '电话' },
|
{ value: 'phone_call', label: '电话' },
|
||||||
{ value: 'voice_call', label: '语音通话' },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
const typeLabelCurrent = computed(() => {
|
|
||||||
const opt = typeOptions.find((o) => o.value === callType.value)
|
|
||||||
return opt ? opt.label : '全部类型'
|
|
||||||
})
|
|
||||||
|
|
||||||
async function load(): Promise<void> {
|
async function load(): Promise<void> {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
errorMsg.value = null
|
errorMsg.value = null
|
||||||
@@ -74,8 +69,8 @@ function handlePageSizeChange(s: number): void {
|
|||||||
load()
|
load()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTypeChange(value: string | number | boolean | undefined): void {
|
function onTabChange(_name: TabPaneName): void {
|
||||||
callType.value = value as CallChannel | 'all'
|
// v-model has already updated callType; just reset paging and reload.
|
||||||
page.value = 1
|
page.value = 1
|
||||||
load()
|
load()
|
||||||
}
|
}
|
||||||
@@ -128,22 +123,20 @@ onMounted(load)
|
|||||||
<div>
|
<div>
|
||||||
<h2 style="margin: 0 0 4px; font-size: 16px">通话记录</h2>
|
<h2 style="margin: 0 0 4px; font-size: 16px">通话记录</h2>
|
||||||
<span class="yk-calls__sub">
|
<span class="yk-calls__sub">
|
||||||
共 {{ total }} 条 · 类型:{{ typeLabelCurrent }}
|
共 {{ total }} 条 · 类型:{{ tabs.find(t => t.value === callType)?.label }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="yk-calls__filters">
|
|
||||||
<el-radio-group :model-value="callType" size="small" @change="onTypeChange">
|
|
||||||
<el-radio-button
|
|
||||||
v-for="opt in typeOptions"
|
|
||||||
:key="opt.value"
|
|
||||||
:value="opt.value"
|
|
||||||
>
|
|
||||||
{{ opt.label }}
|
|
||||||
</el-radio-button>
|
|
||||||
</el-radio-group>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<el-tabs v-model="callType" class="yk-calls__tabs" @tab-change="onTabChange">
|
||||||
|
<el-tab-pane
|
||||||
|
v-for="t in tabs"
|
||||||
|
:key="t.value"
|
||||||
|
:label="t.label"
|
||||||
|
:name="t.value"
|
||||||
|
/>
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
<el-alert
|
<el-alert
|
||||||
v-if="errorMsg"
|
v-if="errorMsg"
|
||||||
:title="errorMsg"
|
:title="errorMsg"
|
||||||
|
|||||||
Reference in New Issue
Block a user