281 lines
7.3 KiB
Vue
281 lines
7.3 KiB
Vue
<script lang='ts' setup>
|
|
import type { Treaty } from "@elysiajs/eden";
|
|
import { alertController, toastController } from "@ionic/vue";
|
|
import { addOutline, cardOutline, createOutline, logoAlipay, trashOutline } from "ionicons/icons";
|
|
import { client, safeClient } from "@/api";
|
|
|
|
const router = useRouter();
|
|
type Receipt = Treaty.Data<typeof client.api.receipt_method.get>["data"][number];
|
|
|
|
const { data } = await safeClient(client.api.receipt_method.get({ query: { offset: 0, limit: 20 } }));
|
|
|
|
async function showToast(message: string, color: "success" | "danger" | "warning" = "success") {
|
|
const toast = await toastController.create({
|
|
message,
|
|
duration: 2000,
|
|
position: "top",
|
|
color,
|
|
});
|
|
await toast.present();
|
|
}
|
|
|
|
function handleAdd() {
|
|
router.push("/payment/add");
|
|
}
|
|
|
|
function handleEdit(payment: Receipt) {
|
|
router.push(`/payment/add?id=${payment.id}`);
|
|
}
|
|
|
|
async function handleDelete(payment: Receipt) {
|
|
const alert = await alertController.create({
|
|
header: "确认删除",
|
|
message: `确定要删除这个收款方式吗?`,
|
|
buttons: [
|
|
{
|
|
text: "取消",
|
|
role: "cancel",
|
|
},
|
|
{
|
|
text: "删除",
|
|
role: "destructive",
|
|
handler: async () => {
|
|
const index = data.value?.data.findIndex(item => item.id === payment.id);
|
|
if (index && index > -1) {
|
|
data.value?.data.splice(index, 1);
|
|
}
|
|
await safeClient(client.api.receipt_method({ id: payment.id }).delete());
|
|
await showToast("删除成功");
|
|
},
|
|
},
|
|
],
|
|
});
|
|
|
|
await alert.present();
|
|
}
|
|
|
|
function getPaymentIcon(type: Receipt["type"]) {
|
|
return type === "bank_card" ? cardOutline : logoAlipay;
|
|
}
|
|
|
|
function getPaymentTypeName(type: Receipt["type"]) {
|
|
return type === "bank_card" ? "银行卡" : "支付宝";
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<ion-page>
|
|
<ion-header class="ion-no-border">
|
|
<ion-toolbar class="ion-toolbar">
|
|
<ion-buttons slot="start">
|
|
<back-button />
|
|
</ion-buttons>
|
|
<ion-title>收款方式</ion-title>
|
|
<ion-buttons slot="end">
|
|
<ion-button @click="handleAdd">
|
|
<ion-icon slot="icon-only" :icon="addOutline" />
|
|
</ion-button>
|
|
</ion-buttons>
|
|
</ion-toolbar>
|
|
</ion-header>
|
|
|
|
<ion-content>
|
|
<!-- 空状态 -->
|
|
<div v-if="data?.data?.length === 0" class="empty-state">
|
|
<empty title="暂无收款方式">
|
|
<template #icon>
|
|
<ion-icon :icon="cardOutline" class="empty-icon" />
|
|
</template>
|
|
<template #extra>
|
|
<ion-button class="add-button" @click="handleAdd">
|
|
<ion-icon slot="start" :icon="addOutline" />
|
|
添加收款方式
|
|
</ion-button>
|
|
</template>
|
|
</empty>
|
|
</div>
|
|
|
|
<div v-else class="ion-padding">
|
|
<div class="space-y-3">
|
|
<div
|
|
v-for="payment in data?.data"
|
|
:key="payment.id"
|
|
class="payment-card"
|
|
>
|
|
<!-- 收款方式信息 -->
|
|
<div class="payment-info">
|
|
<div class="flex items-center justify-between mb-3">
|
|
<div class="flex items-center gap-2">
|
|
<ion-icon
|
|
:icon="getPaymentIcon(payment.type)"
|
|
class="text-2xl"
|
|
:class="payment.type === 'alipay' ? 'text-[#1677ff]' : 'text-primary'"
|
|
/>
|
|
<span class="payment-type">{{ getPaymentTypeName(payment.type) }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="payment-details">
|
|
<div class="detail-row">
|
|
<span class="label">姓名</span>
|
|
<span class="value">{{ payment.fullName }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="label">账号</span>
|
|
<span class="value">{{ payment.bankCardNumber || payment.alipayAccount }}</span>
|
|
</div>
|
|
<div v-if="payment.type === 'bank_card' && payment.bankName" class="detail-row">
|
|
<span class="label">银行</span>
|
|
<span class="value">{{ payment.bankName }}</span>
|
|
</div>
|
|
<div v-if="payment.type === 'bank_card' && payment.bankBranchName" class="detail-row">
|
|
<span class="label">开户行</span>
|
|
<span class="value">{{ payment.bankBranchName }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 操作按钮 -->
|
|
<div class="payment-actions">
|
|
<div class="flex gap-2">
|
|
<ion-button
|
|
fill="clear"
|
|
size="small"
|
|
color="medium"
|
|
@click="handleEdit(payment)"
|
|
>
|
|
<ion-icon slot="start" :icon="createOutline" />
|
|
编辑
|
|
</ion-button>
|
|
|
|
<ion-button
|
|
fill="clear"
|
|
size="small"
|
|
color="danger"
|
|
@click="handleDelete(payment)"
|
|
>
|
|
<ion-icon slot="start" :icon="trashOutline" />
|
|
删除
|
|
</ion-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 底部添加按钮 -->
|
|
<div v-if="data?.data && data.data.length > 0" class="fixed-bottom">
|
|
<ion-button expand="block" class="add-button" @click="handleAdd">
|
|
<ion-icon slot="start" :icon="addOutline" />
|
|
添加新收款方式
|
|
</ion-button>
|
|
</div>
|
|
</ion-content>
|
|
</ion-page>
|
|
</template>
|
|
|
|
<style lang='css' scoped>
|
|
.payment-card {
|
|
background: white;
|
|
border-radius: 16px;
|
|
padding: 16px;
|
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
|
}
|
|
|
|
.payment-info {
|
|
padding-bottom: 12px;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.payment-type {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: #333;
|
|
}
|
|
|
|
.default-badge {
|
|
font-size: 11px;
|
|
padding: 2px 8px;
|
|
}
|
|
|
|
.payment-details {
|
|
margin-top: 12px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.detail-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.detail-row .label {
|
|
font-size: 13px;
|
|
color: #999;
|
|
min-width: 60px;
|
|
}
|
|
|
|
.detail-row .value {
|
|
font-size: 14px;
|
|
color: #333;
|
|
font-weight: 500;
|
|
text-align: right;
|
|
flex: 1;
|
|
}
|
|
|
|
.payment-actions {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.payment-actions ion-button {
|
|
--padding-start: 8px;
|
|
--padding-end: 8px;
|
|
font-size: 13px;
|
|
text-transform: none;
|
|
}
|
|
|
|
.empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 60vh;
|
|
padding: 40px 20px;
|
|
}
|
|
|
|
.empty-icon {
|
|
font-size: 80px;
|
|
color: #ddd;
|
|
}
|
|
|
|
.add-button {
|
|
--background: linear-gradient(135deg, #c41e3a 0%, #8b1a2e 100%);
|
|
--background-activated: linear-gradient(135deg, #8b1a2e 0%, #c41e3a 100%);
|
|
--border-radius: 12px;
|
|
--padding-top: 14px;
|
|
--padding-bottom: 14px;
|
|
font-weight: 600;
|
|
font-size: 15px;
|
|
text-transform: none;
|
|
letter-spacing: 0.5px;
|
|
margin-top: 12px;
|
|
}
|
|
|
|
.fixed-bottom {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
padding: 12px 16px;
|
|
background: white;
|
|
box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.08);
|
|
z-index: 10;
|
|
padding-bottom: calc(12px + var(--ion-safe-area-bottom));
|
|
}
|
|
</style>
|