Files
verify/frontend/src/pages/developer/agent-apps/[id]/recharge.vue
T
2026-04-27 17:22:56 +08:00

186 lines
5.1 KiB
Vue

<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { onMounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { toast } from 'vue-sonner'
import { BasicPage } from '@/components/global-layout'
const route = useRoute()
const router = useRouter()
const API_BASE = 'http://localhost:8080/api/v1'
const loading = ref(true)
const saving = ref(false)
const currentBalance = ref(0)
const agentAppName = ref('')
const rechargeAmount = ref(0)
async function fetchAgentApp() {
loading.value = true
try {
const token = localStorage.getItem('token')
const response = await fetch(`${API_BASE}/dev/agent-apps/${route.params.id}`, {
headers: { Authorization: `Bearer ${token}` },
})
const data = await response.json()
if (data.code === 200 && data.agent_app) {
currentBalance.value = data.agent_app.balance
agentAppName.value = `${data.agent_app.agent_name} - ${data.agent_app.app_name}`
}
else {
toast.error('获取授权信息失败')
router.push('/developer/agent-apps')
}
}
catch (error) {
console.error('获取授权信息失败:', error)
toast.error('获取授权信息失败')
router.push('/developer/agent-apps')
}
finally {
loading.value = false
}
}
async function handleSubmit() {
if (rechargeAmount.value <= 0) {
toast.error('请输入有效的充值金额')
return
}
saving.value = true
try {
const token = localStorage.getItem('token')
const response = await fetch(`${API_BASE}/dev/agent-apps/${route.params.id}`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
balance: currentBalance.value + rechargeAmount.value,
}),
})
const data = await response.json()
if (data.code === 200) {
toast.success('充值成功')
router.push('/developer/agent-apps')
}
else {
toast.error(data.message || '充值失败')
}
}
catch (error) {
console.error('充值失败:', error)
toast.error('充值失败')
}
finally {
saving.value = false
}
}
function goBack() {
router.push('/developer/agent-apps')
}
const quickAmounts = [100, 500, 1000, 5000]
function setAmount(amount: number) {
rechargeAmount.value = amount
}
onMounted(() => {
fetchAgentApp()
})
</script>
<template>
<BasicPage
title="充值余额"
description="为代理商充值余额"
>
<template #actions>
<UiButton variant="outline" @click="goBack">
<Icon icon="lucide:arrow-left" class="mr-2 h-4 w-4" />
返回
</UiButton>
</template>
<div v-if="loading" class="flex items-center justify-center py-12">
<Icon icon="lucide:loader-2" class="h-8 w-8 animate-spin text-muted-foreground" />
</div>
<div v-else class="max-w-2xl">
<UiCard>
<UiCardHeader>
<UiCardTitle>充值信息</UiCardTitle>
<UiCardDescription>
{{ agentAppName }}
</UiCardDescription>
</UiCardHeader>
<UiCardContent class="space-y-6">
<div class="space-y-2">
<UiLabel>当前余额</UiLabel>
<div class="text-3xl font-bold text-primary">
¥{{ currentBalance.toFixed(2) }}
</div>
</div>
<div class="space-y-2">
<UiLabel for="amount">
充值金额
</UiLabel>
<UiInput
id="amount"
v-model.number="rechargeAmount"
type="number"
min="0"
step="0.01"
placeholder="请输入充值金额"
/>
</div>
<div class="flex flex-wrap gap-2">
<UiButton
v-for="amount in quickAmounts"
:key="amount"
variant="outline"
size="sm"
@click="setAmount(amount)"
>
¥{{ amount }}
</UiButton>
</div>
<div v-if="rechargeAmount > 0" class="p-4 bg-muted rounded-lg">
<div class="flex justify-between text-sm">
<span>当前余额</span>
<span>¥{{ currentBalance.toFixed(2) }}</span>
</div>
<div class="flex justify-between text-sm mt-1">
<span>充值金额</span>
<span class="text-green-600">+¥{{ rechargeAmount.toFixed(2) }}</span>
</div>
<UiSeparator class="my-2" />
<div class="flex justify-between font-medium">
<span>充值后余额</span>
<span>¥{{ (currentBalance + rechargeAmount).toFixed(2) }}</span>
</div>
</div>
</UiCardContent>
<UiCardFooter class="flex justify-end gap-2">
<UiButton variant="outline" @click="goBack">
取消
</UiButton>
<UiButton :disabled="saving || rechargeAmount <= 0" @click="handleSubmit">
<Icon v-if="saving" icon="lucide:loader-2" class="mr-2 h-4 w-4 animate-spin" />
确认充值
</UiButton>
</UiCardFooter>
</UiCard>
</div>
</BasicPage>
</template>