代码修改

This commit is contained in:
qiuyuan 2025-12-29 16:34:12 +08:00
parent 3ccb4a600c
commit bf8c5e1cc1
4 changed files with 780 additions and 36 deletions

View File

@ -195,6 +195,12 @@ const routes: RouteRecordRaw[] = [
component: () => component: () =>
import("@/views/admin/account/cost/myOrder/index.vue"), import("@/views/admin/account/cost/myOrder/index.vue"),
}, },
{
path: "myMoney",
name: "myMoney",
component: () =>
import("@/views/admin/account/cost/myMoney/index.vue"),
},
{ {
path: "voucher", path: "voucher",
name: "voucher", name: "voucher",
@ -253,25 +259,25 @@ const router = createRouter({
routes, routes,
}); });
// ====== 添加全局前置守卫 ====== // ====== 添加全局前置守卫 ======
router.beforeEach((to, from, next) => { // router.beforeEach((to, from, next) => {
console.log("Navigating to:", to.path); // console.log("Navigating to:", to.path);
const list = ["/layout/home","/document/introdution","/layout/admin/home"]; // const list = ["/layout/home","/document/introdution","/layout/admin/home"];
if (list.indexOf(to.path) != -1) { // if (list.indexOf(to.path) != -1) {
next(); // next();
return; // return;
} else { // } else {
const token = localStorage.getItem("token"); // 或从 pinia/vuex 获取 // const token = localStorage.getItem("token"); // 或从 pinia/vuex 获取
const isLoginPage = to.path === "/login"; // const isLoginPage = to.path === "/login";
if (!token && !isLoginPage) { // if (!token && !isLoginPage) {
// 没有 token 且不是去登录页 → 跳转登录 // // 没有 token 且不是去登录页 → 跳转登录
next({ path: "/login" }); // next({ path: "/login" });
} else if (token && isLoginPage) { // } else if (token && isLoginPage) {
// 已登录却访问登录页 → 跳转首页(可选) // // 已登录却访问登录页 → 跳转首页(可选)
next({ path: "/layout/home" }); // next({ path: "/layout/home" });
} else { // } else {
// 正常访问 // // 正常访问
next(); // next();
} // }
} // }
}); // });
export default router; export default router;

View File

@ -0,0 +1,679 @@
<template>
<div class="home-page">
<!-- 顶部资产卡片区域 -->
<a-row :gutter="24" class="asset-cards">
<!-- 左侧可用余额卡片 -->
<a-col :span="8">
<a-card :bordered="false" class="card balance-card">
<div class="fee-header">
<div class="fee-title">可用余额</div>
<a-button type="link" size="small" class="fee-titleb" @click="goToBills">查看消费明细</a-button>
</div>
<a-divider />
<div class="money">¥ {{ formatAmount(balance) }}</div>
<div class="money-btn">
<div><a-button type="primary" size="small" @click="goToRecharge">充值</a-button></div>
<div><a-button size="small">提现</a-button></div>
</div>
</a-card>
</a-col>
<!-- 右侧算力点和算力券卡片 -->
<a-col :span="16">
<!-- 算力点卡片 -->
<a-card title="算力点" :bordered="false" class="card computing-card">
<div class="computing-content">
<div class="computing-amount">
<span class="amount-value">{{ formatComputingPoints(computingPoints) }}</span>
<span class="amount-unit"></span>
</div>
<div class="computing-actions">
<a-button type="primary" size="small" @click="goToExchange">去兑换</a-button>
</div>
</div>
</a-card>
<!-- 算力券卡片 -->
<a-card title="算力券" :bordered="false" class="card coupon-card">
<div class="coupon-content">
<div class="coupon-amount">
<span class="amount-value">{{ availableCoupons }}</span>
<span class="amount-unit"></span>
</div>
<div class="coupon-actions">
<a-button type="primary" size="small" @click="goToCoupons">去查看</a-button>
</div>
</div>
</a-card>
</a-col>
</a-row>
<!-- 底部账单区域 -->
<div class="bill-section">
<div class="bill-header">
<h3 class="bill-title">账单明细</h3>
<div class="date-range">
<span class="date-label">日期范围</span>
<a-range-picker
v-model:value="dateRange"
:placeholder="['开始时间', '结束时间']"
@change="handleDateChange"
style="width: 250px;"
/>
</div>
</div>
<!-- 账单表格 -->
<a-table
:columns="columns"
:data-source="billData"
:pagination="pagination"
@change="handleTableChange"
:loading="loading"
class="bill-table"
>
<!-- 流水号列 -->
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'serialNumber'">
<span class="serial-number">{{ record.serialNumber }}</span>
</template>
<!-- 交易类型列 -->
<template v-else-if="column.key === 'transactionType'">
<a-tag :color="getTransactionTypeColor(record.transactionType)">
{{ record.transactionType }}
</a-tag>
</template>
<!-- 金额相关列 -->
<template v-else-if="['transactionAmount', 'originalPrice', 'discountAmount', 'balancePayment', 'voucherDeduction'].includes(column.key)">
<span :class="{
'amount-positive': record[column.key] > 0,
'amount-negative': record[column.key] < 0
}">
¥ {{ formatAmount(Math.abs(record[column.key])) }}
</span>
</template>
</template>
</a-table>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import {
message,
TableProps
} from 'ant-design-vue'
import type { Dayjs } from 'dayjs'
import router from '@/router'
//
const balance = ref<number>(5.00)
const computingPoints = ref<number>(1023)
const availableCoupons = ref<number>(3)
//
const dateRange = ref<[Dayjs, Dayjs]>()
//
interface BillRecord {
key: string
serialNumber: string
transactionTime: string
transactionType: string
productName: string
transactionAmount: number
originalPrice: number
discountAmount: number
balancePayment: number
voucherDeduction: number
}
const loading = ref(false)
const billData = ref<BillRecord[]>([])
const pagination = ref({
current: 1,
pageSize: 10,
total: 0,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total: number) => `${total} 条记录`
})
//
const columns = computed(() => [
{
title: '流水号',
dataIndex: 'serialNumber',
key: 'serialNumber',
width: 180,
ellipsis: true
},
{
title: '交易时间',
dataIndex: 'transactionTime',
key: 'transactionTime',
width: 170,
sorter: true
},
{
title: '交易类型',
dataIndex: 'transactionType',
key: 'transactionType',
width: 120,
filters: [
{ text: '充值', value: '充值' },
{ text: '消费', value: '消费' },
{ text: '提现', value: '提现' },
{ text: '退款', value: '退款' }
]
},
{
title: '产品名称',
dataIndex: 'productName',
key: 'productName',
width: 150,
ellipsis: true
},
{
title: '交易金额',
dataIndex: 'transactionAmount',
key: 'transactionAmount',
width: 120,
align: 'right'
},
{
title: '原价',
dataIndex: 'originalPrice',
key: 'originalPrice',
width: 120,
align: 'right'
},
{
title: '优惠金额',
dataIndex: 'discountAmount',
key: 'discountAmount',
width: 120,
align: 'right'
},
{
title: '余额支付',
dataIndex: 'balancePayment',
key: 'balancePayment',
width: 120,
align: 'right'
},
{
title: '代金券抵扣',
dataIndex: 'voucherDeduction',
key: 'voucherDeduction',
width: 120,
align: 'right'
}
])
//
onMounted(() => {
fetchBillData()
})
//
const formatAmount = (amount: number): string => {
return amount.toFixed(2)
}
//
const formatComputingPoints = (points: number): string => {
return points.toLocaleString()
}
//
const getTransactionTypeColor = (type: string): string => {
const colorMap: Record<string, string> = {
'充值': 'green',
'消费': 'blue',
'提现': 'orange',
'退款': 'purple'
}
return colorMap[type] || 'default'
}
//
const handleDateChange = (dates: [Dayjs, Dayjs] | null) => {
if (dates) {
console.log('选择的日期范围:', dates)
//
fetchBillData()
}
}
//
const handleTableChange: TableProps['onChange'] = (pag, filters, sorter) => {
pagination.value.current = pag.current!
pagination.value.pageSize = pag.pageSize!
//
fetchBillData()
}
//
const fetchBillData = () => {
loading.value = true
// API
setTimeout(() => {
//
const mockData: BillRecord[] = [
{
key: '1',
serialNumber: 'TX202401010001',
transactionTime: '2024-01-01 10:30:25',
transactionType: '充值',
productName: '账户充值',
transactionAmount: 100.00,
originalPrice: 100.00,
discountAmount: 0.00,
balancePayment: 0.00,
voucherDeduction: 0.00
},
{
key: '2',
serialNumber: 'TX202401010002',
transactionTime: '2024-01-01 14:20:15',
transactionType: '消费',
productName: 'GPU算力服务',
transactionAmount: -50.00,
originalPrice: 60.00,
discountAmount: 10.00,
balancePayment: 40.00,
voucherDeduction: 10.00
},
{
key: '3',
serialNumber: 'TX202401020001',
transactionTime: '2024-01-02 09:15:30',
transactionType: '充值',
productName: '账户充值',
transactionAmount: 200.00,
originalPrice: 200.00,
discountAmount: 0.00,
balancePayment: 0.00,
voucherDeduction: 0.00
},
{
key: '4',
serialNumber: 'TX202401030001',
transactionTime: '2024-01-03 16:45:20',
transactionType: '消费',
productName: '存储空间',
transactionAmount: -30.00,
originalPrice: 30.00,
discountAmount: 0.00,
balancePayment: 30.00,
voucherDeduction: 0.00
},
{
key: '5',
serialNumber: 'TX202401040001',
transactionTime: '2024-01-04 11:10:05',
transactionType: '提现',
productName: '余额提现',
transactionAmount: -100.00,
originalPrice: 100.00,
discountAmount: 0.00,
balancePayment: 100.00,
voucherDeduction: 0.00
},
{
key: '6',
serialNumber: 'TX202401050001',
transactionTime: '2024-01-05 15:30:40',
transactionType: '退款',
productName: 'GPU算力服务',
transactionAmount: 25.00,
originalPrice: 25.00,
discountAmount: 0.00,
balancePayment: 0.00,
voucherDeduction: 0.00
}
]
billData.value = mockData
pagination.value.total = mockData.length
loading.value = false
}, 500)
}
//
const goToRecharge = () => {
router.push('/recharge')
}
const goToBills = () => {
router.push('/bills')
}
const goToCoupons = () => {
router.push('/rights')
}
const goToExchange = () => {
message.info('跳转到兑换页面')
//
// router.push('/exchange')
}
</script>
<style lang="scss" scoped>
.home-page {
padding: 24px;
background: #f0f2f5;
min-height: 100vh;
}
.asset-cards {
margin-bottom: 24px;
.ant-col-8, .ant-col-16 {
display: flex;
flex-direction: column;
}
}
.card {
border-radius: 8px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
background: #fff;
border: 1px solid #e8e8e8;
height: 100%;
:deep(.ant-card-head) {
border-bottom: 1px solid #f0f0f0;
min-height: 48px;
background: #fafafa;
.ant-card-head-title {
font-size: 16px;
font-weight: 600;
padding: 12px 0;
color: #333;
}
}
:deep(.ant-card-body) {
padding: 24px;
}
}
//
.balance-card {
.fee-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.fee-title {
font-size: 16px;
font-weight: 600;
color: #333;
}
.fee-titleb {
font-size: 12px;
color: #1890ff;
padding: 0;
height: auto;
}
:deep(.ant-divider) {
margin: 16px 0;
}
.money {
font-size: 32px;
font-weight: 700;
color: #1890ff;
text-align: center;
margin: 20px 0 30px;
line-height: 1;
}
.money-btn {
display: flex;
justify-content: center;
gap: 16px;
div {
flex: 1;
text-align: center;
:deep(.ant-btn) {
width: 100px;
height: 36px;
border-radius: 4px;
font-weight: 500;
&.ant-btn-primary {
background: #1890ff;
border-color: #1890ff;
&:hover {
background: #40a9ff;
border-color: #40a9ff;
}
}
&:not(.ant-btn-primary) {
color: #666;
border-color: #d9d9d9;
&:hover {
color: #1890ff;
border-color: #1890ff;
}
}
}
}
}
}
//
.computing-card, .coupon-card {
margin-bottom: 16px;
&:last-child {
margin-bottom: 0;
}
}
.computing-content, .coupon-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px 0;
.amount-value {
font-size: 36px;
font-weight: 600;
color: #1890ff; //
line-height: 1;
margin-right: 8px;
}
.amount-unit {
font-size: 18px;
color: #666;
font-weight: 500;
}
.computing-actions, .coupon-actions {
margin-top: 24px;
:deep(.ant-btn) {
width: 100px;
height: 32px;
border-radius: 4px;
font-weight: 500;
&.ant-btn-primary {
background: #1890ff;
border-color: #1890ff;
&:hover {
background: #40a9ff;
border-color: #40a9ff;
}
}
}
}
}
//
.bill-section {
background: #fff;
border-radius: 8px;
padding: 24px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
border: 1px solid #e8e8e8;
}
.bill-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 1px solid #f0f0f0;
.bill-title {
font-size: 18px;
font-weight: 600;
color: #333;
margin: 0;
}
.date-range {
display: flex;
align-items: center;
.date-label {
font-size: 14px;
color: #666;
margin-right: 12px;
}
:deep(.ant-picker) {
border-radius: 4px;
border-color: #d9d9d9;
&:hover {
border-color: #40a9ff;
}
&.ant-picker-focused {
border-color: #1890ff;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}
}
}
}
.bill-table {
:deep(.ant-table) {
border-radius: 6px;
overflow: hidden;
border: 1px solid #f0f0f0;
.ant-table-thead > tr > th {
background: #fafafa;
font-weight: 600;
color: #333;
padding: 12px 16px;
border-bottom: 1px solid #f0f0f0;
&:not(:last-child) {
border-right: 1px solid #f0f0f0;
}
}
.ant-table-tbody > tr > td {
padding: 12px 16px;
border-bottom: 1px solid #f0f0f0;
&:not(:last-child) {
border-right: 1px solid #f0f0f0;
}
&:hover {
background: #fafafa;
}
}
.ant-table-tbody > tr:last-child > td {
border-bottom: none;
}
}
.serial-number {
font-family: 'Courier New', monospace;
color: #1890ff;
font-weight: 500;
}
.amount-positive {
color: #52c41a;
font-weight: 500;
}
.amount-negative {
color: #ff4d4f;
font-weight: 500;
}
}
//
@media (max-width: 768px) {
.home-page {
padding: 12px;
}
.asset-cards {
.ant-col-8, .ant-col-16 {
width: 100%;
}
.ant-col-8 {
margin-bottom: 16px;
}
}
.bill-header {
flex-direction: column;
align-items: stretch;
gap: 16px;
.date-range {
justify-content: space-between;
:deep(.ant-picker) {
width: 100%;
}
}
}
.money {
font-size: 28px;
}
.computing-content, .coupon-content {
.amount-value {
font-size: 32px;
}
}
}
</style>

View File

@ -60,20 +60,33 @@
</div> </div>
</div> </div>
<a-button <div class="invite-actions">
type="primary" <a-button
class="generate-btn" type="primary"
@click="generateInviteLink" class="generate-btn"
> @click="generateInviteLink"
<template #icon> >
<PlusOutlined /> <template #icon>
</template> <PlusOutlined />
生成邀请链接 </template>
</a-button> 生成邀请链接
</a-button>
<!-- 新增活动规则链接 -->
<a-button
type="link"
class="rules-link"
@click="goToRules"
>
<template #icon>
<QuestionCircleOutlined />
</template>
查看活动规则
</a-button>
</div>
</div> </div>
</a-col> </a-col>
<!-- 右侧活动规则 -->
</a-row> </a-row>
</a-card> </a-card>
@ -167,13 +180,13 @@
</div> </div>
</div> </div>
<a-divider /> <!-- <a-divider /> -->
<div class="fee-links"> <!-- <div class="fee-links">
<a-button type="link" class="fee-link" @click="goToOrders">我的订单></a-button> <a-button type="link" class="fee-link" @click="goToOrders">我的订单></a-button>
<a-button type="link" class="fee-link" @click="goToBills">我的账单></a-button> <a-button type="link" class="fee-link" @click="goToBills">我的账单></a-button>
<a-button type="link" class="fee-link" @click="goToCoupons">我的代金券></a-button> <a-button type="link" class="fee-link" @click="goToCoupons">我的代金券></a-button>
<a-button type="link" class="fee-link" @click="goToInvoice">开发票></a-button> <a-button type="link" class="fee-link" @click="goToInvoice">开发票></a-button>
</div> </div> -->
</a-card> </a-card>
</a-col> </a-col>
</a-row> </a-row>
@ -192,7 +205,8 @@ import {
WalletOutlined, WalletOutlined,
RightOutlined, RightOutlined,
LinkOutlined, LinkOutlined,
PlusOutlined PlusOutlined,
QuestionCircleOutlined //
} from '@ant-design/icons-vue' } from '@ant-design/icons-vue'
import router from '@/router' import router from '@/router'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
@ -239,6 +253,16 @@ const generateInviteLink = () => {
// const link = await api.generateInviteLink() // const link = await api.generateInviteLink()
} }
//
const goToRules = () => {
// '/invite/rules'
// 使 window.open('/invite/rules', '_blank')
router.push('/invite/rules')
// 使
// window.open('https://your-domain.com/invite-rules', '_blank')
}
// //
const goToRecharge = () => { const goToRecharge = () => {
router.push('/recharge') router.push('/recharge')
@ -382,6 +406,13 @@ const goToInvoice = () => {
line-height: 1.6; line-height: 1.6;
} }
.invite-actions {
display: flex;
align-items: center;
gap: 16px;
margin-top: 8px;
}
.generate-btn { .generate-btn {
height: 40px; height: 40px;
font-size: 14px; font-size: 14px;
@ -408,6 +439,23 @@ const goToInvoice = () => {
} }
} }
/* 新增:活动规则链接样式 */
.rules-link {
padding: 0;
height: auto;
font-size: 14px;
color: #1890ff;
&:hover {
color: #40a9ff;
}
.anticon {
margin-right: 4px;
font-size: 14px;
}
}
/* 活动规则样式 */ /* 活动规则样式 */
.rules-section { .rules-section {
padding-left: 24px; padding-left: 24px;
@ -760,5 +808,15 @@ const goToInvoice = () => {
.rules-section { .rules-section {
padding-left: 0; padding-left: 0;
} }
.invite-actions {
flex-direction: column;
align-items: flex-start;
gap: 12px;
}
.rules-link {
margin-left: 0;
}
} }
</style> </style>

View File

@ -55,6 +55,7 @@ const menuItems: MenuItem[] = [
icon: MoneyCollectOutlined, icon: MoneyCollectOutlined,
children: [ children: [
// { path: '/layout/admin/costDetail', name: '' }, // { path: '/layout/admin/costDetail', name: '' },
{ path: '/layout/admin/myMoney', name: '费用总览' },
{ path: '/layout/admin/myOrder', name: '我的订单' }, { path: '/layout/admin/myOrder', name: '我的订单' },
{ path: '/layout/admin/flow', name: '账单明细' }, { path: '/layout/admin/flow', name: '账单明细' },
{ path: '/layout/admin/coupon', name: '优惠券(待开发)', disabled: true }, { path: '/layout/admin/coupon', name: '优惠券(待开发)', disabled: true },