From 61c62f48b0c49920c2555f08aefc5d92a7796ed9 Mon Sep 17 00:00:00 2001 From: zhongzm Date: Fri, 3 Jan 2025 18:01:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:cdr=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/api/auth.ts | 16 ++ src/typings/api.d.ts | 57 ++++++ src/typings/auto-imports.d.ts | 2 + src/views/user-center/cdr/index.vue | 168 +++++++++--------- .../user-center/cdr/modules/cdr-search.vue | 59 ++---- 5 files changed, 172 insertions(+), 130 deletions(-) diff --git a/src/service/api/auth.ts b/src/service/api/auth.ts index 9f33620..66a7639 100644 --- a/src/service/api/auth.ts +++ b/src/service/api/auth.ts @@ -147,4 +147,20 @@ export function deletePackage(id: string) { method: 'delete' }); } +/** Get CDR history list */ +export function fetchCdrHistory(params: Api.Auth.CdrHistoryParams) { + return request({ + url: '/system/cdr/pageHistory', + method: 'get', + params + }); +} +/** Get bill list */ +export function fetchBillList(params: Api.Auth.BillParams) { + return request({ + url: '/system/order/page', + method: 'get', + params + }); +} diff --git a/src/typings/api.d.ts b/src/typings/api.d.ts index 9a2f62b..3b98b10 100644 --- a/src/typings/api.d.ts +++ b/src/typings/api.d.ts @@ -213,6 +213,63 @@ declare namespace Api { clientNum: number; packageEnable: boolean; } + // CDR 话单查询参数 + interface CdrHistoryParams { + pageNum: number; + pageSize: number; + userName?: string; + clientName?: string; + clientMac?: string; + startTime?: string; + endTime?: string; + } + + // CDR 话单信息 + interface CdrHistory { + id: string; + userId: number; + userName: string; + clientName: string; + clientMac: string; + trafficUp: number; + trafficDown: number; + startTime: string; + endTime: string; + duration: number; + } + + // CDR 话单响应 + interface CdrHistoryResponse { + rows: CdrHistory[]; + total: number; + } + + // 账单查询参数 + interface BillParams { + pageNum: number; + pageSize: number; + userName?: string; + type?: number; + status?: number; + } + + // 账单信息 + interface BillInfo { + id: string; + userId: number; + userName: string; + type: number; + packageName: string; + orderAmount: number; + status: number; + createTime: string; + } + + // 账单响应 + interface BillResponse { + rows: BillInfo[]; + total: number; + } } /** diff --git a/src/typings/auto-imports.d.ts b/src/typings/auto-imports.d.ts index fa1d466..0a70adf 100644 --- a/src/typings/auto-imports.d.ts +++ b/src/typings/auto-imports.d.ts @@ -121,6 +121,8 @@ declare global { const exportJobLog: typeof import('../service/api/jobLog')['exportJobLog'] const extendRef: typeof import('@vueuse/core')['extendRef'] const extractTabsByAllRoutes: typeof import('../store/modules/tab/shared')['extractTabsByAllRoutes'] + const fetchBillList: typeof import('../service/api/auth')['fetchBillList'] + const fetchCdrHistory: typeof import('../service/api/auth')['fetchCdrHistory'] const fetchCustomBackendError: typeof import('../service/api/auth')['fetchCustomBackendError'] const fetchGetAllPages: typeof import('../service/api/menu')['fetchGetAllPages'] const fetchGetConstantRoutes: typeof import('../service/api/route')['fetchGetConstantRoutes'] diff --git a/src/views/user-center/cdr/index.vue b/src/views/user-center/cdr/index.vue index aef1310..b895e57 100644 --- a/src/views/user-center/cdr/index.vue +++ b/src/views/user-center/cdr/index.vue @@ -4,54 +4,17 @@ import { SimpleScrollbar } from '~/packages/materials/src'; import CdrSearch from './modules/cdr-search.vue'; import { computed, shallowRef } from 'vue'; import { useElementSize } from '@vueuse/core'; - -// 定义话单信息接口 -interface CdrInfo { - id: number; - callId: string; - callerNumber: string; - startTime: string; - endTime: string; - duration: number; - recordingUrl?: string; -} +import { fetchCdrHistory } from '@/service/api/auth'; +import { formatStorage } from '@/utils/units'; // 搜索模型 type SearchModel = { pageNum: number; pageSize: number; - callId?: string; - callerNumber?: string; - startTime?: string; - endTime?: string; + userName?: string; + clientName?: string; }; -// 模拟话单数据 -const mockCdrs: CdrInfo[] = [ - { - id: 1, - callId: 'CALL2024031501', - callerNumber: '13800138000', - startTime: '2024-03-15 10:00:00', - endTime: '2024-03-15 10:05:30', - duration: 330, - - recordingUrl: 'https://example.com/recording/1.wav' - }, - { - id: 2, - callId: 'CALL2024031502', - callerNumber: '13800138001', - startTime: '2024-03-15 11:00:00', - endTime: '2024-03-15 11:00:15', - duration: 15, - - } -]; - - - - // 格式化通话时长 const formatDuration = (seconds: number) => { const hours = Math.floor(seconds / 3600); @@ -67,34 +30,28 @@ const formatDuration = (seconds: number) => { }; const doGetCdrInfo = async (params: SearchModel) => { - await new Promise(resolve => setTimeout(resolve, 500)); - - let filteredCdrs = [...mockCdrs]; - - // 根据搜索条件过滤 - if (params.callId) { - filteredCdrs = filteredCdrs.filter(cdr => - cdr.callId.toLowerCase().includes(params.callId!.toLowerCase()) - ); + try { + const response = await fetchCdrHistory(params); + console.log('API Response:', response); + const rows = response.data?.rows || []; + const total = response.data?.total || 0; + console.log('Processed data:', { rows, total }); + return { + data: { + rows, + total + } + }; + } catch (error) { + console.error('API Error:', error); + return { + data: { + rows: [], + total: 0 + }, + error + }; } - if (params.callerNumber) { - filteredCdrs = filteredCdrs.filter(cdr => - cdr.callerNumber.includes(params.callerNumber!) - ); - } - - - const startIndex = (params.pageNum - 1) * params.pageSize; - const endIndex = startIndex + params.pageSize; - const paginatedCdrs = filteredCdrs.slice(startIndex, endIndex); - - return { - data: { - rows: paginatedCdrs, - total: filteredCdrs.length - }, - error: null - }; }; const wrapperEl = shallowRef(null); @@ -113,42 +70,80 @@ const { columns, columnChecks, data, loading, getData, mobilePagination, searchP pageSize: 10 } as SearchModel, rowKey: 'id', - columns: (): AntDesign.TableColumn>[] => [ + pagination: true, + columns: (): AntDesign.TableColumn[] => [ { - key: 'callId', - dataIndex: 'callId', - title: '话单ID', + key: 'userName', + dataIndex: 'userName', + title: '用户名', align: 'center', width: 150 }, { - key: 'callerNumber', - dataIndex: 'callerNumber', - title: '主叫号码', + key: 'clientName', + dataIndex: 'clientName', + title: '设备名', align: 'center', width: 120 }, + { + key: 'clientMac', + dataIndex: 'clientMac', + title: '设备MAC地址', + align: 'center', + width: 120 + }, + { + key: 'trafficUp', + dataIndex: 'trafficUp', + title: '上行流量', + align: 'center', + width: 120, + customRender: ({ text }) => { + const { value, unit } = formatStorage(text); + return `${value.toFixed(2)} ${unit}`; + } + }, + { + key: 'trafficDown', + dataIndex: 'trafficDown', + title: '下行流量', + align: 'center', + width: 120, + customRender: ({ text }) => { + const { value, unit } = formatStorage(text); + return `${value.toFixed(2)} ${unit}`; + } + }, { key: 'startTime', dataIndex: 'startTime', title: '开始时间', align: 'center', - width: 180 + width: 180, + customRender: ({ text }) => { + const timestamp = String(text).length === 13 ? Number(text) : Number(text) * 1000; + return new Date(timestamp).toLocaleString(); + } }, { key: 'endTime', dataIndex: 'endTime', title: '结束时间', align: 'center', - width: 180 + width: 180, + customRender: ({ text }) => { + const timestamp = String(text).length === 13 ? Number(text) : Number(text) * 1000; + return new Date(timestamp).toLocaleString(); + } }, { key: 'duration', dataIndex: 'duration', - title: '连接时长', + title: '时长', align: 'center', width: 120, - customRender: ({ record }: { record: CdrInfo }) => formatDuration(record.duration) + customRender: ({ text }) => formatDuration(text) }, ] }); @@ -173,7 +168,7 @@ const { columns, columnChecks, data, loading, getData, mobilePagination, searchP v-model:columns="columnChecks" :loading="loading" :show-delete="false" - :show-add="false" + :not-show-add="true" @refresh="getData" /> @@ -184,9 +179,20 @@ const { columns, columnChecks, data, loading, getData, mobilePagination, searchP :loading="loading" row-key="id" size="small" - :pagination="mobilePagination" + :pagination="{ + ...mobilePagination, + total: mobilePagination.total, + current: searchParams.pageNum, + pageSize: searchParams.pageSize, + showTotal: (total: number) => `共 ${total} 条` + }" :scroll="scrollConfig" class="h-full" + @change="(pagination) => { + searchParams.pageNum = pagination.current; + searchParams.pageSize = pagination.pageSize; + getData(); + }" /> diff --git a/src/views/user-center/cdr/modules/cdr-search.vue b/src/views/user-center/cdr/modules/cdr-search.vue index 7e27741..fdd94ea 100644 --- a/src/views/user-center/cdr/modules/cdr-search.vue +++ b/src/views/user-center/cdr/modules/cdr-search.vue @@ -2,31 +2,22 @@ import { ref, computed } from 'vue'; import { Form } from 'ant-design-vue'; import type { FormInstance } from 'ant-design-vue'; -import dayjs, { Dayjs } from 'dayjs'; - -// 修改类型定义以匹配 ARangePicker 的期望类型 -type TimeRangeValue = [Dayjs, Dayjs] | [string, string] | undefined; interface SearchModel { pageNum: number; pageSize: number; - callId?: string; - callerNumber?: string; - startTime?: string; - endTime?: string; + userName?: string; + clientName?: string; } -// 修改 props 定义 const props = withDefaults(defineProps<{ model: SearchModel; }>(), { model: () => ({ pageNum: 1, pageSize: 10, - callId: '', - callerNumber: '', - startTime: '', - endTime: '' + userName: '', + clientName: '' }) }); @@ -44,22 +35,6 @@ const formModel = computed({ set: (val: SearchModel) => emit('update:model', val) }); -// 修改 timeRange 的实现 -const timeRange = computed({ - get() { - const { startTime, endTime } = formModel.value; - if (!startTime || !endTime) return undefined; - return [dayjs(startTime), dayjs(endTime)] as [Dayjs, Dayjs]; - }, - set(val: TimeRangeValue) { - emit('update:model', { - ...formModel.value, - startTime: val ? (typeof val[0] === 'string' ? val[0] : val[0].format('YYYY-MM-DD HH:mm:ss')) : '', - endTime: val ? (typeof val[1] === 'string' ? val[1] : val[1].format('YYYY-MM-DD HH:mm:ss')) : '' - }); - } -}); - function handleReset() { resetFields(); emit('reset'); @@ -78,34 +53,20 @@ function handleSearch() { layout="inline" class="flex flex-wrap gap-16px items-center" > - + - + - - - 重置