feat: 更新银行卡管理功能,添加银行卡和删除银行卡的逻辑,优化API请求方式

This commit is contained in:
2025-12-17 01:31:17 +07:00
parent 88b05581b5
commit 3cdb71effc
14 changed files with 564 additions and 29 deletions

View File

@@ -0,0 +1,192 @@
<script lang='ts' setup>
import type { GenericObject } from "vee-validate";
import { toastController } from "@ionic/vue";
import { toTypedSchema } from "@vee-validate/yup";
import { informationCircle, shieldCheckmark } from "ionicons/icons";
import { ErrorMessage, Field, Form } from "vee-validate";
import * as yup from "yup";
import { client, safeClient } from "@/api";
const { t } = useI18n();
const router = useRouter();
// 银行列表数据
const bankList = [
{ code: "BOC", name: "中国银行" },
{ code: "CMB", name: "招商银行" },
{ code: "ICBC", name: "工商银行" },
{ code: "CCB", name: "建设银行" },
{ code: "ABC", name: "农业银行" },
{ code: "BOCOM", name: "交通银行" },
{ code: "PSBC", name: "邮储银行" },
{ code: "CITIC", name: "中信银行" },
{ code: "CEB", name: "光大银行" },
{ code: "CMBC", name: "民生银行" },
];
// 表单验证 Schema
const schema = toTypedSchema(
yup.object({
bankName: yup.string().required("请选择银行"),
accountNumber: yup
.string()
.required("请输入银行卡号"),
accountName: yup.string().required("请输入持卡人姓名"),
}),
);
async function handleSubmit(values: GenericObject) {
try {
await safeClient(() => client.api.bank_account.post({
bankName: values.bankName,
accountNumber: values.accountNumber,
accountName: values.accountName,
}));
const toast = await toastController.create({
message: "银行卡添加成功",
duration: 2000,
position: "bottom",
color: "success",
});
await toast.present();
router.back();
}
catch (error) {
console.error("添加银行卡失败:", error);
}
}
// 格式化银行卡号显示
function formatCardNumber(value: string) {
if (!value)
return value;
const numbers = value.replace(/\D/g, "");
return numbers.replace(/(\d{4})(?=\d)/g, "$1 ");
}
</script>
<template>
<IonPage>
<ion-header>
<ion-toolbar class="ui-toolbar">
<ion-back-button slot="start" />
<ion-title>添加银行卡</ion-title>
</ion-toolbar>
</ion-header>
<IonContent :fullscreen="true">
<div class="min-h-full">
<div class="p-4">
<!-- 表单说明 -->
<div class="border border-blue-200 dark:border-blue-900 rounded-xl p-4 mb-6">
<div class="flex items-start gap-3">
<ion-icon
:icon="informationCircle"
class="text-blue-500 text-xl mt-0.5 shrink-0"
/>
<div class="text-sm text-blue-700 dark:text-blue-300">
<p class="font-medium mb-1">
温馨提示
</p>
<p class="leading-relaxed">
为了保障您的资金安全请确保银行卡信息真实有效添加的银行卡将用于充值和提现操作
</p>
</div>
</div>
</div>
<Form :validation-schema="schema" class="space-y-5" @submit="handleSubmit">
<div class="space-y-4">
<Field v-slot="{ field }" name="bankName">
<ion-select class="ui-select" interface="action-sheet" toggle-icon="" v-bind="field" label="银行卡" placeholder="请选择您的银行">
<ion-select-option v-for="item in bankList" :key="item.code" :value="item.code">
{{ item.name }}
</ion-select-option>
</ion-select>
</Field>
<div>
<Field name="accountNumber">
<template #default="{ field }">
<ui-input-label
v-bind="field"
label="银行卡号"
placeholder="请输入银行卡号"
type="text"
inputmode="numeric"
:maxlength="23"
helper-text="支持16-19位银行卡号"
required
@input="(e:any) => field.value = formatCardNumber(e.target.value)"
/>
</template>
</Field>
<ErrorMessage name="accountNumber" class="text-red-500 text-sm mt-1" />
</div>
<div>
<Field name="accountName">
<template #default="{ field }">
<ui-input-label
v-bind="field"
label="持卡人姓名"
placeholder="请输入持卡人姓名"
type="text"
helper-text="请输入银行卡开户时的真实姓名"
required
/>
</template>
</Field>
<ErrorMessage name="accountName" class="text-red-500 text-sm mt-1" />
</div>
<div class="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-xl p-4">
<div class="flex gap-3">
<ion-icon
:icon="shieldCheckmark"
class="text-amber-500 text-xl mt-0.5 shrink-0"
/>
<div class="text-sm text-amber-700 dark:text-amber-300">
<p class="font-medium mb-1">
安全保障
</p>
<ul class="space-y-1 text-xs leading-relaxed">
<li> 所有银行卡信息均经过SSL加密传输</li>
<li> 我们严格遵循银行级安全标准</li>
<li> 您的个人信息将被妥善保护</li>
</ul>
</div>
</div>
</div>
<ion-button type="submit" expand="block">
确认添加银行卡
</ion-button>
</div>
</Form>
</div>
</div>
</IonContent>
</IonPage>
</template>
<style scoped>
/* Tailwind CSS 处理所有样式 */
.ui-select {
--padding-start: 16px;
--padding-end: 16px;
border: 1px solid #d1d5db;
border-radius: 8px;
}
.ui-select.ion-invalid {
border-color: #ef4444;
}
@media (prefers-color-scheme: dark) {
.ui-select {
border-color: #4b5563;
}
}
</style>