This commit is contained in:
qiuyuan 2026-01-14 11:24:09 +08:00
parent 3ccfcea326
commit 60e84f5ef2

View File

@ -8,22 +8,13 @@
<a-breadcrumb-item>算力点兑换</a-breadcrumb-item> <a-breadcrumb-item>算力点兑换</a-breadcrumb-item>
</a-breadcrumb> </a-breadcrumb>
<!-- 页面标题 -->
<div class="page-header">
<h1 class="page-title">算力点兑换</h1>
<p class="page-description">使用余额兑换算力点提升计算能力</p>
</div>
<!-- 主要内容区域 -->
<div class="main-content">
<!-- 余额卡片 --> <!-- 余额卡片 -->
<a-card class="balance-card" :bordered="false"> <a-card class="balance-card" :bordered="false">
<div class="balance-info"> <div class="balance-info">
<div class="balance-item"> <div class="balance-item">
<div class="balance-label"> <div class="balance-label">
<span class="icon-wrapper">
<DollarCircleOutlined />
</span>
<span class="label-text">我的余额</span> <span class="label-text">我的余额</span>
</div> </div>
<div class="balance-value"> <div class="balance-value">
@ -33,42 +24,31 @@
</div> </div>
<div class="balance-item"> <div class="balance-item">
<div class="balance-label"> <div class="balance-label">
<span class="icon-wrapper">
<ThunderboltOutlined /> <span class="label-text">算力点</span>
</span>
<span class="label-text">当前算力点</span>
</div> </div>
<div class="balance-value"> <div class="balance-value">
<span class="points">{{ formatPoints(points) }}</span> <span class="points">{{ formatPoints(points) }}</span>
<span class="points-unit">算力点</span>
</div> </div>
</div> </div>
</div> </div>
<div class="balance-tips">
<InfoCircleOutlined />
<span>余额可用于兑换算力点算力点可用于平台计算服务</span>
</div>
</a-card> </a-card>
<!-- 兑换卡片 --> <!-- 兑换卡片 -->
<a-card class="exchange-card" title="兑换算力点"> <a-card class="exchange-card" title="兑换算力点">
<div class="exchange-content"> <div class="exchange-content">
<!-- 兑换金额选择 --> <!-- 兑换金额选择 -->
<div class="exchange-section"> <div class="exchange-section">
<h3 class="section-title">选择兑换金额</h3>
<p class="section-subtitle">请选择或输入要兑换的金额</p>
<div class="amount-options"> <div class="amount-options">
<a-button <div class="section-title">选择兑换金额</div>
v-for="option in amountOptions" <a-button v-for="option in amountOptions" :key="option.value"
:key="option.value"
:class="['amount-option', { 'selected': selectedAmount === option.value }]" :class="['amount-option', { 'selected': selectedAmount === option.value }]"
@click="selectAmount(option.value)" @click="selectAmount(option.value)" size="large">
size="large"
>
<div class="amount-option-content"> <div class="amount-option-content">
<div class="amount-number">¥{{ option.value }}</div> <div class="amount-number">{{ option.value }}</div>
<div class="amount-points">= {{ option.value }} 算力点</div>
</div> </div>
</a-button> </a-button>
</div> </div>
@ -76,24 +56,14 @@
<!-- 自定义输入 --> <!-- 自定义输入 -->
<div class="custom-amount"> <div class="custom-amount">
<a-input-group compact> <a-input-group compact>
<a-input <a-input v-model:value="customAmount" placeholder="输入其他金额" size="large" style="width: calc(100% - 120px)"
v-model:value="customAmount" @change="handleCustomAmountChange" :disabled="loading" />
placeholder="输入其他金额" <!-- <a-button type="primary" size="large" style="width: 120px" :disabled="!isCustomAmountValid || loading"
size="large" @click="handleCustomAmountConfirm">
style="width: calc(100% - 120px)"
@change="handleCustomAmountChange"
:disabled="loading"
/>
<a-button
type="primary"
size="large"
style="width: 120px"
:disabled="!isCustomAmountValid || loading"
@click="handleCustomAmountConfirm"
>
确认 确认
</a-button> </a-button> -->
</a-input-group> </a-input-group>
<p class="input-name">用户自定义输入算力点数量</p>
<div v-if="customAmountError" class="error-text"> <div v-if="customAmountError" class="error-text">
<ExclamationCircleOutlined /> <ExclamationCircleOutlined />
{{ customAmountError }} {{ customAmountError }}
@ -148,7 +118,8 @@
</div> </div>
<div class="preview-item"> <div class="preview-item">
<span class="preview-label">兑换后算力点</span> <span class="preview-label">兑换后算力点</span>
<span class="preview-value points-value">{{ formatPoints(points + selectedExchangeAmount) }} 算力点</span> <span class="preview-value points-value">{{ formatPoints(points + selectedExchangeAmount) }}
算力点</span>
</div> </div>
</div> </div>
</div> </div>
@ -167,38 +138,48 @@
<!-- 操作按钮 --> <!-- 操作按钮 -->
<div class="action-buttons"> <div class="action-buttons">
<a-button <a-button type="primary" size="large" :loading="loading" :disabled="!canExchange" @click="handleExchange"
type="primary" class="exchange-button">
size="large" <template #icon>
:loading="loading" <ThunderboltOutlined />
:disabled="!canExchange" </template>
@click="handleExchange"
class="exchange-button"
>
<template #icon><ThunderboltOutlined /></template>
确认兑换 确认兑换
</a-button> </a-button>
<a-button <a-button size="large" @click="handleCancel" :disabled="loading" class="cancel-button">
size="large"
@click="handleCancel"
:disabled="loading"
class="cancel-button"
>
取消 取消
</a-button> </a-button>
</div> </div>
</div> </div>
</a-card> </a-card>
<!-- 主要内容区域 -->
<div class="main-content">
<a-card class="history-card" title="算力点兑换历史">
<a-table :columns="historyColumns" :data-source="exchangeHistory" row-key="key" :pagination="false">
<!-- 自定义状态列的渲染 -->
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'status'">
<span :style="{ color: getStatusColor(record.status) }">{{ getStatusText(record.status) }}</span>
</template>
<template v-else-if="column.key === 'amount' || column.key === 'points'">
<span>{{ formatCurrency(record.amount) }}</span>
</template>
<template v-else>
{{ record[column.dataIndex] }}
</template>
</template>
</a-table>
</a-card>
</div> </div>
<!-- 用户协议模态框 --> <!-- 用户协议模态框 -->
<a-modal <a-modal v-model:visible="agreementModalVisible" title="用户协议" width="800px" :footer="null">
v-model:visible="agreementModalVisible"
title="用户协议"
width="800px"
:footer="null"
>
<div class="agreement-content"> <div class="agreement-content">
<h3>算力点兑换服务协议</h3> <h3>算力点兑换服务协议</h3>
<p>欢迎使用算力点兑换服务在兑换算力点前请您仔细阅读以下协议内容</p> <p>欢迎使用算力点兑换服务在兑换算力点前请您仔细阅读以下协议内容</p>
@ -221,11 +202,7 @@
<a-checkbox v-model:checked="modalAgreementChecked"> <a-checkbox v-model:checked="modalAgreementChecked">
我已阅读并同意以上协议 我已阅读并同意以上协议
</a-checkbox> </a-checkbox>
<a-button <a-button type="primary" @click="handleAgreementConfirm" :disabled="!modalAgreementChecked">
type="primary"
@click="handleAgreementConfirm"
:disabled="!modalAgreementChecked"
>
确认并关闭 确认并关闭
</a-button> </a-button>
</div> </div>
@ -235,7 +212,7 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive, computed, onMounted } from 'vue' import { ref, computed, onMounted } from 'vue'
import { import {
DollarCircleOutlined, DollarCircleOutlined,
ThunderboltOutlined, ThunderboltOutlined,
@ -245,47 +222,21 @@ import {
SafetyOutlined, SafetyOutlined,
CloseOutlined CloseOutlined
} from '@ant-design/icons-vue' } from '@ant-design/icons-vue'
import { message, Modal } from 'ant-design-vue' import { message, Modal, Divider } from 'ant-design-vue'
// //
const balance = ref(3568.50) const balance = ref(3568.5)
const points = ref(1250) const points = ref(1250)
// //
const amountOptions = ref([ const amountOptions = ref([
{ value: 100, label: '100元' }, { value: 100, label: '100' },
{ value: 200, label: '200元' }, { value: 200, label: '200' },
{ value: 500, label: '500元' }, { value: 1000, label: '1000' },
{ value: 1000, label: '1000元' }, { value: 5000, label: '5000' }
{ value: 2000, label: '2000元' },
{ value: 5000, label: '5000元' }
])
//
const selectedAmount = ref(0)
const customAmount = ref('')
const customAmountError = ref('')
//
const agreementChecked = ref(false)
const showAgreementError = ref(false)
//
const loading = ref(false)
//
const agreementModalVisible = ref(false)
const modalAgreementChecked = ref(false)
//
const exchangeHistory = ref([
{ key: 1, amount: 1000, points: 1000, time: '2024-03-15 14:30:22', status: 'success' },
{ key: 2, amount: 500, points: 500, time: '2024-03-10 09:15:45', status: 'success' },
{ key: 3, amount: 2000, points: 2000, time: '2024-03-05 16:20:33', status: 'success' },
{ key: 4, amount: 100, points: 100, time: '2024-02-28 11:45:12', status: 'success' },
{ key: 5, amount: 5000, points: 5000, time: '2024-02-20 13:05:27', status: 'success' }
]) ])
// columns customRender
const historyColumns = [ const historyColumns = [
{ {
title: '兑换金额', title: '兑换金额',
@ -312,6 +263,31 @@ const historyColumns = [
} }
] ]
//
const selectedAmount = ref(0)
const customAmount = ref('')
const customAmountError = ref('')
//
const agreementChecked = ref(false)
const showAgreementError = ref(false)
//
const loading = ref(false)
//
const agreementModalVisible = ref(false)
const modalAgreementChecked = ref(false)
//
const exchangeHistory = ref([
{ key: 1, amount: 1000, points: 1000, time: '2024-03-15 14:30:22', status: 'success' },
{ key: 2, amount: 500, points: 500, time: '2024-03-10 09:15:45', status: 'success' },
{ key: 3, amount: 2000, points: 2000, time: '2024-03-05 16:20:33', status: 'success' },
{ key: 4, amount: 100, points: 100, time: '2024-02-28 11:45:12', status: 'success' },
{ key: 5, amount: 5000, points: 5000, time: '2024-02-20 13:05:27', status: 'success' }
])
// //
const selectedExchangeAmount = computed(() => { const selectedExchangeAmount = computed(() => {
if (selectedAmount.value > 0) { if (selectedAmount.value > 0) {
@ -447,11 +423,9 @@ const performExchange = () => {
// API // API
setTimeout(() => { setTimeout(() => {
//
balance.value -= selectedExchangeAmount.value balance.value -= selectedExchangeAmount.value
points.value += selectedExchangeAmount.value points.value += selectedExchangeAmount.value
//
const now = new Date() const now = new Date()
const timeStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}` const timeStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`
@ -463,10 +437,8 @@ const performExchange = () => {
status: 'success' status: 'success'
}) })
//
clearSelection() clearSelection()
agreementChecked.value = false agreementChecked.value = false
loading.value = false loading.value = false
message.success(`兑换成功!获得 ${selectedExchangeAmount.value} 算力点`) message.success(`兑换成功!获得 ${selectedExchangeAmount.value} 算力点`)
@ -480,11 +452,6 @@ const handleCancel = () => {
showAgreementError.value = false showAgreementError.value = false
} }
//
const formatTime = (timeStr) => {
return timeStr
}
// //
const getStatusColor = (status) => { const getStatusColor = (status) => {
const colors = { const colors = {
@ -505,14 +472,13 @@ const getStatusText = (status) => {
return texts[status] || status return texts[status] || status
} }
//
onMounted(() => { onMounted(() => {
//
console.log('页面加载完成') console.log('页面加载完成')
}) })
</script> </script>
<style scoped> <style scoped>
/* 你的样式保持不变 */
.points-exchange-page { .points-exchange-page {
padding: 20px; padding: 20px;
background-color: #f0f2f5; background-color: #f0f2f5;
@ -540,10 +506,7 @@ onMounted(() => {
margin: 0; margin: 0;
} }
.main-content { .main-content {}
max-width: 1200px;
margin: 0 auto;
}
.balance-card { .balance-card {
margin-bottom: 20px; margin-bottom: 20px;
@ -581,24 +544,25 @@ onMounted(() => {
} }
.label-text { .label-text {
font-size: 14px; font-size: 20px;
color: rgba(0, 0, 0, 0.45); font-weight: 500;
color: rgba(56, 56, 56, 1);
} }
.balance-value { .balance-value {
font-size: 28px; font-size: 18px;
font-weight: 600; font-weight: 600;
color: rgba(0, 0, 0, 0.85); color: rgba(0, 0, 0, 0.85);
} }
.balance-value .currency { .balance-value .currency {
font-size: 20px; font-size: 20px;
color: #52c41a; color: rgba(56, 56, 56, 1);
margin-right: 4px; margin-right: 4px;
} }
.balance-value .points { .balance-value .points {
color: #722ed1; color: rgba(56, 56, 56, 1);
} }
.balance-value .points-unit { .balance-value .points-unit {
@ -648,8 +612,8 @@ onMounted(() => {
.amount-options { .amount-options {
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(8, 1fr);
gap: 16px; gap: 6px;
margin-bottom: 24px; margin-bottom: 24px;
} }
@ -661,7 +625,7 @@ onMounted(() => {
.amount-option { .amount-option {
height: auto !important; height: auto !important;
padding: 16px !important; /* padding: 6px !important; */
border-radius: 8px !important; border-radius: 8px !important;
border: 2px solid #f0f0f0 !important; border: 2px solid #f0f0f0 !important;
background: #fff !important; background: #fff !important;
@ -696,7 +660,24 @@ onMounted(() => {
} }
.custom-amount { .custom-amount {
width: 460px;
margin-bottom: 24px; margin-bottom: 24px;
margin-left: 170px;
input {
height: 45px;
}
.input-name {
width: 350px;
text-align: center;
font-size: 14px;
font-weight: 400;
color: rgba(166, 166, 166, 1);
height: 35px;
line-height: 35px;
}
} }
.error-text { .error-text {
@ -888,7 +869,6 @@ onMounted(() => {
border-top: 1px solid #f0f0f0; border-top: 1px solid #f0f0f0;
} }
/* 加载状态 */
:deep(.ant-btn-loading) { :deep(.ant-btn-loading) {
opacity: 0.8; opacity: 0.8;
} }