2
0

feat:历史账单界面接通

This commit is contained in:
zhongzm
2025-01-09 16:19:19 +08:00
parent 671498b216
commit 10153e2c6b
3 changed files with 117 additions and 130 deletions

View File

@@ -136,4 +136,13 @@ export function submitOrder(data: Api.Order.SubmitOrderParams) {
data data
}); });
} }
/** Get bill history records */
export function fetchBillHistory(params: Api.Bill.BillQueryParams) {
return request<Api.Bill.BillListResponse>({
url: '/u/bill/page',
method: 'get',
params
});
}

33
src/typings/api.d.ts vendored
View File

@@ -629,4 +629,37 @@ declare namespace Api {
/** Combined order params type */ /** Combined order params type */
type SubmitOrderParams = PackageOrderParams | RechargeOrderParams; type SubmitOrderParams = PackageOrderParams | RechargeOrderParams;
} }
/**
* Namespace Bill
*
* Backend api module: "bill"
*/
namespace Bill {
/** Bill record information */
interface BillRecord {
id: string;
startTime: string | null;
endTime: string | null;
traffic: string | null;
amount: string;
status: number;
createTime: string;
}
/** Bill list response */
interface BillListResponse {
rows: BillRecord[];
total: number;
}
/** Bill query parameters */
interface BillQueryParams {
pageNum: number;
pageSize: number;
}
}
} }

View File

@@ -1,160 +1,93 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, h } from 'vue' import { ref, h, onMounted, computed } from 'vue'
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import type { TableColumnsType } from 'ant-design-vue' import type { TableColumnsType } from 'ant-design-vue'
import { Tag as ATag, Table as ATable } from 'ant-design-vue' import { Tag as ATag, Table as ATable } from 'ant-design-vue'
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { fetchBillHistory } from '@/service/api/auth';
import { useWindowSize } from '@vueuse/core';
const router = useRouter(); const router = useRouter();
const handleBack = () => { const handleBack = () => {
router.push('/billing/billservice'); router.push('/billing/billservice');
}; };
const { t } = useI18n(); const { t } = useI18n();
interface BillDetail {
deviceName: string
usage: number
unit: string
}
interface BillRecord { const billData = ref<Api.Bill.BillRecord[]>([]);
id: number const total = ref(0);
date: string
amount: number
status: 'paid' | 'unpaid'
details: BillDetail[]
}
// 模拟数据 const { width } = useWindowSize();
const billData = ref<BillRecord[]>([ const isMobile = computed(() => width.value < 768);
{
id: 1, const getBillData = async () => {
date: '2024-03-01', try {
amount: 299, const response = await fetchBillHistory({
status: 'paid', pageNum: 1,
details: [ pageSize: 10
{ deviceName: 'Device A', usage: 50, unit: 'GB' }, });
{ deviceName: 'Device B', usage: 30, unit: 'GB' } console.log('API Response:', response);
] if (response?.data?.rows) {
}, console.log('Rows data:', response.data.rows);
{ billData.value = response.data.rows;
id: 2, total.value = response.data.total;
date: '2024-02-01', console.log('billData value:', billData.value);
amount: 199, } else {
status: 'paid', console.log('No data found. Response structure:', JSON.stringify(response, null, 2));
details: [ }
{ deviceName: 'Device A', usage: 30, unit: 'GB' }, } catch (error) {
{ deviceName: 'Device C', usage: 20, unit: 'GB' } console.error('Failed to fetch bill history:', error);
]
},
{
id: 3,
date: '2024-01-01',
amount: 399,
status: 'paid',
details: [
{ deviceName: 'Device B', usage: 80, unit: 'GB' },
{ deviceName: 'Device D', usage: 40, unit: 'GB' }
]
},
{
id: 4,
date: '2023-12-01',
amount: 159,
status: 'paid',
details: [
{ deviceName: 'Device A', usage: 25, unit: 'GB' },
{ deviceName: 'Device E', usage: 15, unit: 'GB' }
]
},
{
id: 5,
date: '2023-11-01',
amount: 499,
status: 'unpaid',
details: [
{ deviceName: 'Device C', usage: 100, unit: 'GB' },
{ deviceName: 'Device D', usage: 60, unit: 'GB' },
{ deviceName: 'Device E', usage: 40, unit: 'GB' }
]
},
{
id: 6,
date: '2023-10-01',
amount: 259,
status: 'paid',
details: [
{ deviceName: 'Device B', usage: 45, unit: 'GB' },
{ deviceName: 'Device D', usage: 35, unit: 'GB' }
]
},
{
id: 7,
date: '2023-09-01',
amount: 359,
status: 'paid',
details: [
{ deviceName: 'Device A', usage: 60, unit: 'GB' },
{ deviceName: 'Device C', usage: 40, unit: 'GB' }
]
},
{
id: 8,
date: '2023-08-01',
amount: 189,
status: 'unpaid',
details: [
{ deviceName: 'Device B', usage: 25, unit: 'GB' },
{ deviceName: 'Device E', usage: 20, unit: 'GB' }
]
},
{
id: 9,
date: '2023-07-01',
amount: 299,
status: 'paid',
details: [
{ deviceName: 'Device A', usage: 45, unit: 'GB' },
{ deviceName: 'Device D', usage: 35, unit: 'GB' }
]
},
{
id: 10,
date: '2023-06-01',
amount: 459,
status: 'paid',
details: [
{ deviceName: 'Device C', usage: 70, unit: 'GB' },
{ deviceName: 'Device E', usage: 50, unit: 'GB' },
{ deviceName: 'Device B', usage: 30, unit: 'GB' }
]
} }
]) };
const columns: TableColumnsType = [ onMounted(() => {
getBillData();
});
const formatDateTime = (dateTimeString: string) => {
if (!dateTimeString) return '';
const date = new Date(dateTimeString);
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
});
};
const columns = computed<TableColumnsType>(() => [
{ {
title: t('page.histories.billdate'), title: t('page.histories.billdate'),
dataIndex: 'date', dataIndex: 'createTime',
key: 'date' key: 'createTime',
responsive: ['md'],
customRender: ({ text }) => text ? formatDateTime(text) : ''
}, },
{ {
title: t('page.histories.amount'), title: t('page.histories.amount'),
dataIndex: 'amount', dataIndex: 'amount',
key: 'amount', key: 'amount',
customRender: ({ text }: { text: number }) => `¥${text}` customRender: ({ text }: { text: string }) => {
const formattedAmount = Number(text).toFixed(2);
return `¥${formattedAmount}`;
}
}, },
{ {
title: t('page.histories.status'), title: t('page.histories.status'),
dataIndex: 'status', dataIndex: 'status',
key: 'status', key: 'status',
customRender: ({ text }: { text: 'paid' | 'unpaid' }) => { customRender: ({ text }: { text: number }) => {
return h(ATag, { return h(ATag, {
color: text === 'paid' ? 'success' : 'warning' color: text === 1 ? 'success' : 'warning'
}, { }, {
default: () => text === 'paid' ? t('page.histories.Paid') : t('page.histories.Unpaid') default: () => text === 1 ? t('page.histories.Paid') : t('page.histories.Unpaid')
}) })
} }
} }
] ]);
</script> </script>
<template> <template>
@@ -168,11 +101,10 @@ const columns: TableColumnsType = [
<ATable <ATable
:columns="columns" :columns="columns"
:data-source="billData" :data-source="billData"
:row-key="(record: BillRecord) => record.id" :row-key="(record: Api.Bill.BillRecord) => record.id"
:expand-column-width="60"
:pagination="{ :pagination="{
pageSize: 5, pageSize: 5,
total: billData.length, total: total,
showTotal: (total: number) => `${total}`, showTotal: (total: number) => `${total}`,
showSizeChanger: true, showSizeChanger: true,
showQuickJumper: true, showQuickJumper: true,
@@ -181,8 +113,21 @@ const columns: TableColumnsType = [
> >
<template #expandedRowRender="{ record }"> <template #expandedRowRender="{ record }">
<div class="pl-4"> <div class="pl-4">
<div v-for="(detail, index) in record.details" :key="index"> <div v-if="isMobile" class="mb-2">
{{ t('page.histories.device') }}: {{ detail.deviceName }} - {{ t('page.histories.Usetraffic') }}: {{ detail.usage }}{{ detail.unit }} <strong>{{ t('page.histories.billdate') }}:</strong>
{{ formatDateTime(record.createTime) }}
</div>
<div v-if="record.traffic">
<strong>{{ t('page.histories.traffic') }}:</strong>
{{ record.traffic }}
</div>
<div v-if="record.startTime">
<strong>{{ t('page.histories.startTime') }}:</strong>
{{ formatDateTime(record.startTime) }}
</div>
<div v-if="record.endTime">
<strong>{{ t('page.histories.endTime') }}:</strong>
{{ formatDateTime(record.endTime) }}
</div> </div>
</div> </div>
</template> </template>