接入订单支付与钱包充值前端入口
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
confirmReturn,
|
||||
fetchHandoffRecords,
|
||||
fetchOrder,
|
||||
payOrder,
|
||||
submitHandoff,
|
||||
submitReturn,
|
||||
type HandoffRecord,
|
||||
@@ -25,6 +26,7 @@ const router = useRouter()
|
||||
const session = useSessionStore()
|
||||
const loading = ref(false)
|
||||
const cancelling = ref(false)
|
||||
const paying = ref(false)
|
||||
const handoffing = ref(false)
|
||||
const confirming = ref(false)
|
||||
const returning = ref(false)
|
||||
@@ -72,6 +74,20 @@ async function handleCancel() {
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePay() {
|
||||
if (!order.value) return
|
||||
paying.value = true
|
||||
try {
|
||||
await payOrder(order.value.id)
|
||||
ElMessage.success('支付成功,等待号主交接')
|
||||
await loadOrder()
|
||||
} catch (error) {
|
||||
ElMessage.error(readError(error, '支付失败'))
|
||||
} finally {
|
||||
paying.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSubmitHandoff() {
|
||||
if (!order.value) return
|
||||
handoffing.value = true
|
||||
@@ -210,7 +226,11 @@ function readError(error: unknown, fallback: string) {
|
||||
<div v-if="order" class="order-panel">
|
||||
<p>开始:{{ formatDateTime(order.rent_start_at, '未开始') }}</p>
|
||||
<p>预计截止:{{ formatDateTime(order.rent_end_at, '未设置') }}</p>
|
||||
<el-button v-if="order.status === 'pending_handoff'" type="danger" :loading="cancelling" @click="handleCancel">
|
||||
<p v-if="order.status === 'pending_payment'">订单待支付,支付后账号进入交接流程。</p>
|
||||
<el-button v-if="order.status === 'pending_payment' && isRenter" type="primary" :loading="paying" @click="handlePay">
|
||||
支付订单
|
||||
</el-button>
|
||||
<el-button v-if="['pending_payment', 'pending_handoff'].includes(order.status)" type="danger" :loading="cancelling" @click="handleCancel">
|
||||
取消订单并释放账号
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
import { fetchOrders, type Order } from '@/api/orders'
|
||||
import { fetchOrders, payOrder, type Order } from '@/api/orders'
|
||||
import { orderStatusLabel } from '@/utils/statusLabels'
|
||||
|
||||
const loading = ref(false)
|
||||
const orders = ref<Order[]>([])
|
||||
const payingOrderId = ref<number | null>(null)
|
||||
|
||||
onMounted(loadOrders)
|
||||
|
||||
@@ -17,6 +19,27 @@ async function loadOrders() {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePay(order: Order) {
|
||||
payingOrderId.value = order.id
|
||||
try {
|
||||
await payOrder(order.id)
|
||||
ElMessage.success('支付成功,等待号主交接')
|
||||
await loadOrders()
|
||||
} catch (error) {
|
||||
ElMessage.error(readError(error, '支付失败'))
|
||||
} finally {
|
||||
payingOrderId.value = null
|
||||
}
|
||||
}
|
||||
|
||||
function readError(error: unknown, fallback: string) {
|
||||
if (typeof error === 'object' && error && 'response' in error) {
|
||||
const response = (error as { response?: { data?: { message?: string } } }).response
|
||||
return response?.data?.message || fallback
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -24,7 +47,7 @@ async function loadOrders() {
|
||||
<div class="page-header">
|
||||
<p class="eyebrow">Orders</p>
|
||||
<h1>我的订单</h1>
|
||||
<p>跟踪待交接、使用中、待归还、申诉中和已完成订单。</p>
|
||||
<p>跟踪待支付、待交接、使用中、待归还、申诉中和已完成订单。</p>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" class="table-panel" :data="orders">
|
||||
@@ -35,8 +58,17 @@ async function loadOrders() {
|
||||
<el-table-column label="状态" width="140">
|
||||
<template #default="{ row }">{{ orderStatusLabel(row.status) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100">
|
||||
<el-table-column label="操作" width="160">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
v-if="row.status === 'pending_payment'"
|
||||
size="small"
|
||||
type="primary"
|
||||
:loading="payingOrderId === row.id"
|
||||
@click="handlePay(row)"
|
||||
>
|
||||
支付
|
||||
</el-button>
|
||||
<RouterLink :to="`/orders/${row.id}`">
|
||||
<el-button size="small">详情</el-button>
|
||||
</RouterLink>
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
import { fetchWalletBalance, fetchWalletLedger, type WalletAccount, type WalletLedger } from '@/api/wallet'
|
||||
import { fetchWalletBalance, fetchWalletLedger, rechargeWallet, type WalletAccount, type WalletLedger } from '@/api/wallet'
|
||||
import { balanceTypeLabel, ledgerDirectionLabel, walletStatusLabel } from '@/utils/statusLabels'
|
||||
import { formatDateTime } from '@/utils/time'
|
||||
|
||||
const loading = ref(false)
|
||||
const account = ref<WalletAccount | null>(null)
|
||||
const ledger = ref<WalletLedger[]>([])
|
||||
const rechargeAmount = ref(100)
|
||||
const recharging = ref(false)
|
||||
|
||||
onMounted(loadWallet)
|
||||
|
||||
@@ -21,6 +24,27 @@ async function loadWallet() {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleRecharge() {
|
||||
recharging.value = true
|
||||
try {
|
||||
account.value = await rechargeWallet(rechargeAmount.value)
|
||||
ElMessage.success('充值成功')
|
||||
await loadWallet()
|
||||
} catch (error) {
|
||||
ElMessage.error(readError(error, '充值失败'))
|
||||
} finally {
|
||||
recharging.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function readError(error: unknown, fallback: string) {
|
||||
if (typeof error === 'object' && error && 'response' in error) {
|
||||
const response = (error as { response?: { data?: { message?: string } } }).response
|
||||
return response?.data?.message || fallback
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -28,7 +52,7 @@ async function loadWallet() {
|
||||
<div class="page-header">
|
||||
<p class="eyebrow">Wallet</p>
|
||||
<h1>钱包</h1>
|
||||
<p>查看可用余额、冻结余额和不可变资金流水。当前是开发态模拟账务,不代表真实支付余额。</p>
|
||||
<p>查看可用余额、冻结余额和资金流水。</p>
|
||||
</div>
|
||||
|
||||
<div v-if="account" class="metric-grid">
|
||||
@@ -46,6 +70,12 @@ async function loadWallet() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-panel recharge-panel">
|
||||
<h2>开发充值</h2>
|
||||
<el-input-number v-model="rechargeAmount" :min="0.01" :precision="2" controls-position="right" />
|
||||
<el-button type="primary" :loading="recharging" @click="handleRecharge">充值</el-button>
|
||||
</div>
|
||||
|
||||
<el-table class="table-panel" :data="ledger">
|
||||
<el-table-column prop="ledger_no" label="流水号" min-width="220" />
|
||||
<el-table-column prop="biz_type" label="业务" width="140" />
|
||||
@@ -64,3 +94,18 @@ async function loadWallet() {
|
||||
</el-table>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.recharge-panel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.recharge-panel h2 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user