feat: 添加 dayjs 依赖并优化钱包视图,增强日期格式化和交易记录显示
This commit is contained in:
7
frontend/portal/package-lock.json
generated
7
frontend/portal/package-lock.json
generated
@@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"@primevue/themes": "^4.5.4",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"dayjs": "^1.11.19",
|
||||
"pinia": "^3.0.4",
|
||||
"primeicons": "^7.0.0",
|
||||
"primevue": "^4.5.4",
|
||||
@@ -1685,6 +1686,12 @@
|
||||
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.19",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
|
||||
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"@primevue/themes": "^4.5.4",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"dayjs": "^1.11.19",
|
||||
"pinia": "^3.0.4",
|
||||
"primeicons": "^7.0.0",
|
||||
"primevue": "^4.5.4",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="relative z-10 flex flex-col md:flex-row justify-between items-center gap-6">
|
||||
<div>
|
||||
<div class="text-blue-100 text-sm font-medium mb-1">账户余额 (元)</div>
|
||||
<div class="text-5xl font-bold font-mono">128.50</div>
|
||||
<div class="text-5xl font-bold font-mono">{{ balance.toFixed(2) }}</div>
|
||||
</div>
|
||||
<button @click="showRecharge = !showRecharge" class="px-8 py-3 bg-white text-blue-600 font-bold rounded-full shadow-sm hover:bg-blue-50 transition-all active:scale-95 cursor-pointer">
|
||||
立即充值
|
||||
@@ -44,15 +44,28 @@
|
||||
|
||||
<h3 class="font-bold text-slate-900 mb-4">支付方式</h3>
|
||||
<div class="flex gap-4 mb-8">
|
||||
<button class="flex items-center gap-2 px-6 py-3 border-2 border-blue-600 bg-blue-50 text-blue-700 rounded-lg font-medium cursor-pointer active:scale-95 transition-transform">
|
||||
<button
|
||||
@click="paymentMethod = 'wechat'"
|
||||
class="flex items-center gap-2 px-6 py-3 border-2 rounded-lg font-medium cursor-pointer active:scale-95 transition-transform"
|
||||
:class="paymentMethod === 'wechat' ? 'border-blue-600 bg-blue-50 text-blue-700' : 'border-slate-200 text-slate-600 hover:bg-white hover:border-slate-300'"
|
||||
>
|
||||
<i class="pi pi-wechat text-xl text-green-600"></i> 微信支付
|
||||
</button>
|
||||
<button class="flex items-center gap-2 px-6 py-3 border-2 border-slate-200 text-slate-600 rounded-lg hover:bg-white hover:border-slate-300 font-medium cursor-pointer active:scale-95 transition-all">
|
||||
<button
|
||||
@click="paymentMethod = 'alipay'"
|
||||
class="flex items-center gap-2 px-6 py-3 border-2 rounded-lg font-medium cursor-pointer active:scale-95 transition-transform"
|
||||
:class="paymentMethod === 'alipay' ? 'border-blue-600 bg-blue-50 text-blue-700' : 'border-slate-200 text-slate-600 hover:bg-white hover:border-slate-300'"
|
||||
>
|
||||
<i class="pi pi-alipay text-xl text-blue-500"></i> 支付宝
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button class="w-full py-4 bg-blue-600 text-white rounded-xl font-bold text-lg hover:bg-blue-700 transition-all shadow-lg shadow-blue-200 cursor-pointer active:scale-[0.98]">
|
||||
<button
|
||||
@click="handleRecharge"
|
||||
:disabled="loading"
|
||||
class="w-full py-4 bg-blue-600 text-white rounded-xl font-bold text-lg hover:bg-blue-700 transition-all shadow-lg shadow-blue-200 cursor-pointer active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<i v-if="loading" class="pi pi-spin pi-spinner mr-2"></i>
|
||||
确认支付 ¥ {{ displayAmount }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -63,15 +76,15 @@
|
||||
<i class="pi pi-history text-slate-400"></i> 交易明细
|
||||
</h3>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div v-if="transactions.length > 0" class="space-y-4">
|
||||
<div v-for="item in transactions" :key="item.id" class="flex items-center justify-between p-4 border-b border-slate-50 hover:bg-slate-50 rounded-lg transition-colors">
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="w-10 h-10 rounded-full flex items-center justify-center" :class="item.type === 'income' ? 'bg-green-100 text-green-600' : 'bg-slate-100 text-slate-500'">
|
||||
<i class="pi" :class="item.type === 'income' ? 'pi-plus' : 'pi-minus'"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold text-slate-900">{{ item.title }}</div>
|
||||
<div class="text-xs text-slate-400">{{ item.date }}</div>
|
||||
<div class="font-bold text-slate-900">{{ item.title || (item.type === 'income' ? '充值' : '消费') }}</div>
|
||||
<div class="text-xs text-slate-400">{{ formatDate(item.date) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="font-mono font-bold text-lg" :class="item.type === 'income' ? 'text-green-600' : 'text-slate-900'">
|
||||
@@ -79,6 +92,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-center py-10 text-slate-400">
|
||||
暂无交易记录
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Toast />
|
||||
@@ -86,24 +102,62 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import Toast from 'primevue/toast';
|
||||
import { useToast } from 'primevue/usetoast';
|
||||
import { userApi } from '../../api/user';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const toast = useToast();
|
||||
const showRecharge = ref(false);
|
||||
const selectedAmount = ref(50);
|
||||
const customAmount = ref('');
|
||||
const balance = ref(0);
|
||||
const transactions = ref([]);
|
||||
const loading = ref(false);
|
||||
const paymentMethod = ref('wechat');
|
||||
|
||||
const displayAmount = computed(() => {
|
||||
return customAmount.value ? Number(customAmount.value).toFixed(2) : selectedAmount.value.toFixed(2);
|
||||
});
|
||||
|
||||
// Mock Data
|
||||
const transactions = ref([
|
||||
{ id: 1, title: '购买《霸王别姬》全本', date: '2025-12-24 14:30', amount: 9.90, type: 'expense' },
|
||||
{ id: 2, title: '账户充值', date: '2025-12-20 10:00', amount: 100.00, type: 'income' },
|
||||
{ id: 3, title: '购买周边商品', date: '2025-12-15 18:20', amount: 45.00, type: 'expense' },
|
||||
{ id: 4, title: '付费专栏订阅', date: '2025-12-10 09:15', amount: 19.90, type: 'expense' },
|
||||
]);
|
||||
const formatDate = (date) => {
|
||||
return dayjs(date).format('YYYY-MM-DD HH:mm');
|
||||
};
|
||||
|
||||
const fetchWallet = async () => {
|
||||
try {
|
||||
const res = await userApi.getWallet();
|
||||
balance.value = res.balance || 0;
|
||||
transactions.value = res.transactions || [];
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch wallet:', error);
|
||||
toast.add({ severity: 'error', summary: '错误', detail: '获取钱包信息失败', life: 3000 });
|
||||
}
|
||||
};
|
||||
|
||||
const handleRecharge = async () => {
|
||||
const amount = Number(displayAmount.value);
|
||||
if (!amount || amount <= 0) {
|
||||
toast.add({ severity: 'warn', summary: '提示', detail: '请输入有效的充值金额', life: 3000 });
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
await userApi.recharge({ amount: amount, method: paymentMethod.value });
|
||||
toast.add({ severity: 'success', summary: '成功', detail: '充值成功', life: 3000 });
|
||||
showRecharge.value = false;
|
||||
fetchWallet(); // Refresh balance
|
||||
} catch (error) {
|
||||
console.error('Recharge failed:', error);
|
||||
toast.add({ severity: 'error', summary: '错误', detail: error.message || '充值失败', life: 3000 });
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchWallet();
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user