feat:套餐记录界面增加套餐显示以及中英文显示
This commit is contained in:
@@ -605,7 +605,18 @@ const local: any = {
|
||||
status: 'Status',
|
||||
packageType: 'Package',
|
||||
paid: 'Paid',
|
||||
unpaid: 'Unpaid'
|
||||
unpaid: 'Unpaid',
|
||||
packagename:'Package name',
|
||||
packageinfo:'Package',
|
||||
price:'Price',
|
||||
traffic:'Traffic',
|
||||
Expirationdate:'Expiration date',
|
||||
unpackage:'Unknow package',
|
||||
unlimit:'Unlimited',
|
||||
hour:'Hour',
|
||||
day:'Day',
|
||||
month:'Month',
|
||||
year:'Year',
|
||||
},
|
||||
endpoint:{
|
||||
access:"current client",
|
||||
|
||||
@@ -607,7 +607,18 @@ const local:any = {
|
||||
status: '状态',
|
||||
packageType: '套餐',
|
||||
paid: '已支付',
|
||||
unpaid: '未支付'
|
||||
unpaid: '未支付',
|
||||
packagename:'套餐名',
|
||||
packageinfo:'套餐详情',
|
||||
price:'套餐金额',
|
||||
traffic:'流量',
|
||||
Expirationdate:'有效期限',
|
||||
unpackage:'未知套餐',
|
||||
unlimit:'无限制',
|
||||
hour:'小时',
|
||||
day:'天',
|
||||
month:'月',
|
||||
year:'年',
|
||||
},
|
||||
endpoint:{
|
||||
access:"当前设备",
|
||||
|
||||
49
src/typings/api.d.ts
vendored
49
src/typings/api.d.ts
vendored
@@ -616,27 +616,50 @@ declare namespace Api {
|
||||
|
||||
/** Package history record information */
|
||||
interface PackageHistoryRecord {
|
||||
id: string;
|
||||
delFlag: boolean;
|
||||
createBy: number;
|
||||
/** Record ID */
|
||||
id: number;
|
||||
/** Order creation time */
|
||||
createTime: string;
|
||||
updateBy: number;
|
||||
updateTime: string;
|
||||
userId: number;
|
||||
packageId: string;
|
||||
paymentId: string | null;
|
||||
orderNo: string | null;
|
||||
type: number; // 0 表示套餐
|
||||
/** Order amount */
|
||||
orderAmount: string;
|
||||
status: number; // 0未支付,1已支付
|
||||
/** Order status: 1-paid, 0-unpaid */
|
||||
status: number;
|
||||
/** Package information */
|
||||
upackage?: {
|
||||
/** Package name */
|
||||
packageName: string;
|
||||
/** Package price */
|
||||
price: number;
|
||||
/** Whether traffic is limited */
|
||||
trafficEnable: boolean;
|
||||
/** Traffic limit in bytes */
|
||||
traffic: number;
|
||||
/** Period number */
|
||||
periodNum: number;
|
||||
/** Period type: 0-hour, 1-day, 2-month, 3-year */
|
||||
periodType: number;
|
||||
};
|
||||
}
|
||||
|
||||
/** Package history list response */
|
||||
interface PackageHistoryListResponse {
|
||||
/** Package history response */
|
||||
interface PackageHistoryResponse {
|
||||
code: number;
|
||||
msg: string;
|
||||
data: {
|
||||
rows: PackageHistoryRecord[];
|
||||
total: number;
|
||||
};
|
||||
}
|
||||
|
||||
/** Package history response */
|
||||
interface PackageHistoryResponse {
|
||||
code: number;
|
||||
msg: string;
|
||||
data: {
|
||||
rows: PackageHistoryRecord[];
|
||||
total: number;
|
||||
};
|
||||
}
|
||||
/** Package history query parameters */
|
||||
interface PackageHistoryQueryParams {
|
||||
pageNum: number;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from '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, Modal, Button as AButton } from 'ant-design-vue'
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRouter } from 'vue-router';
|
||||
import { fetchPackageHistory } from '@/service/api/auth';
|
||||
@@ -53,6 +53,50 @@ onMounted(() => {
|
||||
getPackageData();
|
||||
});
|
||||
|
||||
const formatPeriodType = (type: number) => {
|
||||
switch (type) {
|
||||
case 0: return t('page.packagehistories.hour');
|
||||
case 1: return t('page.packagehistories.day');
|
||||
case 2: return t('page.packagehistories.month');
|
||||
case 3: return t('page.packagehistories.year');
|
||||
default: return '未知';
|
||||
}
|
||||
};
|
||||
|
||||
const showPackageDetail = (record: Api.Package.PackageHistoryRecord) => {
|
||||
Modal.info({
|
||||
title: t('page.packagehistories.packageinfo'),
|
||||
width: 400,
|
||||
content: h('div', { class: 'package-detail' }, [
|
||||
h('div', { class: 'detail-item' }, [
|
||||
h('span', { class: 'detail-label' }, t('page.packagehistories.packagename')+':'),
|
||||
h('span', { class: 'detail-value' }, record.upackage?.packageName || '未知套餐')
|
||||
]),
|
||||
h('div', { class: 'detail-item' }, [
|
||||
h('span', { class: 'detail-label' }, t('page.packagehistories.price')+':'),
|
||||
h('span', { class: 'detail-value' }, `¥${Number(record.upackage?.price || 0).toFixed(2)}`)
|
||||
]),
|
||||
h('div', { class: 'detail-item' }, [
|
||||
h('span', { class: 'detail-label' }, t('page.packagehistories.traffic')+':'),
|
||||
h('span', { class: 'detail-value' },
|
||||
record.upackage?.trafficEnable ? formatTraffic(record.upackage.traffic) : t('page.packagehistories.unlimit')
|
||||
)
|
||||
]),
|
||||
h('div', { class: 'detail-item' }, [
|
||||
h('span', { class: 'detail-label' }, t('page.packagehistories.Expirationdate')+':'),
|
||||
h('span', { class: 'detail-value' },
|
||||
`${record.upackage?.periodNum || 0} ${formatPeriodType(record.upackage?.periodType || 0)}`
|
||||
)
|
||||
]),
|
||||
h('div', { class: 'detail-item' }, [
|
||||
h('span', { class: 'detail-label' }, t('page.packagehistories.orderdate')+':'),
|
||||
h('span', { class: 'detail-value' }, formatDateTime(record.createTime))
|
||||
])
|
||||
]),
|
||||
class: 'package-detail-modal'
|
||||
});
|
||||
};
|
||||
|
||||
const columns = computed<TableColumnsType>(() => [
|
||||
{
|
||||
title: t('page.packagehistories.orderdate'),
|
||||
@@ -71,15 +115,20 @@ const columns = computed<TableColumnsType>(() => [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: t('page.packagehistories.type'),
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
customRender: ({ text }: { text: number }) => {
|
||||
return h(ATag, {
|
||||
color: 'green'
|
||||
title: t('page.packagehistories.packagename'),
|
||||
dataIndex: ['upackage', 'packageName'],
|
||||
key: 'packageName',
|
||||
customRender: ({ text, record }: { text: string; record: Api.Package.PackageHistoryRecord }) => {
|
||||
return h(AButton, {
|
||||
type: 'link',
|
||||
size: 'small',
|
||||
onClick: (e: Event) => {
|
||||
e.stopPropagation(); // 阻止事件冒泡,避免触发行点击事件
|
||||
showPackageDetail(record);
|
||||
}
|
||||
}, {
|
||||
default: () => t('page.packagehistories.packageType')
|
||||
})
|
||||
default: () => text || t('page.packagehistories.unpackage')
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -95,6 +144,19 @@ const columns = computed<TableColumnsType>(() => [
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
const formatTraffic = (bytes: number): string => {
|
||||
if (!bytes) return '0B';
|
||||
|
||||
if (bytes >= 1024 * 1024 * 1024) {
|
||||
return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)}GB`;
|
||||
} else if (bytes >= 1024 * 1024) {
|
||||
return `${(bytes / (1024 * 1024)).toFixed(2)}MB`;
|
||||
} else if (bytes >= 1024) {
|
||||
return `${(bytes / 1024).toFixed(2)}KB`;
|
||||
}
|
||||
return `${bytes}B`;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -148,4 +210,45 @@ const columns = computed<TableColumnsType>(() => [
|
||||
.pl-4 {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
:deep(.package-detail) {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
:deep(.detail-item) {
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:deep(.detail-item:last-child) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
:deep(.detail-label) {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
margin-right: 8px;
|
||||
flex-shrink: 0;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
:deep(.detail-value) {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.package-detail-modal .ant-modal-confirm-content) {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
:deep(.ant-btn-link) {
|
||||
padding: 0;
|
||||
height: auto;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
:deep(.ant-btn-link:hover) {
|
||||
color: #1890ff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user