feat: 完善移动端会员业务流程

This commit is contained in:
richjohnrambo
2026-10-13 14:19:55 +08:00
parent 32c6238751
commit b2ebea4c80
59 changed files with 1516 additions and 470 deletions
+66 -32
View File
@@ -43,38 +43,38 @@
</div>
</AsyncState>
<form v-else-if="formType === 'bank'" class="m-plain-form" @submit.prevent="saveBank">
<form v-else-if="formType === 'bank'" class="m-plain-form m-bank-form" @submit.prevent="saveBank">
<label
><span>姓名</span><input v-model.trim="bank.holder_name" placeholder="请输入姓名"
/></label>
<label
><span>身份证号</span
><input v-model.trim="bank.identity_no" maxlength="18" placeholder="请输入你的身份证号"
/></label>
<div class="m-bank-form__divider"></div>
<label
><span>银行卡号</span
><input v-model.trim="bank.account_no" inputmode="numeric" placeholder="请输入银行卡号"
><input v-model.trim="bank.account_no" inputmode="numeric" placeholder="请输入你的银行卡号"
/></label>
<label
><span>开户行</span><input v-model.trim="bank.bank_name" placeholder="请输入开户行"
/></label>
<label
><span>银行编码</span><input v-model.trim="bank.bank_code" placeholder="例如 ICBC"
/></label>
<label
><span>预留手机号</span
><input
v-model.trim="bank.reserved_phone"
inputmode="numeric"
maxlength="11"
placeholder="请输入预留手机号(选填)"
/></label>
<label
><span>交易密码</span
><input
v-model="bank.trade_password"
type="password"
inputmode="numeric"
maxlength="6"
placeholder="请输入 6 位交易密码"
/></label>
<p class="m-form-hint">微信、支付宝二维码上传能力将在上传接口开放后提供。</p>
<section class="m-qr-field">
<h3>微信二维码</h3>
<label class="m-qr-upload">
<input type="file" accept="image/jpeg,image/png,image/webp" @change="uploadQRCode('wechat', $event)" />
<img v-if="qr.wechat.url" :src="safeImage(qr.wechat.url)" alt="微信二维码" />
<span v-else><n-icon :component="CameraOutline" /><b>{{ qr.wechat.uploading ? '上传中...' : '点击上传' }}</b></span>
</label>
</section>
<section class="m-qr-field">
<h3>支付宝二维码</h3>
<label class="m-qr-upload">
<input type="file" accept="image/jpeg,image/png,image/webp" @change="uploadQRCode('alipay', $event)" />
<img v-if="qr.alipay.url" :src="safeImage(qr.alipay.url)" alt="支付宝二维码" />
<span v-else><n-icon :component="CameraOutline" /><b>{{ qr.alipay.uploading ? '上传中...' : '点击上传' }}</b></span>
</label>
</section>
<p v-if="error" class="m-form-error">{{ error }}</p
><button class="m-primary-btn" :disabled="submitting">{{
submitting ? '提交中...' : '确认绑定'
@@ -208,6 +208,7 @@
import { computed, onMounted, reactive, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import {
CameraOutline,
ChevronForwardOutline,
KeyOutline,
LockClosedOutline,
@@ -239,14 +240,16 @@
const content = ref<any>();
const resetPassword = ref('');
const bank = reactive({
account_type: 'bank_card',
bank_code: '',
bank_name: '',
holder_name: '',
identity_no: '',
account_no: '',
reserved_phone: '',
trade_password: '',
qr_attachment_id: 0,
wechat_qr_attachment_id: 0,
alipay_qr_attachment_id: 0,
});
const qr = reactive({
wechat: { uploading: false, url: '' },
alipay: { uploading: false, url: '' },
});
const trade = reactive({ login_password: '', old_trade_password: '', new_trade_password: '' });
const loginPassword = reactive({ old_password: '', new_password: '', confirm_password: '' });
@@ -266,24 +269,55 @@
error.value = '';
if (
!bank.holder_name ||
!/^[1-9]\d{14}(?:\d{2}[\dXx])?$/.test(bank.identity_no.replace(/[ -]/g, '')) ||
!/^[0-9 -]{8,36}$/.test(bank.account_no) ||
!bank.bank_name ||
!/^[0-9]{6}$/.test(bank.trade_password)
!bank.wechat_qr_attachment_id ||
!bank.alipay_qr_attachment_id
) {
error.value = '请完整填写姓名、银行卡、开户行和 6 位交易密码';
error.value = '请完整填写绑卡信息并上传微信、支付宝二维码';
return;
}
submitting.value = true;
try {
await request({ url: '/v1/payment-accounts', method: 'POST', data: bank });
window.$message?.success('提交成功,等待后台核验');
router.back();
window.$message?.success('银行卡绑定成功');
await router.replace('/app/profile/withdrawal');
} catch (err) {
error.value = errorText(err);
} finally {
submitting.value = false;
}
}
async function uploadQRCode(kind: 'wechat' | 'alipay', event: Event) {
const input = event.target as HTMLInputElement;
const file = input.files?.[0];
input.value = '';
if (!file) return;
if (!['image/jpeg', 'image/png', 'image/webp'].includes(file.type) || file.size > 5 * 1024 * 1024) {
error.value = '二维码仅支持 5MB 以内的 JPG、PNG 或 WebP 图片';
return;
}
const target = qr[kind];
target.uploading = true;
error.value = '';
try {
const form = new FormData();
form.append('file', file);
const uploaded = await request<{ id: number; url: string }>({
url: '/v1/attachments/images',
method: 'POST',
data: form,
});
target.url = uploaded.url;
if (kind === 'wechat') bank.wechat_qr_attachment_id = uploaded.id;
else bank.alipay_qr_attachment_id = uploaded.id;
} catch (err) {
error.value = errorText(err);
} finally {
target.uploading = false;
}
}
async function saveTradePassword() {
error.value = '';
if (!/^\d{6}$/.test(trade.new_trade_password) || trade.login_password.length < 6) {