2
0
Files
fe.wfc/src/views/user-center/cdr/index.vue

231 lines
5.9 KiB
Vue

<script setup lang="tsx">
import { useTable } from '@/hooks/common/table';
import { SimpleScrollbar } from '~/packages/materials/src';
import CdrSearch from './modules/cdr-search.vue';
import { computed, shallowRef } from 'vue';
import { useElementSize } from '@vueuse/core';
import { fetchCdrHistory } from '@/service/api/auth';
import { formatStorage } from '@/utils/units';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
// 搜索模型
type SearchModel = {
pageNum: number;
pageSize: number;
userName?: string;
clientName?: string;
endTimeS?:string;
endTimeE?:string;
};
// 格式化通话时长
const formatDuration = (seconds: number) => {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const remainingSeconds = seconds % 60;
const parts = [];
if (hours > 0) parts.push(`${hours}${t('page.cdr.hour')}`);
if (minutes > 0) parts.push(`${minutes}${t('page.cdr.min')}`);
parts.push(`${remainingSeconds}${t('page.cdr.sec')}`);
return parts.join('');
};
const doGetCdrInfo = async (params: SearchModel) => {
try {
const response = await fetchCdrHistory(params);
console.log('API Response:', response);
const rows = response.data?.rows || [];
const total = response.data?.total || 0;
return {
data: {
rows,
total
}
};
} catch (error) {
console.error('API Error:', error);
return {
data: {
rows: [],
total: 0
},
error
};
}
};
const wrapperEl = shallowRef<HTMLElement | null>(null);
const { height: wrapperElHeight } = useElementSize(wrapperEl);
const scrollConfig = computed(() => ({
y: wrapperElHeight.value - 72,
x: 1200
}));
const { columns, columnChecks, data, loading, getData, mobilePagination, searchParams } = useTable({
apiFn: doGetCdrInfo,
immediate: true,
apiParams: {
pageNum: 1,
pageSize: 10
} as SearchModel,
rowKey: 'id',
pagination: true,
columns: (): AntDesign.TableColumn<Api.Auth.CdrHistory>[] => [
{
key: 'userName',
dataIndex: 'userName',
title: t('page.cdr.username'),
align: 'center',
width: 150
},
{
key: 'clientName',
dataIndex: 'clientName',
title: t('page.cdr.clientname'),
align: 'center',
width: 120
},
{
key: 'clientMac',
dataIndex: 'clientMac',
title: t('page.cdr.clientmac'),
align: 'center',
width: 120
},
{
key: 'trafficUp',
dataIndex: 'trafficUp',
title: t('page.cdr.up'),
align: 'center',
width: 120,
sorter: (a, b) => a.trafficUp - b.trafficUp,
customRender: ({ text }) => {
const { value, unit } = formatStorage(text);
return `${value.toFixed(2)} ${unit}`;
}
},
{
key: 'trafficDown',
dataIndex: 'trafficDown',
title: t('page.cdr.down'),
align: 'center',
width: 120,
sorter: (a, b) => a.trafficDown - b.trafficDown,
customRender: ({ text }) => {
const { value, unit } = formatStorage(text);
return `${value.toFixed(2)} ${unit}`;
}
},
{
key: 'startTime',
dataIndex: 'startTime',
title: t('page.cdr.start'),
align: 'center',
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: t('page.cdr.end'),
align: 'center',
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: t('page.cdr.duration'),
align: 'center',
width: 120,
sorter: (a, b) => a.duration - b.duration,
customRender: ({ text }) => formatDuration(text)
},
]
});
const handleTableChange = (
pagination: any,
filters: any,
sorter: any
) => {
searchParams.pageNum = pagination.current;
searchParams.pageSize = pagination.pageSize;
getData();
};
const handleReset = () => {
// 保存当前的 pageSize
const currentPageSize = searchParams.pageSize;
// 重置搜索参数
searchParams.userName = '';
searchParams.clientName = '';
searchParams.endTimeS = undefined;
searchParams.endTimeE = undefined;
searchParams.pageNum = 1;
searchParams.pageSize = currentPageSize;
// 重新获取数据
getData();
};
</script>
<template>
<SimpleScrollbar>
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
<CdrSearch
v-model:model="searchParams"
@reset="handleReset"
@search="getData"
/>
<ACard
:title="t('page.cdr.title')"
:bordered="false"
:body-style="{ flex: 1, overflow: 'hidden' }"
class="flex-col-stretch sm:flex-1-hidden card-wrapper"
>
<template #extra>
<TableHeaderOperation
v-model:columns="columnChecks"
:loading="loading"
:show-delete="false"
:not-show-add="true"
@refresh="getData"
/>
</template>
<ATable
ref="wrapperEl"
:columns="columns"
:data-source="data"
:loading="loading"
row-key="id"
size="small"
:pagination="{
...mobilePagination,
total: mobilePagination.total,
current: searchParams.pageNum,
pageSize: searchParams.pageSize,
showTotal: (total: number) => `${t('page.cdr.total')} ${total} `
}"
:scroll="scrollConfig"
class="h-full"
@change="handleTableChange"
/>
</ACard>
</div>
</SimpleScrollbar>
</template>
<style scoped></style>