Files
mp-vue/src/views/glt/shopDealerWithdraw/components/shopDealerWithdrawEdit.vue
赵忠林 f96d4d8530 feat(dealer): 添加经销商申请管理功能
- 新增经销商申请页面,支持申请列表展示和分页查询
- 添加搜索组件,支持按客户名称、联系电话、审核状态等条件筛选
- 实现申请状态管理,包括跟进中、已签约、已取消三种状态
- 开发编辑弹窗功能,支持新增和修改申请信息
- 添加审核功能,支持批量通过和单个驳回操作
- 集成跟进记录管理,可查看历史记录并添加新的跟进内容
- 完善表单验证,包含必填字段校验和格式验证
- 优化模型定义,在相关实体中增加头像、昵称、真实姓名等字段
- 调整商品模型,将isShow字段从数字类型改为布尔类型
- 新增分销佣金相关字段,支持固定金额和百分比两种分佣类型
2026-01-28 22:37:37 +08:00

698 lines
18 KiB
Vue

<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="1000"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑提现申请' : '新增提现申请'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
>
<!-- 基本信息 -->
<a-divider orientation="left">
<span style="color: #1890ff; font-weight: 600">基本信息</span>
</a-divider>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="备注" name="comments">
<div class="text-red-500">{{ form.comments }}</div>
</a-form-item>
</a-col>
</a-row>
<!-- 收款信息 -->
<a-divider orientation="left">
<span style="color: #1890ff; font-weight: 600">收款信息</span>
</a-divider>
<!-- 微信收款信息 -->
<div v-if="form.payType === 10" class="payment-info wechat-info">
<a-alert
message="微信收款信息"
description="请确保微信账号信息准确,以免影响到账"
type="success"
show-icon
style="margin-bottom: 16px"
/>
<a-form-item label="微信号" name="wechatAccount">
<a-input
placeholder="请输入微信号"
v-model:value="form.wechatAccount"
/>
</a-form-item>
<a-form-item label="微信昵称" name="wechatName">
<a-input
placeholder="请输入微信昵称"
v-model:value="form.wechatName"
/>
</a-form-item>
</div>
<!-- 支付宝收款信息 -->
<div v-if="form.payType === 20" class="payment-info alipay-info">
<a-alert
message="支付宝收款信息"
description="请确保支付宝账号信息准确,姓名需与实名认证一致"
type="info"
show-icon
style="margin-bottom: 16px"
/>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="支付宝姓名" name="alipayName">
<a-input
placeholder="请输入支付宝实名姓名"
disabled
v-model:value="form.alipayName"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="支付宝账号" name="alipayAccount">
<a-input
placeholder="请输入支付宝账号"
disabled
v-model:value="form.alipayAccount"
/>
</a-form-item>
</a-col>
</a-row>
</div>
<!-- 银行卡收款信息 -->
<div v-if="form.payType === 30" class="payment-info bank-info">
<a-alert
message="银行卡收款信息"
description="请确保银行卡信息准确,开户名需与身份证姓名一致"
type="warning"
show-icon
style="margin-bottom: 16px"
/>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="开户行名称" name="bankName">
{{ form.bankName }}
</a-form-item>
<a-form-item label="银行开户名" name="bankAccount">
{{ form.bankAccount }}
</a-form-item>
<a-form-item label="银行卡号" name="bankCard">
{{ form.bankCard }}
</a-form-item>
</a-col>
</a-row>
</div>
<!-- 审核信息 -->
<a-divider orientation="left">
<span style="color: #1890ff; font-weight: 600">审核信息</span>
</a-divider>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="申请状态" name="applyStatus">
<a-select
v-model:value="form.applyStatus"
:disabled="form.applyStatus == 40 || form.applyStatus == 30"
placeholder="请选择申请状态"
>
<a-select-option :value="10">
<div class="status-option">
<a-tag color="orange">待审核</a-tag>
<span>等待审核</span>
</div>
</a-select-option>
<a-select-option :value="20">
<div class="status-option">
<a-tag color="success">审核通过</a-tag>
<span>审核通过</span>
</div>
</a-select-option>
<a-select-option :value="30">
<div class="status-option">
<a-tag color="error">审核驳回</a-tag>
<span>审核驳回</span>
</div>
</a-select-option>
<a-select-option :value="40">
<div class="status-option">
<a-tag>已打款</a-tag>
<span>已完成打款</span>
</div>
</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item
label="驳回原因"
name="rejectReason"
v-if="form.applyStatus === 30"
>
<a-textarea
v-model:value="form.rejectReason"
placeholder="请输入驳回原因"
:rows="3"
:maxlength="200"
show-count
/>
</a-form-item>
<a-form-item
label="上传支付凭证"
name="image"
v-if="form.applyStatus === 40"
>
<SelectFile
:placeholder="`请选择图片`"
:limit="2"
:data="files"
@done="chooseFile"
@del="onDeleteFile"
/>
</a-form-item>
</a-col>
</a-row>
<!-- 提现预览 -->
<div class="withdraw-preview" v-if="form.money && form.payType">
<a-alert
:type="getPreviewAlertType()"
:message="getPreviewText()"
show-icon
style="margin-top: 16px"
/>
</div>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, uuid } from 'ele-admin-pro';
import {
addShopDealerWithdraw,
updateShopDealerWithdraw
} from '@/api/shop/shopDealerWithdraw';
import { ShopDealerWithdraw } from '@/api/shop/shopDealerWithdraw/model';
import { FormInstance } from 'ant-design-vue/es/form';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import dayjs from 'dayjs';
import { FileRecord } from '@/api/system/file/model';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ShopDealerWithdraw | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref<boolean>(false);
const isSuccess = ref<boolean>(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
const files = ref<ItemType[]>([]);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
// 表单数据
const form = reactive<ShopDealerWithdraw>({
id: undefined,
userId: undefined,
realName: undefined,
nickname: undefined,
phone: undefined,
avatar: undefined,
money: undefined,
payType: undefined,
// 微信相关
wechatAccount: '',
wechatName: '',
// 支付宝相关
alipayName: '',
alipayAccount: '',
// 银行卡相关
bankName: '',
bankAccount: '',
bankCard: '',
// 审核相关
applyStatus: 10,
auditTime: undefined,
rejectReason: '',
platform: '',
comments: '',
tenantId: undefined,
createTime: undefined,
updateTime: undefined
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
userId: [
{
required: true,
message: '请输入分销商用户ID',
trigger: 'blur'
}
],
money: [
{
required: true,
message: '请输入提现金额',
trigger: 'blur'
},
{
validator: (rule: any, value: any) => {
if (value && value <= 0) {
return Promise.reject('提现金额必须大于0');
}
return Promise.resolve();
},
trigger: 'blur'
}
],
payType: [
{
required: true,
message: '请选择打款方式',
trigger: 'change'
}
],
platform: [
{
required: true,
message: '请选择来源平台',
trigger: 'change'
}
],
// 微信验证
wechatAccount: [
{
validator: (rule: any, value: any) => {
if (form.payType === 10 && !value) {
return Promise.reject('请输入微信号');
}
return Promise.resolve();
},
trigger: 'blur'
}
],
wechatName: [
{
validator: (rule: any, value: any) => {
if (form.payType === 10 && !value) {
return Promise.reject('请输入微信昵称');
}
return Promise.resolve();
},
trigger: 'blur'
}
],
// 支付宝验证
alipayName: [
{
validator: (rule: any, value: any) => {
if (form.payType === 20 && !value) {
return Promise.reject('请输入支付宝姓名');
}
return Promise.resolve();
},
trigger: 'blur'
}
],
alipayAccount: [
{
validator: (rule: any, value: any) => {
if (form.payType === 20 && !value) {
return Promise.reject('请输入支付宝账号');
}
return Promise.resolve();
},
trigger: 'blur'
}
],
// 银行卡验证
bankName: [
{
validator: (rule: any, value: any) => {
if (form.payType === 30 && !value) {
return Promise.reject('请输入开户行名称');
}
return Promise.resolve();
},
trigger: 'blur'
}
],
bankAccount: [
{
validator: (rule: any, value: any) => {
if (form.payType === 30 && !value) {
return Promise.reject('请输入银行开户名');
}
return Promise.resolve();
},
trigger: 'blur'
}
],
bankCard: [
{
validator: (rule: any, value: any) => {
if (form.payType === 30 && !value) {
return Promise.reject('请输入银行卡号');
}
if (form.payType === 30 && value && !/^\d{16,19}$/.test(value)) {
return Promise.reject('银行卡号格式不正确');
}
return Promise.resolve();
},
trigger: 'blur'
}
],
applyStatus: [
{
required: true,
message: '请选择申请状态',
trigger: 'change'
}
],
rejectReason: [
{
validator: (rule: any, value: any) => {
if (form.applyStatus === 30 && !value) {
return Promise.reject('驳回时必须填写驳回原因');
}
return Promise.resolve();
},
trigger: 'blur'
}
],
image: [
{
required: true,
message: '请上传打款凭证',
trigger: 'change'
}
]
});
/* 打款方式改变时的处理 */
const onPayTypeChange = (e: any) => {
const payType = e.target.value;
// 清空其他支付方式的信息
if (payType !== 10) {
form.alipayAccount = '';
form.alipayName = '';
}
if (payType !== 20) {
form.alipayName = '';
form.alipayAccount = '';
}
if (payType !== 30) {
form.bankName = '';
form.bankAccount = '';
form.bankCard = '';
}
};
const chooseFile = (data: FileRecord) => {
files.value.push({
uid: data.id,
url: data.url,
status: 'done'
});
form.image = JSON.stringify(files.value.map((d) => d.url));
};
const onDeleteFile = (index: number) => {
files.value.splice(index, 1);
};
/* 获取预览提示类型 */
const getPreviewAlertType = () => {
if (!form.applyStatus) return 'info';
switch (form.applyStatus) {
case 10:
return 'processing';
case 20:
return 'success';
case 30:
return 'error';
case 40:
return 'success';
default:
return 'info';
}
};
/* 获取预览文本 */
const getPreviewText = () => {
if (!form.money || !form.payType) return '';
const amount = parseFloat(form.money.toString()).toFixed(2);
const payTypeMap = {
10: '微信',
20: '支付宝',
30: '银行卡'
};
const statusMap = {
10: '待审核',
20: '审核通过',
30: '审核驳回',
40: '已打款'
};
const payTypeName = payTypeMap[form.payType] || '未知方式';
const statusName = statusMap[form.applyStatus] || '未知状态';
return `提现金额:¥${amount},打款方式:${payTypeName},当前状态:${statusName}`;
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
if (isSuccess.value) {
console.log('isSuccess');
updateVisible(false);
emit('done');
return;
}
if (form.realName == '' || form.realName == null) {
message.error('该用户未完成实名认证!');
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form
};
// 处理时间字段转换
if (formData.auditTime && dayjs.isDayjs(formData.auditTime)) {
formData.auditTime = formData.auditTime.valueOf();
}
// 根据支付方式清理不相关字段
if (formData.payType !== 10) {
delete formData.wechatAccount;
delete formData.wechatName;
}
if (formData.payType !== 20) {
delete formData.alipayName;
delete formData.alipayAccount;
}
if (formData.payType !== 30) {
delete formData.bankName;
delete formData.bankAccount;
delete formData.bankCard;
}
const saveOrUpdate = isUpdate.value
? updateShopDealerWithdraw
: addShopDealerWithdraw;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
files.value = [];
if (props.data) {
assignObject(form, props.data);
// 处理时间字段
if (props.data.auditTime) {
form.auditTime = dayjs(props.data.auditTime);
}
if (props.data.image) {
const arr = JSON.parse(props.data.image);
arr.map((url: string) => {
files.value.push({
uid: uuid(),
url: url,
status: 'done'
});
});
isSuccess.value = true;
}
isUpdate.value = true;
} else {
// 重置为默认值
Object.assign(form, {
id: undefined,
userId: undefined,
money: undefined,
payType: undefined,
wechatAccount: '',
wechatName: '',
alipayName: '',
alipayAccount: '',
bankName: '',
bankAccount: '',
bankCard: '',
applyStatus: 10,
auditTime: undefined,
rejectReason: '',
platform: '',
image: '',
tenantId: undefined,
createTime: undefined,
updateTime: undefined
});
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
<style lang="less" scoped>
.platform-option,
.status-option {
display: flex;
align-items: center;
.ant-tag {
margin-right: 8px;
}
span {
color: #666;
font-size: 12px;
}
}
.payment-info {
background: #fafafa;
padding: 16px;
border-radius: 6px;
margin-bottom: 16px;
&.wechat-info {
border-left: 3px solid #52c41a;
}
&.alipay-info {
border-left: 3px solid #1890ff;
}
&.bank-info {
border-left: 3px solid #faad14;
}
}
.withdraw-preview {
:deep(.ant-alert) {
.ant-alert-message {
font-weight: 600;
font-size: 14px;
}
}
}
:deep(.ant-divider-horizontal.ant-divider-with-text-left) {
margin: 24px 0 16px 0;
.ant-divider-inner-text {
padding: 0 16px 0 0;
}
}
:deep(.ant-form-item) {
margin-bottom: 16px;
}
:deep(.ant-radio) {
display: flex;
align-items: center;
margin-bottom: 8px;
.ant-radio-inner {
margin-right: 8px;
}
}
:deep(.ant-select-selection-item) {
display: flex;
align-items: center;
}
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-alert) {
.ant-alert-message {
font-weight: 600;
}
}
</style>