feat(shop): 添加商户入驻申请功能
- 在API模型中新增证件类型字段(idType) - 修改API请求路径,移除SERVER_API_URL前缀 - 新增根据入驻申请创建商户的接口方法 - 在菜单配置中添加商城管理和商户入驻申请菜单项 - 新增商家入驻申请和申请成功页面路由 - 创建商家入驻申请表单页面,包含三步流程:基本信息、资质信息、确认提交 - 实现图片上传和预览功能,支持营业执照、身份证等资质文件上传 - 添加表单验证规则,确保必填信息完整 - 创建申请提交成功页面,提供返回首页和查看申请按钮 - 优化CMS网站搜索组件代码结构和格式
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
VITE_APP_NAME=后台管理(开发环境)
|
VITE_APP_NAME=后台管理(开发环境)
|
||||||
#VITE_API_URL=http://192.168.1.131:9200/api
|
VITE_API_URL=http://127.0.0.1:9200/api
|
||||||
VITE_SERVER_API_URL=http://127.0.0.1:8000/api
|
#VITE_SERVER_API_URL=http://127.0.0.1:8000/api
|
||||||
|
|
||||||
|
|
||||||
#VITE_API_URL=https://cms-api.s209.websoft.top/api
|
#VITE_API_URL=https://cms-api.s209.websoft.top/api
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export async function listShopMerchantApply(params?: ShopMerchantApplyParam) {
|
|||||||
*/
|
*/
|
||||||
export async function addShopMerchantApply(data: ShopMerchantApply) {
|
export async function addShopMerchantApply(data: ShopMerchantApply) {
|
||||||
const res = await request.post<ApiResult<unknown>>(
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
SERVER_API_URL + '/shop/shop-merchant-apply',
|
'/shop/shop-merchant-apply',
|
||||||
data
|
data
|
||||||
);
|
);
|
||||||
if (res.data.code === 0) {
|
if (res.data.code === 0) {
|
||||||
@@ -75,6 +75,17 @@ export async function checkShopMerchantApply(data: ShopMerchantApply) {
|
|||||||
return Promise.reject(new Error(res.data.message));
|
return Promise.reject(new Error(res.data.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据入驻申请创建商户
|
||||||
|
export async function createMerchantFromApply(applyId: number) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
SERVER_API_URL + '/shop/shop-merchant-apply/create-merchant/' + applyId
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除商户入驻申请
|
* 删除商户入驻申请
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ export interface ShopMerchantApply {
|
|||||||
applyId?: number;
|
applyId?: number;
|
||||||
// 类型
|
// 类型
|
||||||
type?: number;
|
type?: number;
|
||||||
|
// 证件类型
|
||||||
|
idType?: string;
|
||||||
// 主体名称
|
// 主体名称
|
||||||
merchantName?: string;
|
merchantName?: string;
|
||||||
// 证件号码
|
// 证件号码
|
||||||
@@ -69,4 +71,4 @@ export interface ShopMerchantApplyParam extends PageParam {
|
|||||||
shopType?: string;
|
shopType?: string;
|
||||||
phone?: string;
|
phone?: string;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
}
|
}
|
||||||
@@ -34,6 +34,18 @@ export default [
|
|||||||
component: '/appstore',
|
component: '/appstore',
|
||||||
meta: { title: '应用管理', icon: 'AppstoreOutlined' }
|
meta: { title: '应用管理', icon: 'AppstoreOutlined' }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/shop',
|
||||||
|
redirect: '/shop/shopMerchantApply',
|
||||||
|
meta: { title: '商城管理', icon: 'ShoppingOutlined' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/shop/shopMerchantApply',
|
||||||
|
component: '/shop/shopMerchantApply',
|
||||||
|
meta: { title: '商户入驻申请', icon: 'UserAddOutlined' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/system',
|
path: '/system',
|
||||||
redirect: '/system/user',
|
redirect: '/system/user',
|
||||||
@@ -114,4 +126,4 @@ export default [
|
|||||||
component: '/passport/register/index.vue',
|
component: '/passport/register/index.vue',
|
||||||
meta: { title: '免费注册' }
|
meta: { title: '免费注册' }
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -45,6 +45,16 @@ export const routes = [
|
|||||||
component: () => import('@/components/QrLogin/demo.vue'),
|
component: () => import('@/components/QrLogin/demo.vue'),
|
||||||
meta: { title: '二维码登录演示' }
|
meta: { title: '二维码登录演示' }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/merchant/apply',
|
||||||
|
component: () => import('@/views/passport/merchant/apply.vue'),
|
||||||
|
meta: { title: '商家入驻申请' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/merchant/success',
|
||||||
|
component: () => import('@/views/passport/merchant/success.vue'),
|
||||||
|
meta: { title: '申请提交成功' }
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// path: '/forget',
|
// path: '/forget',
|
||||||
// component: () => import('@/views/passport/forget/index.vue'),
|
// component: () => import('@/views/passport/forget/index.vue'),
|
||||||
|
|||||||
@@ -1,100 +1,71 @@
|
|||||||
<!-- 搜索表单 -->
|
<!-- 搜索表单 -->
|
||||||
<template>
|
<template>
|
||||||
<a-space style="flex-wrap: wrap">
|
<a-space style="flex-wrap: wrap">
|
||||||
<a-button
|
<a-button type="text" @click="openUrl(`/website/field`)"
|
||||||
type="text"
|
>字段扩展
|
||||||
@click="openUrl(`/website/field`)"
|
|
||||||
>字段扩展
|
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button
|
<a-button type="text" @click="openUrl('/website/dict')">字典管理 </a-button>
|
||||||
type="text"
|
<a-button type="text" @click="openUrl('/website/domain')"
|
||||||
@click="openUrl('/website/dict')"
|
>域名管理
|
||||||
>字典管理
|
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button
|
<a-button type="text" @click="openUrl('/website/model')"
|
||||||
type="text"
|
>模型管理
|
||||||
@click="openUrl('/website/domain')"
|
</a-button>
|
||||||
>域名管理
|
<a-button type="text" @click="openUrl('/website/form')">表单管理 </a-button>
|
||||||
</a-button
|
<a-button type="text" @click="openUrl('/website/lang')">国际化 </a-button>
|
||||||
>
|
<a-button type="text" @click="openUrl('/website/setting')"
|
||||||
<a-button
|
>网站设置
|
||||||
type="text"
|
</a-button>
|
||||||
@click="openUrl('/website/model')"
|
<a-button type="text" class="ele-btn-icon" @click="clearSiteInfoCache">
|
||||||
>模型管理
|
|
||||||
</a-button
|
|
||||||
>
|
|
||||||
<a-button
|
|
||||||
type="text"
|
|
||||||
@click="openUrl('/website/form')"
|
|
||||||
>表单管理
|
|
||||||
</a-button
|
|
||||||
>
|
|
||||||
<a-button
|
|
||||||
type="text"
|
|
||||||
@click="openUrl('/website/lang')"
|
|
||||||
>国际化
|
|
||||||
</a-button
|
|
||||||
>
|
|
||||||
<a-button
|
|
||||||
type="text"
|
|
||||||
@click="openUrl('/website/setting')"
|
|
||||||
>网站设置
|
|
||||||
</a-button
|
|
||||||
>
|
|
||||||
<a-button
|
|
||||||
type="text"
|
|
||||||
class="ele-btn-icon"
|
|
||||||
@click="clearSiteInfoCache">
|
|
||||||
清除缓存
|
清除缓存
|
||||||
</a-button>
|
</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {watch,nextTick} from 'vue';
|
import { watch, nextTick } from 'vue';
|
||||||
import {CmsWebsite} from '@/api/cms/cmsWebsite/model';
|
import { CmsWebsite } from '@/api/cms/cmsWebsite/model';
|
||||||
import {openUrl} from "@/utils/common";
|
import { openUrl } from '@/utils/common';
|
||||||
import {message} from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import {removeSiteInfoCache} from "@/api/cms/cmsWebsite";
|
import { removeSiteInfoCache } from '@/api/cms/cmsWebsite';
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
// 选中的角色
|
// 选中的角色
|
||||||
selection?: [];
|
selection?: [];
|
||||||
website?: CmsWebsite;
|
website?: CmsWebsite;
|
||||||
count?: 0;
|
count?: 0;
|
||||||
}>(),
|
}>(),
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'add'): void;
|
(e: 'add'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const add = () => {
|
const add = () => {
|
||||||
emit('add');
|
emit('add');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 清除缓存
|
// 清除缓存
|
||||||
const clearSiteInfoCache = () => {
|
const clearSiteInfoCache = () => {
|
||||||
removeSiteInfoCache('SiteInfo:' + localStorage.getItem('TenantId') + "*").then(
|
removeSiteInfoCache(
|
||||||
(msg) => {
|
'SiteInfo:' + localStorage.getItem('TenantId') + '*'
|
||||||
|
).then((msg) => {
|
||||||
if (msg) {
|
if (msg) {
|
||||||
message.success(msg);
|
message.success(msg);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
if (localStorage.getItem('NotActive')) {
|
||||||
|
// IsActive.value = false
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.selection,
|
||||||
|
() => {}
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
nextTick(() => {
|
|
||||||
if(localStorage.getItem('NotActive')){
|
|
||||||
// IsActive.value = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.selection,
|
|
||||||
() => {
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
581
src/views/passport/merchant/apply.vue
Normal file
581
src/views/passport/merchant/apply.vue
Normal file
@@ -0,0 +1,581 @@
|
|||||||
|
<template>
|
||||||
|
<div class="merchant-apply-container">
|
||||||
|
<div class="merchant-apply-header">
|
||||||
|
<h1>商家入驻申请</h1>
|
||||||
|
<p>欢迎申请成为平台商家,请填写以下信息</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-steps :current="currentStep" style="margin-bottom: 30px">
|
||||||
|
<a-step title="基本信息" />
|
||||||
|
<a-step title="资质信息" />
|
||||||
|
<a-step title="确认提交" />
|
||||||
|
</a-steps>
|
||||||
|
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
:label-col="{ span: 6 }"
|
||||||
|
:wrapper-col="{ span: 18 }"
|
||||||
|
class="merchant-apply-form"
|
||||||
|
>
|
||||||
|
<!-- 第一步:基本信息 -->
|
||||||
|
<div v-show="currentStep === 0">
|
||||||
|
<a-card title="基本信息" style="margin-bottom: 20px">
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="商户名称" name="merchantName">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.merchantName"
|
||||||
|
placeholder="请输入商户名称"
|
||||||
|
:maxlength="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="证件类型" name="idType">
|
||||||
|
<a-select
|
||||||
|
v-model:value="form.idType"
|
||||||
|
placeholder="请选择证件类型"
|
||||||
|
>
|
||||||
|
<a-select-option value="1">营业执照</a-select-option>
|
||||||
|
<a-select-option value="2">统一社会信用代码</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="证件号码" name="merchantCode">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.merchantCode"
|
||||||
|
placeholder="请输入证件号码"
|
||||||
|
:maxlength="50"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="商户手机号" name="phone">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.phone"
|
||||||
|
placeholder="请输入联系人手机号"
|
||||||
|
:maxlength="11"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="商户姓名" name="realName">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.realName"
|
||||||
|
placeholder="请输入联系人姓名"
|
||||||
|
:maxlength="20"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="身份证号码" name="idCard">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.idCard"
|
||||||
|
placeholder="请输入法人身份证号码"
|
||||||
|
:maxlength="18"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="店铺类型" name="shopType">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.shopType"
|
||||||
|
placeholder="请输入店铺类型"
|
||||||
|
:maxlength="50"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="商户分类" name="category">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.category"
|
||||||
|
placeholder="请输入商户所属分类"
|
||||||
|
:maxlength="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第二步:资质信息 -->
|
||||||
|
<div v-show="currentStep === 1">
|
||||||
|
<a-card title="资质信息" style="margin-bottom: 20px">
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="营业执照" name="yyzz">
|
||||||
|
<div class="upload-container">
|
||||||
|
<a-image
|
||||||
|
v-if="form.yyzz"
|
||||||
|
:src="form.yyzz"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
style="margin-bottom: 10px"
|
||||||
|
/>
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请上传营业执照`"
|
||||||
|
:limit="1"
|
||||||
|
:data="yyzzImages"
|
||||||
|
@done="chooseYyzzImage"
|
||||||
|
@del="onDeleteYyzzImage"
|
||||||
|
/>
|
||||||
|
<p class="upload-tip">请上传清晰的营业执照照片</p>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="身份证正面" name="sfz1">
|
||||||
|
<div class="upload-container">
|
||||||
|
<a-image
|
||||||
|
v-if="form.sfz1"
|
||||||
|
:src="form.sfz1"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
style="margin-bottom: 10px"
|
||||||
|
/>
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请上传身份证正面`"
|
||||||
|
:limit="1"
|
||||||
|
:data="sfz1Images"
|
||||||
|
@done="chooseSfz1Image"
|
||||||
|
@del="onDeleteSfz1Image"
|
||||||
|
/>
|
||||||
|
<p class="upload-tip">请上传清晰的身份证正面照片</p>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="身份证反面" name="sfz2">
|
||||||
|
<div class="upload-container">
|
||||||
|
<a-image
|
||||||
|
v-if="form.sfz2"
|
||||||
|
:src="form.sfz2"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
style="margin-bottom: 10px"
|
||||||
|
/>
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请上传身份证反面`"
|
||||||
|
:limit="1"
|
||||||
|
:data="sfz2Images"
|
||||||
|
@done="chooseSfz2Image"
|
||||||
|
@del="onDeleteSfz2Image"
|
||||||
|
/>
|
||||||
|
<p class="upload-tip">请上传清晰的身份证反面照片</p>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="24">
|
||||||
|
<a-form-item label="资质图片" name="files">
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请上传其他资质证明文件`"
|
||||||
|
:limit="9"
|
||||||
|
:data="files"
|
||||||
|
@done="chooseFiles"
|
||||||
|
@del="onDeleteFiles"
|
||||||
|
/>
|
||||||
|
<p class="upload-tip"
|
||||||
|
>可上传产品合格证、授权书等相关资质文件(最多9张)</p
|
||||||
|
>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第三步:确认提交 -->
|
||||||
|
<div v-show="currentStep === 2">
|
||||||
|
<a-card title="申请信息确认" style="margin-bottom: 20px">
|
||||||
|
<a-descriptions
|
||||||
|
bordered
|
||||||
|
:column="{ xxl: 1, xl: 1, lg: 1, md: 1, sm: 1, xs: 1 }"
|
||||||
|
>
|
||||||
|
<a-descriptions-item label="商户名称">{{
|
||||||
|
form.merchantName
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="证件类型">{{
|
||||||
|
getIdTypeName(form.idType)
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="证件号码">{{
|
||||||
|
form.merchantCode
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="联系人手机号">{{
|
||||||
|
form.phone
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="联系人姓名">{{
|
||||||
|
form.realName
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="身份证号码">{{
|
||||||
|
form.idCard
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="店铺类型">{{
|
||||||
|
form.shopType
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="商户分类">{{
|
||||||
|
form.category
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="营业执照">
|
||||||
|
<a-image
|
||||||
|
v-if="form.yyzz"
|
||||||
|
:src="form.yyzz"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
/>
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="身份证正面">
|
||||||
|
<a-image
|
||||||
|
v-if="form.sfz1"
|
||||||
|
:src="form.sfz1"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
/>
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="身份证反面">
|
||||||
|
<a-image
|
||||||
|
v-if="form.sfz2"
|
||||||
|
:src="form.sfz2"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
/>
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="其他资质文件">
|
||||||
|
<div v-if="files.length > 0" class="files-preview">
|
||||||
|
<a-image
|
||||||
|
v-for="(file, index) in files"
|
||||||
|
:key="index"
|
||||||
|
:src="file.url"
|
||||||
|
:width="80"
|
||||||
|
:height="80"
|
||||||
|
style="margin-right: 10px; margin-bottom: 10px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span v-else>无</span>
|
||||||
|
</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
|
||||||
|
<a-alert
|
||||||
|
message="请仔细核对以上信息,提交后将无法修改。审核结果将在3个工作日内通过短信通知您。"
|
||||||
|
type="info"
|
||||||
|
show-icon
|
||||||
|
style="margin-top: 20px"
|
||||||
|
/>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<div class="form-actions">
|
||||||
|
<a-button
|
||||||
|
v-if="currentStep > 0"
|
||||||
|
@click="prevStep"
|
||||||
|
style="margin-right: 10px"
|
||||||
|
>
|
||||||
|
上一步
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<a-button v-if="currentStep < 2" type="primary" @click="nextStep">
|
||||||
|
下一步
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<a-button
|
||||||
|
v-if="currentStep === 2"
|
||||||
|
type="primary"
|
||||||
|
@click="submitApply"
|
||||||
|
:loading="submitLoading"
|
||||||
|
>
|
||||||
|
提交申请
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive } from 'vue';
|
||||||
|
import { Form, message } from 'ant-design-vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { addShopMerchantApply } from '@/api/shop/shopMerchantApply';
|
||||||
|
import { ShopMerchantApply } from '@/api/shop/shopMerchantApply/model';
|
||||||
|
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||||
|
import { FileRecord } from '@/api/system/file/model';
|
||||||
|
|
||||||
|
const useForm = Form.useForm;
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 当前步骤
|
||||||
|
const currentStep = ref(0);
|
||||||
|
|
||||||
|
// 提交状态
|
||||||
|
const submitLoading = ref(false);
|
||||||
|
|
||||||
|
// 表单引用
|
||||||
|
const formRef = ref<any>(null);
|
||||||
|
|
||||||
|
// 图片数据
|
||||||
|
const yyzzImages = ref<ItemType[]>([]);
|
||||||
|
const sfz1Images = ref<ItemType[]>([]);
|
||||||
|
const sfz2Images = ref<ItemType[]>([]);
|
||||||
|
const files = ref<ItemType[]>([]);
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const form = reactive<ShopMerchantApply>({
|
||||||
|
type: 1,
|
||||||
|
idType: '1', // 默认营业执照
|
||||||
|
merchantName: undefined,
|
||||||
|
merchantCode: undefined,
|
||||||
|
image: undefined,
|
||||||
|
phone: undefined,
|
||||||
|
realName: undefined,
|
||||||
|
idCard: undefined,
|
||||||
|
shopType: undefined,
|
||||||
|
category: undefined,
|
||||||
|
commission: undefined,
|
||||||
|
keywords: undefined,
|
||||||
|
yyzz: undefined,
|
||||||
|
sfz1: undefined,
|
||||||
|
sfz2: undefined,
|
||||||
|
files: undefined,
|
||||||
|
userId: undefined,
|
||||||
|
ownStore: 0,
|
||||||
|
recommend: 0,
|
||||||
|
goodsReview: 1,
|
||||||
|
name2: undefined,
|
||||||
|
reason: undefined,
|
||||||
|
comments: '商家入驻申请',
|
||||||
|
status: 0,
|
||||||
|
sortNumber: 100,
|
||||||
|
tenantId: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const rules = reactive({
|
||||||
|
merchantName: [
|
||||||
|
{ required: true, message: '请输入商户名称', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
idType: [{ required: true, message: '请选择证件类型', trigger: 'change' }],
|
||||||
|
merchantCode: [
|
||||||
|
{ required: true, message: '请输入证件号码', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
phone: [{ required: true, message: '请输入联系人手机号', trigger: 'blur' }],
|
||||||
|
realName: [
|
||||||
|
{ required: true, message: '请输入联系人姓名', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
idCard: [{ required: true, message: '请输入身份证号码', trigger: 'blur' }],
|
||||||
|
shopType: [{ required: true, message: '请输入店铺类型', trigger: 'blur' }],
|
||||||
|
category: [{ required: true, message: '请输入商户分类', trigger: 'blur' }],
|
||||||
|
yyzz: [{ required: true, message: '请上传营业执照', trigger: 'change' }],
|
||||||
|
sfz1: [{ required: true, message: '请上传身份证正面', trigger: 'change' }],
|
||||||
|
sfz2: [{ required: true, message: '请上传身份证反面', trigger: 'change' }]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取证件类型名称
|
||||||
|
const getIdTypeName = (type: string | undefined) => {
|
||||||
|
switch (type) {
|
||||||
|
case '1':
|
||||||
|
return '营业执照';
|
||||||
|
case '2':
|
||||||
|
return '统一社会信用代码';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 图片选择处理
|
||||||
|
const chooseYyzzImage = (data: FileRecord) => {
|
||||||
|
yyzzImages.value = [
|
||||||
|
{
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
form.yyzz = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteYyzzImage = () => {
|
||||||
|
yyzzImages.value = [];
|
||||||
|
form.yyzz = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseSfz1Image = (data: FileRecord) => {
|
||||||
|
sfz1Images.value = [
|
||||||
|
{
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
form.sfz1 = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteSfz1Image = () => {
|
||||||
|
sfz1Images.value = [];
|
||||||
|
form.sfz1 = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseSfz2Image = (data: FileRecord) => {
|
||||||
|
sfz2Images.value = [
|
||||||
|
{
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
form.sfz2 = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteSfz2Image = () => {
|
||||||
|
sfz2Images.value = [];
|
||||||
|
form.sfz2 = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseFiles = (data: FileRecord) => {
|
||||||
|
files.value.push({
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteFiles = (index: number) => {
|
||||||
|
files.value.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 步骤控制
|
||||||
|
const nextStep = () => {
|
||||||
|
if (!formRef.value) return;
|
||||||
|
|
||||||
|
// 验证当前步骤的表单
|
||||||
|
const validateFields = getValidateFields();
|
||||||
|
if (validateFields.length > 0) {
|
||||||
|
formRef.value
|
||||||
|
.validateFields(validateFields)
|
||||||
|
.then(() => {
|
||||||
|
currentStep.value++;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error('请完善必填信息');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
currentStep.value++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const prevStep = () => {
|
||||||
|
currentStep.value--;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取当前步骤需要验证的字段
|
||||||
|
const getValidateFields = () => {
|
||||||
|
switch (currentStep.value) {
|
||||||
|
case 0:
|
||||||
|
return [
|
||||||
|
'merchantName',
|
||||||
|
'idType',
|
||||||
|
'merchantCode',
|
||||||
|
'phone',
|
||||||
|
'realName',
|
||||||
|
'idCard',
|
||||||
|
'shopType',
|
||||||
|
'category'
|
||||||
|
];
|
||||||
|
case 1:
|
||||||
|
return ['yyzz', 'sfz1', 'sfz2'];
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交申请
|
||||||
|
const submitApply = () => {
|
||||||
|
if (!formRef.value) return;
|
||||||
|
|
||||||
|
submitLoading.value = true;
|
||||||
|
|
||||||
|
// 处理表单数据
|
||||||
|
const formData = {
|
||||||
|
...form,
|
||||||
|
files:
|
||||||
|
files.value.length > 0
|
||||||
|
? JSON.stringify(files.value.map((item) => item.url))
|
||||||
|
: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
addShopMerchantApply(formData)
|
||||||
|
.then((msg) => {
|
||||||
|
submitLoading.value = false;
|
||||||
|
message.success('申请提交成功,我们将在3个工作日内完成审核!');
|
||||||
|
// 跳转到申请成功页面
|
||||||
|
router.push('/merchant/success');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
submitLoading.value = false;
|
||||||
|
message.error(e.message || '申请提交失败,请稍后重试');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const { resetFields } = useForm(form, rules);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.merchant-apply-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 20px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.merchant-apply-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.merchant-apply-form {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-tip {
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.files-preview {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-actions {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
41
src/views/passport/merchant/success.vue
Normal file
41
src/views/passport/merchant/success.vue
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<template>
|
||||||
|
<div class="success-container">
|
||||||
|
<a-result
|
||||||
|
status="success"
|
||||||
|
title="商家入驻申请提交成功"
|
||||||
|
sub-title="我们将在3个工作日内完成审核,审核结果将通过短信通知您"
|
||||||
|
>
|
||||||
|
<template #extra>
|
||||||
|
<a-button key="console" type="primary" @click="goHome"
|
||||||
|
>返回首页</a-button
|
||||||
|
>
|
||||||
|
<a-button key="buy" @click="viewApplication">查看申请</a-button>
|
||||||
|
</template>
|
||||||
|
</a-result>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const goHome = () => {
|
||||||
|
router.push('/');
|
||||||
|
};
|
||||||
|
|
||||||
|
const viewApplication = () => {
|
||||||
|
router.push('/merchant/apply');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.success-container {
|
||||||
|
padding: 40px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 20px auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
581
src/views/shop/shopMerchant/components/apply.vue
Normal file
581
src/views/shop/shopMerchant/components/apply.vue
Normal file
@@ -0,0 +1,581 @@
|
|||||||
|
<template>
|
||||||
|
<div class="merchant-apply-container">
|
||||||
|
<div class="merchant-apply-header">
|
||||||
|
<h1>商家入驻申请</h1>
|
||||||
|
<p>欢迎申请成为平台商家,请填写以下信息</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-steps :current="currentStep" style="margin-bottom: 30px">
|
||||||
|
<a-step title="基本信息" />
|
||||||
|
<a-step title="资质信息" />
|
||||||
|
<a-step title="确认提交" />
|
||||||
|
</a-steps>
|
||||||
|
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
:label-col="{ span: 6 }"
|
||||||
|
:wrapper-col="{ span: 18 }"
|
||||||
|
class="merchant-apply-form"
|
||||||
|
>
|
||||||
|
<!-- 第一步:基本信息 -->
|
||||||
|
<div v-show="currentStep === 0">
|
||||||
|
<a-card title="基本信息" style="margin-bottom: 20px">
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="商户名称" name="merchantName">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.merchantName"
|
||||||
|
placeholder="请输入商户名称"
|
||||||
|
:maxlength="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="证件类型" name="idType">
|
||||||
|
<a-select
|
||||||
|
v-model:value="form.idType"
|
||||||
|
placeholder="请选择证件类型"
|
||||||
|
>
|
||||||
|
<a-select-option value="1">营业执照</a-select-option>
|
||||||
|
<a-select-option value="2">统一社会信用代码</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="证件号码" name="merchantCode">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.merchantCode"
|
||||||
|
placeholder="请输入证件号码"
|
||||||
|
:maxlength="50"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="商户手机号" name="phone">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.phone"
|
||||||
|
placeholder="请输入联系人手机号"
|
||||||
|
:maxlength="11"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="商户姓名" name="realName">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.realName"
|
||||||
|
placeholder="请输入联系人姓名"
|
||||||
|
:maxlength="20"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="身份证号码" name="idCard">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.idCard"
|
||||||
|
placeholder="请输入法人身份证号码"
|
||||||
|
:maxlength="18"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="店铺类型" name="shopType">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.shopType"
|
||||||
|
placeholder="请输入店铺类型"
|
||||||
|
:maxlength="50"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="商户分类" name="category">
|
||||||
|
<a-input
|
||||||
|
v-model:value="form.category"
|
||||||
|
placeholder="请输入商户所属分类"
|
||||||
|
:maxlength="100"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第二步:资质信息 -->
|
||||||
|
<div v-show="currentStep === 1">
|
||||||
|
<a-card title="资质信息" style="margin-bottom: 20px">
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="营业执照" name="yyzz">
|
||||||
|
<div class="upload-container">
|
||||||
|
<a-image
|
||||||
|
v-if="form.yyzz"
|
||||||
|
:src="form.yyzz"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
style="margin-bottom: 10px"
|
||||||
|
/>
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请上传营业执照`"
|
||||||
|
:limit="1"
|
||||||
|
:data="yyzzImages"
|
||||||
|
@done="chooseYyzzImage"
|
||||||
|
@del="onDeleteYyzzImage"
|
||||||
|
/>
|
||||||
|
<p class="upload-tip">请上传清晰的营业执照照片</p>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="身份证正面" name="sfz1">
|
||||||
|
<div class="upload-container">
|
||||||
|
<a-image
|
||||||
|
v-if="form.sfz1"
|
||||||
|
:src="form.sfz1"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
style="margin-bottom: 10px"
|
||||||
|
/>
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请上传身份证正面`"
|
||||||
|
:limit="1"
|
||||||
|
:data="sfz1Images"
|
||||||
|
@done="chooseSfz1Image"
|
||||||
|
@del="onDeleteSfz1Image"
|
||||||
|
/>
|
||||||
|
<p class="upload-tip">请上传清晰的身份证正面照片</p>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="身份证反面" name="sfz2">
|
||||||
|
<div class="upload-container">
|
||||||
|
<a-image
|
||||||
|
v-if="form.sfz2"
|
||||||
|
:src="form.sfz2"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
style="margin-bottom: 10px"
|
||||||
|
/>
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请上传身份证反面`"
|
||||||
|
:limit="1"
|
||||||
|
:data="sfz2Images"
|
||||||
|
@done="chooseSfz2Image"
|
||||||
|
@del="onDeleteSfz2Image"
|
||||||
|
/>
|
||||||
|
<p class="upload-tip">请上传清晰的身份证反面照片</p>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="24">
|
||||||
|
<a-form-item label="资质图片" name="files">
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请上传其他资质证明文件`"
|
||||||
|
:limit="9"
|
||||||
|
:data="files"
|
||||||
|
@done="chooseFiles"
|
||||||
|
@del="onDeleteFiles"
|
||||||
|
/>
|
||||||
|
<p class="upload-tip"
|
||||||
|
>可上传产品合格证、授权书等相关资质文件(最多9张)</p
|
||||||
|
>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 第三步:确认提交 -->
|
||||||
|
<div v-show="currentStep === 2">
|
||||||
|
<a-card title="申请信息确认" style="margin-bottom: 20px">
|
||||||
|
<a-descriptions
|
||||||
|
bordered
|
||||||
|
:column="{ xxl: 1, xl: 1, lg: 1, md: 1, sm: 1, xs: 1 }"
|
||||||
|
>
|
||||||
|
<a-descriptions-item label="商户名称">{{
|
||||||
|
form.merchantName
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="证件类型">{{
|
||||||
|
getIdTypeName(form.idType)
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="证件号码">{{
|
||||||
|
form.merchantCode
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="联系人手机号">{{
|
||||||
|
form.phone
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="联系人姓名">{{
|
||||||
|
form.realName
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="身份证号码">{{
|
||||||
|
form.idCard
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="店铺类型">{{
|
||||||
|
form.shopType
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="商户分类">{{
|
||||||
|
form.category
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="营业执照">
|
||||||
|
<a-image
|
||||||
|
v-if="form.yyzz"
|
||||||
|
:src="form.yyzz"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
/>
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="身份证正面">
|
||||||
|
<a-image
|
||||||
|
v-if="form.sfz1"
|
||||||
|
:src="form.sfz1"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
/>
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="身份证反面">
|
||||||
|
<a-image
|
||||||
|
v-if="form.sfz2"
|
||||||
|
:src="form.sfz2"
|
||||||
|
:width="120"
|
||||||
|
:height="120"
|
||||||
|
/>
|
||||||
|
</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="其他资质文件">
|
||||||
|
<div v-if="files.length > 0" class="files-preview">
|
||||||
|
<a-image
|
||||||
|
v-for="(file, index) in files"
|
||||||
|
:key="index"
|
||||||
|
:src="file.url"
|
||||||
|
:width="80"
|
||||||
|
:height="80"
|
||||||
|
style="margin-right: 10px; margin-bottom: 10px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span v-else>无</span>
|
||||||
|
</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
|
||||||
|
<a-alert
|
||||||
|
message="请仔细核对以上信息,提交后将无法修改。审核结果将在3个工作日内通过短信通知您。"
|
||||||
|
type="info"
|
||||||
|
show-icon
|
||||||
|
style="margin-top: 20px"
|
||||||
|
/>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<div class="form-actions">
|
||||||
|
<a-button
|
||||||
|
v-if="currentStep > 0"
|
||||||
|
@click="prevStep"
|
||||||
|
style="margin-right: 10px"
|
||||||
|
>
|
||||||
|
上一步
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<a-button v-if="currentStep < 2" type="primary" @click="nextStep">
|
||||||
|
下一步
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<a-button
|
||||||
|
v-if="currentStep === 2"
|
||||||
|
type="primary"
|
||||||
|
@click="submitApply"
|
||||||
|
:loading="submitLoading"
|
||||||
|
>
|
||||||
|
提交申请
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive } from 'vue';
|
||||||
|
import { Form, message } from 'ant-design-vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { addShopMerchantApply } from '@/api/shop/shopMerchantApply';
|
||||||
|
import { ShopMerchantApply } from '@/api/shop/shopMerchantApply/model';
|
||||||
|
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||||
|
import { FileRecord } from '@/api/system/file/model';
|
||||||
|
|
||||||
|
const useForm = Form.useForm;
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 当前步骤
|
||||||
|
const currentStep = ref(0);
|
||||||
|
|
||||||
|
// 提交状态
|
||||||
|
const submitLoading = ref(false);
|
||||||
|
|
||||||
|
// 表单引用
|
||||||
|
const formRef = ref<any>(null);
|
||||||
|
|
||||||
|
// 图片数据
|
||||||
|
const yyzzImages = ref<ItemType[]>([]);
|
||||||
|
const sfz1Images = ref<ItemType[]>([]);
|
||||||
|
const sfz2Images = ref<ItemType[]>([]);
|
||||||
|
const files = ref<ItemType[]>([]);
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const form = reactive<ShopMerchantApply>({
|
||||||
|
type: 1,
|
||||||
|
idType: '1', // 默认营业执照
|
||||||
|
merchantName: undefined,
|
||||||
|
merchantCode: undefined,
|
||||||
|
image: undefined,
|
||||||
|
phone: undefined,
|
||||||
|
realName: undefined,
|
||||||
|
idCard: undefined,
|
||||||
|
shopType: undefined,
|
||||||
|
category: undefined,
|
||||||
|
commission: undefined,
|
||||||
|
keywords: undefined,
|
||||||
|
yyzz: undefined,
|
||||||
|
sfz1: undefined,
|
||||||
|
sfz2: undefined,
|
||||||
|
files: undefined,
|
||||||
|
userId: undefined,
|
||||||
|
ownStore: 0,
|
||||||
|
recommend: 0,
|
||||||
|
goodsReview: 1,
|
||||||
|
name2: undefined,
|
||||||
|
reason: undefined,
|
||||||
|
comments: '商家入驻申请',
|
||||||
|
status: 0,
|
||||||
|
sortNumber: 100,
|
||||||
|
tenantId: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const rules = reactive({
|
||||||
|
merchantName: [
|
||||||
|
{ required: true, message: '请输入商户名称', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
idType: [{ required: true, message: '请选择证件类型', trigger: 'change' }],
|
||||||
|
merchantCode: [
|
||||||
|
{ required: true, message: '请输入证件号码', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
phone: [{ required: true, message: '请输入联系人手机号', trigger: 'blur' }],
|
||||||
|
realName: [
|
||||||
|
{ required: true, message: '请输入联系人姓名', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
idCard: [{ required: true, message: '请输入身份证号码', trigger: 'blur' }],
|
||||||
|
shopType: [{ required: true, message: '请输入店铺类型', trigger: 'blur' }],
|
||||||
|
category: [{ required: true, message: '请输入商户分类', trigger: 'blur' }],
|
||||||
|
yyzz: [{ required: true, message: '请上传营业执照', trigger: 'change' }],
|
||||||
|
sfz1: [{ required: true, message: '请上传身份证正面', trigger: 'change' }],
|
||||||
|
sfz2: [{ required: true, message: '请上传身份证反面', trigger: 'change' }]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取证件类型名称
|
||||||
|
const getIdTypeName = (type: string | undefined) => {
|
||||||
|
switch (type) {
|
||||||
|
case '1':
|
||||||
|
return '营业执照';
|
||||||
|
case '2':
|
||||||
|
return '统一社会信用代码';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 图片选择处理
|
||||||
|
const chooseYyzzImage = (data: FileRecord) => {
|
||||||
|
yyzzImages.value = [
|
||||||
|
{
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
form.yyzz = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteYyzzImage = () => {
|
||||||
|
yyzzImages.value = [];
|
||||||
|
form.yyzz = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseSfz1Image = (data: FileRecord) => {
|
||||||
|
sfz1Images.value = [
|
||||||
|
{
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
form.sfz1 = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteSfz1Image = () => {
|
||||||
|
sfz1Images.value = [];
|
||||||
|
form.sfz1 = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseSfz2Image = (data: FileRecord) => {
|
||||||
|
sfz2Images.value = [
|
||||||
|
{
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
form.sfz2 = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteSfz2Image = () => {
|
||||||
|
sfz2Images.value = [];
|
||||||
|
form.sfz2 = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseFiles = (data: FileRecord) => {
|
||||||
|
files.value.push({
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteFiles = (index: number) => {
|
||||||
|
files.value.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 步骤控制
|
||||||
|
const nextStep = () => {
|
||||||
|
if (!formRef.value) return;
|
||||||
|
|
||||||
|
// 验证当前步骤的表单
|
||||||
|
const validateFields = getValidateFields();
|
||||||
|
if (validateFields.length > 0) {
|
||||||
|
formRef.value
|
||||||
|
.validateFields(validateFields)
|
||||||
|
.then(() => {
|
||||||
|
currentStep.value++;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
message.error('请完善必填信息');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
currentStep.value++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const prevStep = () => {
|
||||||
|
currentStep.value--;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取当前步骤需要验证的字段
|
||||||
|
const getValidateFields = () => {
|
||||||
|
switch (currentStep.value) {
|
||||||
|
case 0:
|
||||||
|
return [
|
||||||
|
'merchantName',
|
||||||
|
'idType',
|
||||||
|
'merchantCode',
|
||||||
|
'phone',
|
||||||
|
'realName',
|
||||||
|
'idCard',
|
||||||
|
'shopType',
|
||||||
|
'category'
|
||||||
|
];
|
||||||
|
case 1:
|
||||||
|
return ['yyzz', 'sfz1', 'sfz2'];
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交申请
|
||||||
|
const submitApply = () => {
|
||||||
|
if (!formRef.value) return;
|
||||||
|
|
||||||
|
submitLoading.value = true;
|
||||||
|
|
||||||
|
// 处理表单数据
|
||||||
|
const formData = {
|
||||||
|
...form,
|
||||||
|
files:
|
||||||
|
files.value.length > 0
|
||||||
|
? JSON.stringify(files.value.map((item) => item.url))
|
||||||
|
: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
addShopMerchantApply(formData)
|
||||||
|
.then((msg) => {
|
||||||
|
submitLoading.value = false;
|
||||||
|
message.success('申请提交成功,我们将在3个工作日内完成审核!');
|
||||||
|
// 跳转到申请成功页面
|
||||||
|
router.push('/merchant/success');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
submitLoading.value = false;
|
||||||
|
message.error(e.message || '申请提交失败,请稍后重试');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const { resetFields } = useForm(form, rules);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.merchant-apply-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 20px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.merchant-apply-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.merchant-apply-form {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-tip {
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.files-preview {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-actions {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
56
src/views/shop/shopMerchant/components/extra.vue
Normal file
56
src/views/shop/shopMerchant/components/extra.vue
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<!-- 搜索表单 -->
|
||||||
|
<template>
|
||||||
|
<a-space style="flex-wrap: wrap">
|
||||||
|
<a-button type="primary" @click="openUrl(`/shop/shopMerchantApply`)"
|
||||||
|
>入驻申请
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { watch, nextTick } from 'vue';
|
||||||
|
import { CmsWebsite } from '@/api/cms/cmsWebsite/model';
|
||||||
|
import { openUrl } from '@/utils/common';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
import { removeSiteInfoCache } from '@/api/cms/cmsWebsite';
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
// 选中的角色
|
||||||
|
selection?: [];
|
||||||
|
website?: CmsWebsite;
|
||||||
|
count?: 0;
|
||||||
|
}>(),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'add'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const add = () => {
|
||||||
|
emit('add');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 清除缓存
|
||||||
|
const clearSiteInfoCache = () => {
|
||||||
|
removeSiteInfoCache(
|
||||||
|
'SiteInfo:' + localStorage.getItem('TenantId') + '*'
|
||||||
|
).then((msg) => {
|
||||||
|
if (msg) {
|
||||||
|
message.success(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
if (localStorage.getItem('NotActive')) {
|
||||||
|
// IsActive.value = false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.selection,
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
@@ -1,18 +1,20 @@
|
|||||||
<!-- 搜索表单 -->
|
<!-- 搜索表单 -->
|
||||||
<template>
|
<template>
|
||||||
<a-space :size="10" style="flex-wrap: wrap">
|
<a-space :size="10" style="flex-wrap: wrap">
|
||||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
<a-input-search
|
||||||
<template #icon>
|
allow-clear
|
||||||
<PlusOutlined />
|
placeholder="请输入关键词"
|
||||||
</template>
|
style="width: 280px"
|
||||||
<span>添加</span>
|
v-model:value="where.keywords"
|
||||||
</a-button>
|
@search="reload"
|
||||||
|
/>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
|
||||||
import { watch } from 'vue';
|
import { watch } from 'vue';
|
||||||
|
import useSearch from '@/utils/use-search';
|
||||||
|
import { ShopMerchantParam } from '@/api/shop/shopMerchant/model';
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@@ -22,6 +24,12 @@
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const { where } = useSearch<ShopMerchantParam>({
|
||||||
|
merchantId: undefined,
|
||||||
|
keywords: ''
|
||||||
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'search', where?: any): void;
|
(e: 'search', where?: any): void;
|
||||||
(e: 'add'): void;
|
(e: 'add'): void;
|
||||||
@@ -30,8 +38,12 @@
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
// 新增
|
// 新增
|
||||||
const add = () => {
|
// const add = () => {
|
||||||
emit('add');
|
// emit('add');
|
||||||
|
// };
|
||||||
|
|
||||||
|
const reload = () => {
|
||||||
|
emit('search', where);
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- 编辑弹窗 -->
|
<!-- 编辑弹窗 -->
|
||||||
<template>
|
<template>
|
||||||
<ele-modal
|
<a-drawer
|
||||||
:width="800"
|
width="60%"
|
||||||
:visible="visible"
|
:visible="visible"
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
:maxable="maxable"
|
:maxable="maxable"
|
||||||
@@ -33,24 +33,22 @@
|
|||||||
v-model:value="form.merchantCode"
|
v-model:value="form.merchantCode"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="商户类型" name="type">
|
<!-- <a-form-item label="商户类型" name="type">-->
|
||||||
<a-input
|
<!-- <a-input-->
|
||||||
allow-clear
|
<!-- allow-clear-->
|
||||||
placeholder="请输入商户类型"
|
<!-- placeholder="请输入商户类型"-->
|
||||||
v-model:value="form.type"
|
<!-- v-model:value="form.type"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </a-form-item>-->
|
||||||
|
<a-form-item label="商户图标" name="image">
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请选择图片`"
|
||||||
|
:limit="1"
|
||||||
|
:data="images"
|
||||||
|
@done="chooseImage"
|
||||||
|
@del="onDeleteItem"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item
|
|
||||||
label="商户图标"
|
|
||||||
name="image">
|
|
||||||
<SelectFile
|
|
||||||
:placeholder="`请选择图片`"
|
|
||||||
:limit="1"
|
|
||||||
:data="images"
|
|
||||||
@done="chooseImage"
|
|
||||||
@del="onDeleteItem"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="商户手机号" name="phone">
|
<a-form-item label="商户手机号" name="phone">
|
||||||
<a-input
|
<a-input
|
||||||
allow-clear
|
allow-clear
|
||||||
@@ -72,20 +70,20 @@
|
|||||||
v-model:value="form.shopType"
|
v-model:value="form.shopType"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="项目分类" name="itemType">
|
<!-- <a-form-item label="项目分类" name="itemType">-->
|
||||||
<a-input
|
<!-- <a-input-->
|
||||||
allow-clear
|
<!-- allow-clear-->
|
||||||
placeholder="请输入项目分类"
|
<!-- placeholder="请输入项目分类"-->
|
||||||
v-model:value="form.itemType"
|
<!-- v-model:value="form.itemType"-->
|
||||||
/>
|
<!-- />-->
|
||||||
</a-form-item>
|
<!-- </a-form-item>-->
|
||||||
<a-form-item label="商户分类" name="category">
|
<!-- <a-form-item label="商户分类" name="category">-->
|
||||||
<a-input
|
<!-- <a-input-->
|
||||||
allow-clear
|
<!-- allow-clear-->
|
||||||
placeholder="请输入商户分类"
|
<!-- placeholder="请输入商户分类"-->
|
||||||
v-model:value="form.category"
|
<!-- v-model:value="form.category"-->
|
||||||
/>
|
<!-- />-->
|
||||||
</a-form-item>
|
<!-- </a-form-item>-->
|
||||||
<a-form-item label="商户经营分类" name="merchantCategoryId">
|
<a-form-item label="商户经营分类" name="merchantCategoryId">
|
||||||
<a-input
|
<a-input
|
||||||
allow-clear
|
allow-clear
|
||||||
@@ -107,20 +105,12 @@
|
|||||||
v-model:value="form.lngAndLat"
|
v-model:value="form.lngAndLat"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="" name="lng">
|
<!-- <a-form-item label="" name="lng">-->
|
||||||
<a-input
|
<!-- <a-input allow-clear placeholder="请输入" v-model:value="form.lng" />-->
|
||||||
allow-clear
|
<!-- </a-form-item>-->
|
||||||
placeholder="请输入"
|
<!-- <a-form-item label="" name="lat">-->
|
||||||
v-model:value="form.lng"
|
<!-- <a-input allow-clear placeholder="请输入" v-model:value="form.lat" />-->
|
||||||
/>
|
<!-- </a-form-item>-->
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="" name="lat">
|
|
||||||
<a-input
|
|
||||||
allow-clear
|
|
||||||
placeholder="请输入"
|
|
||||||
v-model:value="form.lat"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="所在省份" name="province">
|
<a-form-item label="所在省份" name="province">
|
||||||
<a-input
|
<a-input
|
||||||
allow-clear
|
allow-clear
|
||||||
@@ -164,10 +154,12 @@
|
|||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="资质图片" name="files">
|
<a-form-item label="资质图片" name="files">
|
||||||
<a-input
|
<SelectFile
|
||||||
allow-clear
|
:placeholder="`请选择图片`"
|
||||||
placeholder="请输入资质图片"
|
:limit="9"
|
||||||
v-model:value="form.files"
|
:data="files"
|
||||||
|
@done="chooseFiles"
|
||||||
|
@del="onDeleteFiles"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="营业时间" name="businessTime">
|
<a-form-item label="营业时间" name="businessTime">
|
||||||
@@ -177,10 +169,10 @@
|
|||||||
v-model:value="form.businessTime"
|
v-model:value="form.businessTime"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="文章内容" name="content">
|
<a-form-item label="商户介绍" name="content">
|
||||||
<a-input
|
<a-input
|
||||||
allow-clear
|
allow-clear
|
||||||
placeholder="请输入文章内容"
|
placeholder="请输入商户介绍"
|
||||||
v-model:value="form.content"
|
v-model:value="form.content"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
@@ -219,14 +211,14 @@
|
|||||||
v-model:value="form.isOn"
|
v-model:value="form.isOn"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="" name="startTime">
|
<a-form-item label="开始时间" name="startTime">
|
||||||
<a-input
|
<a-input
|
||||||
allow-clear
|
allow-clear
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
v-model:value="form.startTime"
|
v-model:value="form.startTime"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="" name="endTime">
|
<a-form-item label="结束时间" name="endTime">
|
||||||
<a-input
|
<a-input
|
||||||
allow-clear
|
allow-clear
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@@ -255,13 +247,13 @@
|
|||||||
v-model:value="form.comments"
|
v-model:value="form.comments"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="所有人" name="userId">
|
<!-- <a-form-item label="所有人" name="userId">-->
|
||||||
<a-input
|
<!-- <a-input-->
|
||||||
allow-clear
|
<!-- allow-clear-->
|
||||||
placeholder="请输入所有人"
|
<!-- placeholder="请输入所有人"-->
|
||||||
v-model:value="form.userId"
|
<!-- v-model:value="form.userId"-->
|
||||||
/>
|
<!-- />-->
|
||||||
</a-form-item>
|
<!-- </a-form-item>-->
|
||||||
<a-form-item label="状态" name="status">
|
<a-form-item label="状态" name="status">
|
||||||
<a-radio-group v-model:value="form.status">
|
<a-radio-group v-model:value="form.status">
|
||||||
<a-radio :value="0">显示</a-radio>
|
<a-radio :value="0">显示</a-radio>
|
||||||
@@ -278,7 +270,7 @@
|
|||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</ele-modal>
|
</a-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -299,6 +291,7 @@
|
|||||||
// 是否开启响应式布局
|
// 是否开启响应式布局
|
||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
const { styleResponsive } = storeToRefs(themeStore);
|
const { styleResponsive } = storeToRefs(themeStore);
|
||||||
|
const files = ref<ItemType[]>([]);
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
// 弹窗是否打开
|
// 弹窗是否打开
|
||||||
@@ -361,9 +354,7 @@
|
|||||||
status: undefined,
|
status: undefined,
|
||||||
sortNumber: 100,
|
sortNumber: 100,
|
||||||
tenantId: undefined,
|
tenantId: undefined,
|
||||||
createTime: undefined,
|
createTime: undefined
|
||||||
shopMerchantId: undefined,
|
|
||||||
shopMerchantName: '',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* 更新visible */
|
/* 更新visible */
|
||||||
@@ -383,18 +374,17 @@
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
const chooseImage = (data: FileRecord) => {
|
const onDeleteItem = (index: number) => {
|
||||||
images.value.push({
|
images.value.splice(index, 1);
|
||||||
|
form.image = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseFiles = (data: FileRecord) => {
|
||||||
|
files.value.push({
|
||||||
uid: data.id,
|
uid: data.id,
|
||||||
url: data.path,
|
url: data.path,
|
||||||
status: 'done'
|
status: 'done'
|
||||||
});
|
});
|
||||||
form.image = data.path;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDeleteItem = (index: number) => {
|
|
||||||
images.value.splice(index, 1);
|
|
||||||
form.image = '';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const { resetFields } = useForm(form, rules);
|
const { resetFields } = useForm(form, rules);
|
||||||
@@ -411,7 +401,9 @@
|
|||||||
const formData = {
|
const formData = {
|
||||||
...form
|
...form
|
||||||
};
|
};
|
||||||
const saveOrUpdate = isUpdate.value ? updateShopMerchant : addShopMerchant;
|
const saveOrUpdate = isUpdate.value
|
||||||
|
? updateShopMerchant
|
||||||
|
: addShopMerchant;
|
||||||
saveOrUpdate(formData)
|
saveOrUpdate(formData)
|
||||||
.then((msg) => {
|
.then((msg) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
@@ -434,12 +426,12 @@
|
|||||||
images.value = [];
|
images.value = [];
|
||||||
if (props.data) {
|
if (props.data) {
|
||||||
assignObject(form, props.data);
|
assignObject(form, props.data);
|
||||||
if(props.data.image){
|
if (props.data.image) {
|
||||||
images.value.push({
|
images.value.push({
|
||||||
uid: uuid(),
|
uid: uuid(),
|
||||||
url: props.data.image,
|
url: props.data.image,
|
||||||
status: 'done'
|
status: 'done'
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
isUpdate.value = true;
|
isUpdate.value = true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,50 +1,68 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
<template #extra>
|
||||||
<ele-pro-table
|
<Extra />
|
||||||
ref="tableRef"
|
</template>
|
||||||
row-key="merchantId"
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
:columns="columns"
|
<ele-pro-table
|
||||||
:datasource="datasource"
|
ref="tableRef"
|
||||||
:customRow="customRow"
|
row-key="merchantId"
|
||||||
tool-class="ele-toolbar-form"
|
:columns="columns"
|
||||||
class="sys-org-table"
|
:datasource="datasource"
|
||||||
>
|
:customRow="customRow"
|
||||||
<template #toolbar>
|
tool-class="ele-toolbar-form"
|
||||||
<Search
|
class="sys-org-table"
|
||||||
@search="reload"
|
>
|
||||||
:selection="selection"
|
<template #toolbar>
|
||||||
@add="openEdit"
|
<Search
|
||||||
@remove="removeBatch"
|
@search="reload"
|
||||||
@batchMove="openMove"
|
:selection="selection"
|
||||||
/>
|
@add="openEdit"
|
||||||
|
@remove="removeBatch"
|
||||||
|
@batchMove="openMove"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'merchantName'">
|
||||||
|
<a-space>
|
||||||
|
<a-image :src="record.image" :width="50" :preview="false" />
|
||||||
|
<div class="flex-col">
|
||||||
|
<div class="font-bold">{{ record.merchantName }}</div>
|
||||||
|
</div>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template v-if="column.key === 'userId'">
|
||||||
<template v-if="column.key === 'image'">
|
<div class="flex-col">
|
||||||
<a-image :src="record.image" :width="50" />
|
<div>{{ record.realName }}</div>
|
||||||
</template>
|
<div class="text-gray-400">{{ record.phone }}</div>
|
||||||
<template v-if="column.key === 'status'">
|
</div>
|
||||||
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
|
|
||||||
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'action'">
|
|
||||||
<a-space>
|
|
||||||
<a @click="openEdit(record)">修改</a>
|
|
||||||
<a-divider type="vertical" />
|
|
||||||
<a-popconfirm
|
|
||||||
title="确定要删除此记录吗?"
|
|
||||||
@confirm="remove(record)"
|
|
||||||
>
|
|
||||||
<a class="ele-text-danger">删除</a>
|
|
||||||
</a-popconfirm>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
</template>
|
</template>
|
||||||
</ele-pro-table>
|
<template v-if="column.key === 'status'">
|
||||||
</a-card>
|
<a-tag v-if="record.status === 0" color="green">正常营业</a-tag>
|
||||||
|
<a-tag v-if="record.status === 1" color="red">已闭店</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a-space>
|
||||||
|
<a @click="openEdit(record)">修改</a>
|
||||||
|
<a-divider type="vertical" />
|
||||||
|
<a-popconfirm
|
||||||
|
title="确定要删除此记录吗?"
|
||||||
|
@confirm="remove(record)"
|
||||||
|
>
|
||||||
|
<a class="ele-text-danger">删除</a>
|
||||||
|
</a-popconfirm>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
<!-- 编辑弹窗 -->
|
<!-- 编辑弹窗 -->
|
||||||
<ShopMerchantEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
<ShopMerchantEdit
|
||||||
|
v-model:visible="showEdit"
|
||||||
|
:data="current"
|
||||||
|
@done="reload"
|
||||||
|
/>
|
||||||
</a-page-header>
|
</a-page-header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -59,10 +77,18 @@
|
|||||||
ColumnItem
|
ColumnItem
|
||||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
import Search from './components/search.vue';
|
import Search from './components/search.vue';
|
||||||
import {getPageTitle} from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import ShopMerchantEdit from './components/shopMerchantEdit.vue';
|
import ShopMerchantEdit from './components/shopMerchantEdit.vue';
|
||||||
import { pageShopMerchant, removeShopMerchant, removeBatchShopMerchant } from '@/api/shop/shopMerchant';
|
import {
|
||||||
import type { ShopMerchant, ShopMerchantParam } from '@/api/shop/shopMerchant/model';
|
pageShopMerchant,
|
||||||
|
removeShopMerchant,
|
||||||
|
removeBatchShopMerchant
|
||||||
|
} from '@/api/shop/shopMerchant';
|
||||||
|
import type {
|
||||||
|
ShopMerchant,
|
||||||
|
ShopMerchantParam
|
||||||
|
} from '@/api/shop/shopMerchant/model';
|
||||||
|
import Extra from './components/extra.vue';
|
||||||
|
|
||||||
// 表格实例
|
// 表格实例
|
||||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
@@ -100,41 +126,47 @@
|
|||||||
// 表格列配置
|
// 表格列配置
|
||||||
const columns = ref<ColumnItem[]>([
|
const columns = ref<ColumnItem[]>([
|
||||||
{
|
{
|
||||||
title: '商户ID',
|
title: 'ID',
|
||||||
dataIndex: 'merchantId',
|
dataIndex: 'merchantId',
|
||||||
key: 'merchantId',
|
key: 'merchantId',
|
||||||
align: 'center',
|
width: 90
|
||||||
width: 90,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '商户名称',
|
title: '商户名称',
|
||||||
dataIndex: 'merchantName',
|
dataIndex: 'merchantName',
|
||||||
key: 'merchantName',
|
key: 'merchantName'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户信息',
|
||||||
|
dataIndex: 'userId',
|
||||||
|
key: 'userId'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '店铺类型',
|
||||||
|
dataIndex: 'shopType',
|
||||||
|
key: 'shopType',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
width: 120
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// title: '店铺类型',
|
// title: '商户分类',
|
||||||
// dataIndex: 'shopType',
|
// dataIndex: 'category',
|
||||||
// key: 'shopType',
|
// key: 'category',
|
||||||
// align: 'center',
|
// align: 'center'
|
||||||
// },
|
// },
|
||||||
{
|
|
||||||
title: '商户分类',
|
|
||||||
dataIndex: 'category',
|
|
||||||
key: 'category',
|
|
||||||
align: 'center',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
key: 'status',
|
key: 'status',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
width: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '排序号',
|
title: '排序号',
|
||||||
dataIndex: 'sortNumber',
|
dataIndex: 'sortNumber',
|
||||||
key: 'sortNumber',
|
key: 'sortNumber',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
width: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '创建时间',
|
title: '创建时间',
|
||||||
@@ -143,16 +175,17 @@
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
width: 180,
|
||||||
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 180,
|
||||||
|
fixed: 'right',
|
||||||
|
align: 'center',
|
||||||
|
hideInSetting: true
|
||||||
}
|
}
|
||||||
// {
|
|
||||||
// title: '操作',
|
|
||||||
// key: 'action',
|
|
||||||
// width: 180,
|
|
||||||
// fixed: 'right',
|
|
||||||
// align: 'center',
|
|
||||||
// hideInSetting: true
|
|
||||||
// }
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/* 搜索 */
|
/* 搜索 */
|
||||||
|
|||||||
351
src/views/shop/shopMerchantApply/components/applyReview.vue
Normal file
351
src/views/shop/shopMerchantApply/components/applyReview.vue
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
:width="800"
|
||||||
|
:visible="visible"
|
||||||
|
:maskClosable="false"
|
||||||
|
:maxable="maxable"
|
||||||
|
title="审核商户入驻申请"
|
||||||
|
:body-style="{ paddingBottom: '28px' }"
|
||||||
|
@update:visible="updateVisible"
|
||||||
|
@ok="submitReview"
|
||||||
|
>
|
||||||
|
<a-tabs v-model:activeKey="activeKey">
|
||||||
|
<a-tab-pane key="1" tab="申请信息">
|
||||||
|
<a-descriptions bordered :column="{ xxl: 1, xl: 1, lg: 1, md: 1, sm: 1, xs: 1 }">
|
||||||
|
<a-descriptions-item label="商户名称">{{ data?.merchantName }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="证件号码">{{ data?.merchantCode }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="联系人手机号">{{ data?.phone }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="联系人姓名">{{ data?.realName }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="身份证号码">{{ data?.idCard }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="店铺类型">{{ data?.shopType }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="商户分类">{{ data?.category }}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="手续费">{{ data?.commission }}%</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="创建时间">{{ data?.createTime }}</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
</a-tab-pane>
|
||||||
|
|
||||||
|
<a-tab-pane key="2" tab="资质文件">
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="8">
|
||||||
|
<div class="file-preview">
|
||||||
|
<h4>营业执照</h4>
|
||||||
|
<a-image
|
||||||
|
v-if="data?.yyzz"
|
||||||
|
:src="data?.yyzz"
|
||||||
|
:width="150"
|
||||||
|
:height="150"
|
||||||
|
/>
|
||||||
|
<a-empty v-else description="未上传" />
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="8">
|
||||||
|
<div class="file-preview">
|
||||||
|
<h4>身份证正面</h4>
|
||||||
|
<a-image
|
||||||
|
v-if="data?.sfz1"
|
||||||
|
:src="data?.sfz1"
|
||||||
|
:width="150"
|
||||||
|
:height="150"
|
||||||
|
/>
|
||||||
|
<a-empty v-else description="未上传" />
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="8">
|
||||||
|
<div class="file-preview">
|
||||||
|
<h4>身份证反面</h4>
|
||||||
|
<a-image
|
||||||
|
v-if="data?.sfz2"
|
||||||
|
:src="data?.sfz2"
|
||||||
|
:width="150"
|
||||||
|
:height="150"
|
||||||
|
/>
|
||||||
|
<a-empty v-else description="未上传" />
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
|
||||||
|
<a-col :span="24" style="margin-top: 20px;">
|
||||||
|
<div class="file-preview">
|
||||||
|
<h4>其他资质文件</h4>
|
||||||
|
<div v-if="otherFiles.length > 0" class="files-grid">
|
||||||
|
<a-image
|
||||||
|
v-for="(file, index) in otherFiles"
|
||||||
|
:key="index"
|
||||||
|
:src="file"
|
||||||
|
:width="100"
|
||||||
|
:height="100"
|
||||||
|
style="margin-right: 10px; margin-bottom: 10px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<a-empty v-else description="未上传其他资质文件" />
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-tab-pane>
|
||||||
|
|
||||||
|
<a-tab-pane key="3" tab="审核处理">
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="reviewForm"
|
||||||
|
:rules="reviewRules"
|
||||||
|
:label-col="{ span: 6 }"
|
||||||
|
:wrapper-col="{ span: 18 }"
|
||||||
|
>
|
||||||
|
<a-form-item label="审核结果" name="status" required>
|
||||||
|
<a-radio-group v-model:value="reviewForm.status">
|
||||||
|
<a-radio :value="1">通过</a-radio>
|
||||||
|
<a-radio :value="2">驳回</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
v-if="reviewForm.status === 2"
|
||||||
|
label="驳回原因"
|
||||||
|
name="reason"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<a-textarea
|
||||||
|
v-model:value="reviewForm.reason"
|
||||||
|
:rows="4"
|
||||||
|
:maxlength="200"
|
||||||
|
placeholder="请输入驳回原因"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
v-if="reviewForm.status === 1"
|
||||||
|
label="手续费(%)"
|
||||||
|
name="commission"
|
||||||
|
>
|
||||||
|
<a-input-number
|
||||||
|
v-model:value="reviewForm.commission"
|
||||||
|
:step="0.1"
|
||||||
|
:max="100"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
placeholder="请输入手续费"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
v-if="reviewForm.status === 1"
|
||||||
|
label="是否自营"
|
||||||
|
name="ownStore"
|
||||||
|
>
|
||||||
|
<a-switch
|
||||||
|
checked-children="是"
|
||||||
|
un-checked-children="否"
|
||||||
|
:checked="reviewForm.ownStore === 1"
|
||||||
|
@update:checked="val => reviewForm.ownStore = val ? 1 : 0"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
v-if="reviewForm.status === 1"
|
||||||
|
label="是否推荐"
|
||||||
|
name="recommend"
|
||||||
|
>
|
||||||
|
<a-switch
|
||||||
|
checked-children="是"
|
||||||
|
un-checked-children="否"
|
||||||
|
:checked="reviewForm.recommend === 1"
|
||||||
|
@update:checked="val => reviewForm.recommend = val ? 1 : 0"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
v-if="reviewForm.status === 1"
|
||||||
|
label="是否需要审核"
|
||||||
|
name="goodsReview"
|
||||||
|
>
|
||||||
|
<a-switch
|
||||||
|
checked-children="是"
|
||||||
|
un-checked-children="否"
|
||||||
|
:checked="reviewForm.goodsReview === 1"
|
||||||
|
@update:checked="val => reviewForm.goodsReview = val ? 1 : 0"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
v-if="reviewForm.status === 1"
|
||||||
|
label="创建商户"
|
||||||
|
name="createMerchant"
|
||||||
|
>
|
||||||
|
<a-switch
|
||||||
|
checked-children="是"
|
||||||
|
un-checked-children="否"
|
||||||
|
:checked="reviewForm.createMerchant"
|
||||||
|
@update:checked="val => reviewForm.createMerchant = val"
|
||||||
|
/>
|
||||||
|
<div class="tips">审核通过后是否立即创建商户</div>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="备注" name="comments">
|
||||||
|
<a-textarea
|
||||||
|
v-model:value="reviewForm.comments"
|
||||||
|
:rows="4"
|
||||||
|
:maxlength="200"
|
||||||
|
placeholder="请输入备注信息"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</ele-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, watch } from 'vue';
|
||||||
|
import { Form, message } from 'ant-design-vue';
|
||||||
|
import { checkShopMerchantApply, createMerchantFromApply } from '@/api/shop/shopMerchantApply';
|
||||||
|
import { ShopMerchantApply } from '@/api/shop/shopMerchantApply/model';
|
||||||
|
|
||||||
|
const useForm = Form.useForm;
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
visible: boolean;
|
||||||
|
data?: ShopMerchantApply | null;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done'): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 提交状态
|
||||||
|
const loading = ref(false);
|
||||||
|
// 是否显示最大化切换按钮
|
||||||
|
const maxable = ref(true);
|
||||||
|
// 表单引用
|
||||||
|
const formRef = ref<any>(null);
|
||||||
|
// 当前标签页
|
||||||
|
const activeKey = ref('1');
|
||||||
|
|
||||||
|
// 其他资质文件
|
||||||
|
const otherFiles = ref<string[]>([]);
|
||||||
|
|
||||||
|
// 审核表单
|
||||||
|
const reviewForm = reactive({
|
||||||
|
status: 1, // 默认通过
|
||||||
|
reason: '',
|
||||||
|
commission: 0,
|
||||||
|
ownStore: 0,
|
||||||
|
recommend: 0,
|
||||||
|
goodsReview: 1,
|
||||||
|
createMerchant: true, // 默认创建商户
|
||||||
|
comments: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 审核表单验证规则
|
||||||
|
const reviewRules = reactive({
|
||||||
|
status: [
|
||||||
|
{ required: true, message: '请选择审核结果', trigger: 'change' }
|
||||||
|
],
|
||||||
|
reason: [
|
||||||
|
{ required: true, message: '请输入驳回原因', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 更新visible */
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交审核
|
||||||
|
const submitReview = () => {
|
||||||
|
if (!formRef.value) return;
|
||||||
|
|
||||||
|
formRef.value
|
||||||
|
.validate()
|
||||||
|
.then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
const formData = {
|
||||||
|
applyId: props.data?.applyId,
|
||||||
|
status: reviewForm.status,
|
||||||
|
reason: reviewForm.reason,
|
||||||
|
commission: reviewForm.commission,
|
||||||
|
ownStore: reviewForm.ownStore,
|
||||||
|
recommend: reviewForm.recommend,
|
||||||
|
goodsReview: reviewForm.goodsReview,
|
||||||
|
comments: reviewForm.comments
|
||||||
|
};
|
||||||
|
|
||||||
|
checkShopMerchantApply(formData)
|
||||||
|
.then(async (msg) => {
|
||||||
|
message.success(msg);
|
||||||
|
|
||||||
|
// 如果审核通过且需要创建商户
|
||||||
|
if (reviewForm.status === 1 && reviewForm.createMerchant && props.data?.applyId) {
|
||||||
|
try {
|
||||||
|
await createMerchantFromApply(props.data.applyId);
|
||||||
|
message.success('商户创建成功');
|
||||||
|
} catch (e) {
|
||||||
|
message.error('商户创建失败: ' + (e as Error).message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = false;
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
const { resetFields } = useForm(reviewForm, reviewRules);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(visible) => {
|
||||||
|
if (visible) {
|
||||||
|
resetFields();
|
||||||
|
reviewForm.status = 1;
|
||||||
|
reviewForm.createMerchant = true;
|
||||||
|
|
||||||
|
// 解析其他资质文件
|
||||||
|
otherFiles.value = [];
|
||||||
|
if (props.data?.files) {
|
||||||
|
try {
|
||||||
|
const files = JSON.parse(props.data.files);
|
||||||
|
if (Array.isArray(files)) {
|
||||||
|
otherFiles.value = files;
|
||||||
|
} else {
|
||||||
|
otherFiles.value = [props.data.files];
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
otherFiles.value = [props.data.files];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.file-preview {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.files-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
143
src/views/shop/shopMerchantApply/components/search.vue
Normal file
143
src/views/shop/shopMerchantApply/components/search.vue
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 搜索表单 -->
|
||||||
|
<a-form
|
||||||
|
:model="searchForm"
|
||||||
|
layout="inline"
|
||||||
|
class="search-form"
|
||||||
|
@finish="handleSearch"
|
||||||
|
>
|
||||||
|
<a-form-item label="商户名称">
|
||||||
|
<a-input
|
||||||
|
v-model:value="searchForm.merchantName"
|
||||||
|
placeholder="请输入商户名称"
|
||||||
|
allow-clear
|
||||||
|
style="width: 160px"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="联系人">
|
||||||
|
<a-input
|
||||||
|
v-model:value="searchForm.realName"
|
||||||
|
placeholder="请输入联系人"
|
||||||
|
allow-clear
|
||||||
|
style="width: 160px"
|
||||||
|
:maxlength="20"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="联系电话">
|
||||||
|
<a-input
|
||||||
|
v-model:value="searchForm.phone"
|
||||||
|
placeholder="请输入联系电话"
|
||||||
|
allow-clear
|
||||||
|
style="width: 160px"
|
||||||
|
:maxlength="11"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="店铺类型">
|
||||||
|
<a-input
|
||||||
|
v-model:value="searchForm.shopType"
|
||||||
|
placeholder="请输入店铺类型"
|
||||||
|
allow-clear
|
||||||
|
style="width: 160px"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="状态">
|
||||||
|
<a-select
|
||||||
|
v-model:value="searchForm.status"
|
||||||
|
placeholder="请选择状态"
|
||||||
|
allow-clear
|
||||||
|
style="width: 120px"
|
||||||
|
>
|
||||||
|
<a-select-option :value="0">待审核</a-select-option>
|
||||||
|
<a-select-option :value="1">审核通过</a-select-option>
|
||||||
|
<a-select-option :value="2">审核驳回</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item>
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" html-type="submit">
|
||||||
|
<template #icon>
|
||||||
|
<SearchOutlined />
|
||||||
|
</template>
|
||||||
|
查询
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="resetForm">
|
||||||
|
<template #icon>
|
||||||
|
<ReloadOutlined />
|
||||||
|
</template>
|
||||||
|
重置
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" @click="emit('add')">
|
||||||
|
<template #icon>
|
||||||
|
<PlusOutlined />
|
||||||
|
</template>
|
||||||
|
新增
|
||||||
|
</a-button>
|
||||||
|
<a-dropdown v-if="selection.length > 0">
|
||||||
|
<template #overlay>
|
||||||
|
<a-menu>
|
||||||
|
<a-menu-item key="1" @click="emit('remove', selection)">
|
||||||
|
<DeleteOutlined />
|
||||||
|
批量删除
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
|
<a-button>
|
||||||
|
批量操作
|
||||||
|
<DownOutlined />
|
||||||
|
</a-button>
|
||||||
|
</a-dropdown>
|
||||||
|
</a-space>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive } from 'vue';
|
||||||
|
import {
|
||||||
|
SearchOutlined,
|
||||||
|
ReloadOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
DeleteOutlined,
|
||||||
|
DownOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
const emit = defineEmits(['search', 'add', 'remove']);
|
||||||
|
|
||||||
|
// 搜索表单数据
|
||||||
|
const searchForm = reactive({
|
||||||
|
merchantName: '',
|
||||||
|
realName: '',
|
||||||
|
phone: '',
|
||||||
|
shopType: '',
|
||||||
|
status: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
// 搜索事件
|
||||||
|
const handleSearch = () => {
|
||||||
|
emit('search', { ...searchForm });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
Object.assign(searchForm, {
|
||||||
|
merchantName: '',
|
||||||
|
realName: '',
|
||||||
|
phone: '',
|
||||||
|
shopType: '',
|
||||||
|
status: undefined
|
||||||
|
});
|
||||||
|
emit('search', { ...searchForm });
|
||||||
|
};
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
selection: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,657 @@
|
|||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
:width="800"
|
||||||
|
: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="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||||
|
:wrapper-col="
|
||||||
|
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<a-tabs v-model:activeKey="activeKey">
|
||||||
|
<a-tab-pane key="1" tab="基本信息">
|
||||||
|
<a-form-item label="商户名称" name="merchantName">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
:maxlength="100"
|
||||||
|
placeholder="请输入商户名称"
|
||||||
|
v-model:value="form.merchantName"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="证件号码" name="merchantCode">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
:maxlength="50"
|
||||||
|
placeholder="请输入证件号码"
|
||||||
|
v-model:value="form.merchantCode"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="商户图标" name="image">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<a-image
|
||||||
|
v-if="form.image"
|
||||||
|
:src="form.image"
|
||||||
|
:width="80"
|
||||||
|
:height="80"
|
||||||
|
style="margin-right: 10px"
|
||||||
|
/>
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请选择图片`"
|
||||||
|
:limit="1"
|
||||||
|
:data="images"
|
||||||
|
@done="chooseImage"
|
||||||
|
@del="onDeleteImage"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
label="商户手机号"
|
||||||
|
name="phone"
|
||||||
|
extra="手机号码将用做于商户端的登录账号请填写真实手机号码"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
:maxlength="11"
|
||||||
|
placeholder="请输入商户手机号"
|
||||||
|
v-model:value="form.phone"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="商户姓名" name="realName">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
:maxlength="100"
|
||||||
|
placeholder="请输入商户姓名"
|
||||||
|
v-model:value="form.realName"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="身份证号码" name="idCard">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
:maxlength="18"
|
||||||
|
placeholder="请输入身份证号码"
|
||||||
|
v-model:value="form.idCard"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="店铺类型" name="shopType">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
:maxlength="50"
|
||||||
|
placeholder="请输入店铺类型"
|
||||||
|
v-model:value="form.shopType"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="商户分类" name="category">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
:maxlength="100"
|
||||||
|
placeholder="请输入商户分类"
|
||||||
|
v-model:value="form.category"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-tab-pane>
|
||||||
|
|
||||||
|
<a-tab-pane key="2" tab="资质信息">
|
||||||
|
<a-form-item label="营业执照" name="yyzz">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<a-image
|
||||||
|
v-if="form.yyzz"
|
||||||
|
:src="form.yyzz"
|
||||||
|
:width="80"
|
||||||
|
:height="80"
|
||||||
|
style="margin-right: 10px"
|
||||||
|
/>
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请选择营业执照`"
|
||||||
|
:limit="1"
|
||||||
|
:data="yyzzImages"
|
||||||
|
@done="chooseYyzzImage"
|
||||||
|
@del="onDeleteYyzzImage"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="身份证正面" name="sfz1">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<a-image
|
||||||
|
v-if="form.sfz1"
|
||||||
|
:src="form.sfz1"
|
||||||
|
:width="80"
|
||||||
|
:height="80"
|
||||||
|
style="margin-right: 10px"
|
||||||
|
/>
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请选择身份证正面`"
|
||||||
|
:limit="1"
|
||||||
|
:data="sfz1Images"
|
||||||
|
@done="chooseSfz1Image"
|
||||||
|
@del="onDeleteSfz1Image"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="身份证反面" name="sfz2">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<a-image
|
||||||
|
v-if="form.sfz2"
|
||||||
|
:src="form.sfz2"
|
||||||
|
:width="80"
|
||||||
|
:height="80"
|
||||||
|
style="margin-right: 10px"
|
||||||
|
/>
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请选择身份证反面`"
|
||||||
|
:limit="1"
|
||||||
|
:data="sfz2Images"
|
||||||
|
@done="chooseSfz2Image"
|
||||||
|
@del="onDeleteSfz2Image"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="资质图片" name="files">
|
||||||
|
<SelectFile
|
||||||
|
:placeholder="`请选择资质图片`"
|
||||||
|
:limit="9"
|
||||||
|
:data="files"
|
||||||
|
@done="chooseFiles"
|
||||||
|
@del="onDeleteFiles"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-tab-pane>
|
||||||
|
|
||||||
|
<a-tab-pane key="3" tab="其他信息">
|
||||||
|
<a-form-item label="手续费(%)" name="commission">
|
||||||
|
<a-input-number
|
||||||
|
:step="0.1"
|
||||||
|
:max="100"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
class="ele-fluid"
|
||||||
|
placeholder="请输入手续费"
|
||||||
|
v-model:value="form.commission"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="关键字" name="keywords">
|
||||||
|
<a-select
|
||||||
|
v-model:value="form.keywords"
|
||||||
|
mode="tags"
|
||||||
|
placeholder="输入关键词后回车"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="是否自营" name="ownStore">
|
||||||
|
<a-switch
|
||||||
|
checked-children="是"
|
||||||
|
un-checked-children="否"
|
||||||
|
:checked="form.ownStore === 1"
|
||||||
|
@update:checked="updateOwnStore"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="是否推荐" name="recommend">
|
||||||
|
<a-switch
|
||||||
|
checked-children="是"
|
||||||
|
un-checked-children="否"
|
||||||
|
:checked="form.recommend === 1"
|
||||||
|
@update:checked="updateRecommend"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="是否需要审核" name="goodsReview">
|
||||||
|
<a-switch
|
||||||
|
checked-children="是"
|
||||||
|
un-checked-children="否"
|
||||||
|
:checked="form.goodsReview === 1"
|
||||||
|
@update:checked="updateGoodsReview"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="状态" name="status">
|
||||||
|
<a-radio-group v-model:value="form.status">
|
||||||
|
<a-radio :value="0">待审核</a-radio>
|
||||||
|
<a-radio :value="1">审核通过</a-radio>
|
||||||
|
<a-radio :value="2">审核驳回</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="驳回原因" name="reason" v-if="form.status === 2">
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
:maxlength="200"
|
||||||
|
placeholder="请输入驳回原因"
|
||||||
|
v-model:value="form.reason"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="备注" name="comments">
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
:maxlength="200"
|
||||||
|
placeholder="请输入备注"
|
||||||
|
v-model:value="form.comments"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</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 { addShopMerchantApply, updateShopMerchantApply } from '@/api/shop/shopMerchantApply';
|
||||||
|
import { ShopMerchantApply } from '@/api/shop/shopMerchantApply/model';
|
||||||
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||||
|
import { FormInstance } from 'ant-design-vue/es/form';
|
||||||
|
import { FileRecord } from '@/api/system/file/model';
|
||||||
|
|
||||||
|
// 是否是修改
|
||||||
|
const isUpdate = ref(false);
|
||||||
|
const useForm = Form.useForm;
|
||||||
|
// 是否开启响应式布局
|
||||||
|
const themeStore = useThemeStore();
|
||||||
|
const { styleResponsive } = storeToRefs(themeStore);
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
// 弹窗是否打开
|
||||||
|
visible: boolean;
|
||||||
|
// 修改回显的数据
|
||||||
|
data?: ShopMerchantApply | null;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done'): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 提交状态
|
||||||
|
const loading = ref(false);
|
||||||
|
// 是否显示最大化切换按钮
|
||||||
|
const maxable = ref(true);
|
||||||
|
// 表格选中数据
|
||||||
|
const formRef = ref<FormInstance | null>(null);
|
||||||
|
const activeKey = ref('1');
|
||||||
|
|
||||||
|
// 图片数据
|
||||||
|
const images = ref<ItemType[]>([]);
|
||||||
|
const yyzzImages = ref<ItemType[]>([]);
|
||||||
|
const sfz1Images = ref<ItemType[]>([]);
|
||||||
|
const sfz2Images = ref<ItemType[]>([]);
|
||||||
|
const files = ref<ItemType[]>([]);
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const form = reactive<ShopMerchantApply>({
|
||||||
|
applyId: undefined,
|
||||||
|
type: 1,
|
||||||
|
merchantName: undefined,
|
||||||
|
merchantCode: undefined,
|
||||||
|
image: undefined,
|
||||||
|
phone: undefined,
|
||||||
|
realName: undefined,
|
||||||
|
idCard: undefined,
|
||||||
|
shopType: undefined,
|
||||||
|
category: undefined,
|
||||||
|
commission: undefined,
|
||||||
|
keywords: undefined,
|
||||||
|
yyzz: undefined,
|
||||||
|
sfz1: undefined,
|
||||||
|
sfz2: undefined,
|
||||||
|
files: undefined,
|
||||||
|
userId: undefined,
|
||||||
|
ownStore: 0,
|
||||||
|
recommend: 0,
|
||||||
|
goodsReview: 1,
|
||||||
|
name2: undefined,
|
||||||
|
reason: undefined,
|
||||||
|
comments: undefined,
|
||||||
|
status: 0,
|
||||||
|
sortNumber: 100,
|
||||||
|
tenantId: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 更新visible */
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const rules = reactive({
|
||||||
|
merchantName: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
type: 'string',
|
||||||
|
message: '请输入商户名称',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
merchantCode: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
type: 'string',
|
||||||
|
message: '请输入证件号码',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
phone: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入手机号',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
realName: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
type: 'string',
|
||||||
|
message: '请输入商户姓名',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
idCard: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
type: 'string',
|
||||||
|
message: '请输入身份证号码',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
shopType: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
type: 'string',
|
||||||
|
message: '请输入店铺类型',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
category: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
type: 'string',
|
||||||
|
message: '请输入商户分类',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yyzz: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请上传营业执照',
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
sfz1: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请上传身份证正面',
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
sfz2: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请上传身份证反面',
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 保存编辑 */
|
||||||
|
const save = () => {
|
||||||
|
if (!formRef.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
formRef.value
|
||||||
|
.validate()
|
||||||
|
.then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
// 处理关键字数组转字符串
|
||||||
|
let keywordsStr = '';
|
||||||
|
if (Array.isArray(form.keywords)) {
|
||||||
|
keywordsStr = JSON.stringify(form.keywords);
|
||||||
|
} else if (typeof form.keywords === 'string') {
|
||||||
|
try {
|
||||||
|
JSON.parse(form.keywords);
|
||||||
|
keywordsStr = form.keywords;
|
||||||
|
} catch {
|
||||||
|
keywordsStr = JSON.stringify([form.keywords]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const formData = {
|
||||||
|
...form,
|
||||||
|
keywords: keywordsStr,
|
||||||
|
files: files.value.length > 0 ? JSON.stringify(files.value.map(item => item.url)) : undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveOrUpdate = isUpdate.value ? updateShopMerchantApply : addShopMerchantApply;
|
||||||
|
saveOrUpdate(formData)
|
||||||
|
.then((msg) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.success(msg);
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 图片选择处理
|
||||||
|
const chooseImage = (data: FileRecord) => {
|
||||||
|
images.value = [{
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
}];
|
||||||
|
form.image = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteImage = () => {
|
||||||
|
images.value = [];
|
||||||
|
form.image = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseYyzzImage = (data: FileRecord) => {
|
||||||
|
yyzzImages.value = [{
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
}];
|
||||||
|
form.yyzz = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteYyzzImage = () => {
|
||||||
|
yyzzImages.value = [];
|
||||||
|
form.yyzz = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseSfz1Image = (data: FileRecord) => {
|
||||||
|
sfz1Images.value = [{
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
}];
|
||||||
|
form.sfz1 = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteSfz1Image = () => {
|
||||||
|
sfz1Images.value = [];
|
||||||
|
form.sfz1 = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseSfz2Image = (data: FileRecord) => {
|
||||||
|
sfz2Images.value = [{
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
}];
|
||||||
|
form.sfz2 = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteSfz2Image = () => {
|
||||||
|
sfz2Images.value = [];
|
||||||
|
form.sfz2 = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseFiles = (data: FileRecord) => {
|
||||||
|
files.value.push({
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteFiles = (index: number) => {
|
||||||
|
files.value.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Switch开关处理
|
||||||
|
const updateOwnStore = (value: boolean) => {
|
||||||
|
form.ownStore = value ? 1 : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateRecommend = (value: boolean) => {
|
||||||
|
form.recommend = value ? 1 : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateGoodsReview = (value: boolean) => {
|
||||||
|
form.goodsReview = value ? 1 : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { resetFields } = useForm(form, rules);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(visible) => {
|
||||||
|
if (visible) {
|
||||||
|
images.value = [];
|
||||||
|
yyzzImages.value = [];
|
||||||
|
sfz1Images.value = [];
|
||||||
|
sfz2Images.value = [];
|
||||||
|
files.value = [];
|
||||||
|
|
||||||
|
if (props.data) {
|
||||||
|
isUpdate.value = true;
|
||||||
|
assignObject(form, props.data);
|
||||||
|
|
||||||
|
// 处理图片回显
|
||||||
|
if (props.data.image) {
|
||||||
|
images.value.push({
|
||||||
|
uid: uuid(),
|
||||||
|
url: props.data.image,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.data.yyzz) {
|
||||||
|
yyzzImages.value.push({
|
||||||
|
uid: uuid(),
|
||||||
|
url: props.data.yyzz,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.data.sfz1) {
|
||||||
|
sfz1Images.value.push({
|
||||||
|
uid: uuid(),
|
||||||
|
url: props.data.sfz1,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.data.sfz2) {
|
||||||
|
sfz2Images.value.push({
|
||||||
|
uid: uuid(),
|
||||||
|
url: props.data.sfz2,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理关键字回显
|
||||||
|
if (props.data.keywords) {
|
||||||
|
try {
|
||||||
|
form.keywords = JSON.parse(props.data.keywords);
|
||||||
|
} catch {
|
||||||
|
form.keywords = [props.data.keywords];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理资质图片回显
|
||||||
|
if (props.data.files) {
|
||||||
|
try {
|
||||||
|
const fileUrls = JSON.parse(props.data.files);
|
||||||
|
if (Array.isArray(fileUrls)) {
|
||||||
|
fileUrls.forEach(url => {
|
||||||
|
files.value.push({
|
||||||
|
uid: uuid(),
|
||||||
|
url: url,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// 如果解析失败,当作单个URL处理
|
||||||
|
files.value.push({
|
||||||
|
uid: uuid(),
|
||||||
|
url: props.data.files,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isUpdate.value = false;
|
||||||
|
// 设置默认值
|
||||||
|
form.ownStore = 0;
|
||||||
|
form.recommend = 0;
|
||||||
|
form.goodsReview = 1;
|
||||||
|
form.status = 0;
|
||||||
|
form.sortNumber = 100;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resetFields();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ele-fluid {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
215
src/views/shop/shopMerchantApply/index.vue
Normal file
215
src/views/shop/shopMerchantApply/index.vue
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
<template>
|
||||||
|
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
|
<ele-pro-table
|
||||||
|
ref="tableRef"
|
||||||
|
row-key="applyId"
|
||||||
|
:columns="columns"
|
||||||
|
:datasource="datasource"
|
||||||
|
:customRow="customRow"
|
||||||
|
tool-class="ele-toolbar-form"
|
||||||
|
class="sys-org-table"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<Search
|
||||||
|
@search="reload"
|
||||||
|
:selection="selection"
|
||||||
|
@add="openEdit"
|
||||||
|
@remove="removeBatch"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'image'">
|
||||||
|
<a-image :src="record.image" :width="50" />
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'status'">
|
||||||
|
<a-tag v-if="record.status === 0" color="blue">待审核</a-tag>
|
||||||
|
<a-tag v-if="record.status === 1" color="green">审核通过</a-tag>
|
||||||
|
<a-tag v-if="record.status === 2" color="red">审核驳回</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a-space>
|
||||||
|
<a @click="openEdit(record)">详情</a>
|
||||||
|
<a-divider type="vertical" />
|
||||||
|
<a v-if="record.status === 0" @click="openReview(record)">审核</a>
|
||||||
|
<a-divider v-if="record.status === 0" type="vertical" />
|
||||||
|
<a-popconfirm
|
||||||
|
title="确定要删除此记录吗?"
|
||||||
|
@confirm="remove(record)"
|
||||||
|
>
|
||||||
|
<a class="ele-text-danger">删除</a>
|
||||||
|
</a-popconfirm>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</a-card>
|
||||||
|
</a-page-header>
|
||||||
|
|
||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<ShopMerchantApplyEdit
|
||||||
|
v-model:visible="showEdit"
|
||||||
|
:data="current"
|
||||||
|
@done="reload"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 审核弹窗 -->
|
||||||
|
<ApplyReview
|
||||||
|
v-model:visible="showReview"
|
||||||
|
:data="current"
|
||||||
|
@done="reload"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { message } from 'ant-design-vue';
|
||||||
|
import ShopMerchantApplyEdit from './components/shopMerchantApplyEdit.vue';
|
||||||
|
import ApplyReview from './components/applyReview.vue';
|
||||||
|
import Search from './components/search.vue';
|
||||||
|
import {
|
||||||
|
pageShopMerchantApply,
|
||||||
|
removeShopMerchantApply,
|
||||||
|
removeBatchShopMerchantApply
|
||||||
|
} from '@/api/shop/shopMerchantApply';
|
||||||
|
|
||||||
|
// 页面标题
|
||||||
|
const getPageTitle = () => {
|
||||||
|
return '商户入驻申请';
|
||||||
|
};
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const tableRef = ref();
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const columns = reactive([
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'applyId',
|
||||||
|
width: 80,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '商户名称',
|
||||||
|
dataIndex: 'merchantName',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '联系人',
|
||||||
|
dataIndex: 'realName'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '联系电话',
|
||||||
|
dataIndex: 'phone'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '店铺类型',
|
||||||
|
dataIndex: 'shopType'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
align: 'center',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
width: 180
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
align: 'center',
|
||||||
|
width: 150
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 表格数据源
|
||||||
|
const datasource = ({ page, limit, where }) => {
|
||||||
|
return pageShopMerchantApply({ ...where, page, limit });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 当前选中数据
|
||||||
|
const current = ref(null);
|
||||||
|
|
||||||
|
// 是否显示编辑弹窗
|
||||||
|
const showEdit = ref(false);
|
||||||
|
|
||||||
|
// 是否显示审核弹窗
|
||||||
|
const showReview = ref(false);
|
||||||
|
|
||||||
|
// 表格选中项
|
||||||
|
const selection = ref([]);
|
||||||
|
|
||||||
|
// 刷新表格
|
||||||
|
const reload = (where) => {
|
||||||
|
tableRef.value?.reload({ where });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开编辑弹窗
|
||||||
|
const openEdit = (record) => {
|
||||||
|
current.value = record;
|
||||||
|
showEdit.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开审核弹窗
|
||||||
|
const openReview = (record) => {
|
||||||
|
current.value = record;
|
||||||
|
showReview.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除单条记录
|
||||||
|
const remove = (record) => {
|
||||||
|
removeShopMerchantApply(record.applyId)
|
||||||
|
.then((msg) => {
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 批量删除
|
||||||
|
const removeBatch = (records) => {
|
||||||
|
const ids = records.map((item) => item.applyId);
|
||||||
|
removeBatchShopMerchantApply(ids)
|
||||||
|
.then((msg) => {
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 自定义行属性
|
||||||
|
const customRow = (record) => {
|
||||||
|
return {
|
||||||
|
// 行点击事件
|
||||||
|
onClick: () => {
|
||||||
|
// console.log(record);
|
||||||
|
},
|
||||||
|
// 行双击事件
|
||||||
|
onDblclick: () => {
|
||||||
|
openEdit(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.sys-org-table {
|
||||||
|
:deep(.ant-table-thead > tr > th) {
|
||||||
|
background-color: #fafafa;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-table-tbody > tr:hover > td) {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user