feat: 优化官网免费开店UI;重构注册登录弹窗UI交互;开发驳回审核填写资料功能(待完善,这种按需做的交互很繁琐很费精力)

This commit is contained in:
mixtan 2025-05-23 21:36:09 +08:00
parent 1c6ca5605c
commit 43fe64d286
5 changed files with 1922 additions and 948 deletions

View File

@ -150,6 +150,26 @@ export function re_apply(params){
}) })
} }
/**
* 获取申请信息详情
* @author Seven
* @data 2025-3-4
* @param { }
* @returns { mobile:13199998888 }
* @see https://mall.gpxscs.cn/mobile/shop/merch/detail
*/
export function GetAuditInfo(data) {
return new Promise((resolve, reject) => {
http({
url:'/api/mobile/shop/merch/detail',
method:'post',
data,
}).then(res=>{
resolve(res)
}).catch(e => reject(console.warn(e)))
})
}
/** /**
* 账号密码登录 * 账号密码登录

View File

@ -1,22 +1,30 @@
<template> <template>
<div class="register-box" v-if="isVisible"> <div class="register-box" v-if="isVisible">
<el-form :model="formData" :rules="rules" ref="formRef" label-width="120px" :hide-required-asterisk="true"> <el-form
<div class="register-container"> :model="formData"
<!-- 关闭按钮 --> :rules="rules"
<div class="register-close" @click="closeRegisterForm"> ref="formRef"
× label-width="88px"
</div> :hide-required-asterisk="true"
<!-- 标题 --> >
<h4>注册</h4> <div class="register-container">
<!-- 手机号输入项 --> <!-- 关闭按钮 -->
<el-form-item label="手机号" prop="phoneNumber"> <div class="register-close" @click="closeRegisterForm">×</div>
<el-input v-model="formData.phoneNumber" placeholder="输入11位手机号" maxlength="11" /> <!-- 标题 -->
</el-form-item> <h4>欢迎登录注册</h4>
<!-- 验证码输入项 --> <!-- 手机号输入项 -->
<el-form-item label="验证码" prop="verificationCode"> <el-form-item label="手机号" prop="phoneNumber">
<div class="verifyAndButton"> <el-input
v-model="formData.phoneNumber"
placeholder="请输入手机号"
maxlength="11"
size="large"
/>
</el-form-item>
<!-- 验证码输入项 -->
<el-form-item label="验证码" prop="verificationCode">
<!-- <div class="verifyAndButton">
<el-input v-model="formData.verificationCode" placeholder="输入验证码" style="flex: 1;" maxlength="4" /> <el-input v-model="formData.verificationCode" placeholder="输入验证码" style="flex: 1;" maxlength="4" />
<!-- 获取验证码按钮 -->
<button type="button" v-if="!sendCode" :style="{ <button type="button" v-if="!sendCode" :style="{
marginLeft: '10px', marginLeft: '10px',
width: '80px', width: '80px',
@ -27,7 +35,6 @@
cursor: formData.phoneNumber.length === 11? 'pointer' : 'not-allowed' cursor: formData.phoneNumber.length === 11? 'pointer' : 'not-allowed'
}" }"
:disabled="formData.phoneNumber.length!== 11" @click="getVerify_code">获取验证码</button> :disabled="formData.phoneNumber.length!== 11" @click="getVerify_code">获取验证码</button>
<!-- 倒计时按钮 -->
<button v-if="sendCode" :style="{ <button v-if="sendCode" :style="{
marginLeft: '10px', marginLeft: '10px',
width: '80px', width: '80px',
@ -39,36 +46,45 @@
}" disabled> }" disabled>
{{ countdown }}秒后重发 {{ countdown }}秒后重发
</button> </button>
</div> </div> -->
</el-form-item> <el-input
<!-- 注册按钮 --> v-model="formData.verificationCode"
<el-button type="primary" @click="handleRegister">注册</el-button> placeholder="验证码"
<p>未注册过的手机号将自动注册</p> size="large"
</div> >
</el-form> <template #append>
</div> <el-button type="primary" class="btn_code" size="large" v-if="!sendCode" :disabled="formData.phoneNumber.length!== 11" @click="getVerify_code" round>发送验证码</el-button>
<el-button type="primary" class="btn_code" size="large" v-if="sendCode" disabled round>{{ countdown }}S</el-button>
</template>
</el-input>
</el-form-item>
<div class="foot">
<el-button class="btn_sumit" type="primary" size="large" :disabled="!formData.phoneNumber || !formData.verificationCode" round @click="handleRegister">确定</el-button>
</div>
</div>
</el-form>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, defineProps, defineEmits, onMounted, onUnmounted } from 'vue'; import { ref, defineProps, defineEmits, onMounted, onUnmounted } from "vue";
import { useUserStore } from '@/stores/userStore'; import { useUserStore } from "@/stores/userStore";
import { useRouter } from 'vue-router'; import { useRouter } from "vue-router";
import { GetSmsCode, GetLogin } from '@/api/login'; import { GetSmsCode, GetLogin } from "@/api/login";
import { getApproval_status } from '@/api/login'; import { getApproval_status } from "@/api/login";
import { ElMessage } from 'element-plus'; import { ElMessage } from "element-plus";
const props = defineProps({ const props = defineProps({
isVisible: { isVisible: {
type: Boolean, type: Boolean,
default: false default: false,
} },
}); });
const emits = defineEmits(['close-register-form']); const emits = defineEmits(["close-register-form"]);
const formData = ref({ const formData = ref({
phoneNumber: '', phoneNumber: "",
verificationCode: '' verificationCode: "",
}); });
const router = useRouter(); const router = useRouter();
@ -76,228 +92,194 @@ const userStore = useUserStore();
const sendCode = ref(false); const sendCode = ref(false);
const countdown = ref(0); const countdown = ref(0);
let timer: ReturnType<typeof setInterval>; let timer: ReturnType<typeof setInterval>;
const formRef = ref<InstanceType<typeof import('element-plus/es')['ElForm']>>(); const formRef = ref<InstanceType<typeof import("element-plus/es")["ElForm"]>>();
// verificationError ref // verificationError ref
// const verificationError = ref(''); // const verificationError = ref('');
const closeRegisterForm = () => { const closeRegisterForm = () => {
emits('close-register-form'); emits("close-register-form");
}; };
const getVerify_code = async () => { const getVerify_code = async () => {
const params = { const params = {
number: formData.value.phoneNumber number: formData.value.phoneNumber,
}; };
const res = await GetSmsCode(params); const res = await GetSmsCode(params);
if (res && res.status === 200) { if (res && res.status === 200) {
const clicktime = new Date().getTime() + 60000; const clicktime = new Date().getTime() + 60000;
localStorage.setItem('Countdown', JSON.stringify(clicktime)); localStorage.setItem("Countdown", JSON.stringify(clicktime));
sendCode.value = true; sendCode.value = true;
countdown.value = 60; countdown.value = 60;
startCountdown(); startCountdown();
} else { } else {
console.log('获取失败'); console.log("获取失败");
} }
}; };
const startCountdown = () => { const startCountdown = () => {
timer = setInterval(() => { timer = setInterval(() => {
if (countdown.value > 0) { if (countdown.value > 0) {
countdown.value--; countdown.value--;
} else { } else {
clearInterval(timer); clearInterval(timer);
sendCode.value = false; sendCode.value = false;
localStorage.removeItem('Countdown'); localStorage.removeItem("Countdown");
} }
}, 1000); }, 1000);
}; };
const register = async () => { const register = async () => {
const params = { const params = {
user_mobile: formData.value.phoneNumber, user_mobile: formData.value.phoneNumber,
rand_key: formData.value.phoneNumber, rand_key: formData.value.phoneNumber,
verify_code: formData.value.verificationCode verify_code: formData.value.verificationCode,
}; };
const res = await GetLogin(params); const res = await GetLogin(params);
if (res && res.status === 200 && res.data && res.data) { if (res && res.status === 200 && res.data && res.data) {
userStore.setToken(res.data.token); userStore.setToken(res.data.token);
userStore.setMobilePhone(formData.value.phoneNumber); userStore.setMobilePhone(formData.value.phoneNumber);
formData.value.phoneNumber = ''; formData.value.phoneNumber = "";
formData.value.verificationCode = ''; formData.value.verificationCode = "";
closeRegisterForm(); closeRegisterForm();
try { try {
const approvalRes = await getApproval_status(); const approvalRes = await getApproval_status();
if (approvalRes.data.code === 0 && approvalRes.data.status === 200) { if (approvalRes.data.code === 0 && approvalRes.data.status === 200) {
const approvalStatus = approvalRes.data.approval_status; const approvalStatus = approvalRes.data.approval_status;
localStorage.setItem('approval_status', approvalStatus); localStorage.setItem("approval_status", approvalStatus);
if (approvalStatus == '4') { if (approvalStatus == "4") {
router.push({ name: 'start' }); router.push({ name: "start" });
} else {
router.push({ name: 'check' });
}
}
} catch (error) {
console.error('获取审批状态失败:', error);
}
} else {
if (res.status === 250) {
// 使 ElMessage
ElMessage.error('验证码错误');
} else { } else {
console.log('操作返回的信息', res.data.msg); router.push({ name: "check" });
console.log('hhhhh', res);
} }
}
} catch (error) {
console.error("获取审批状态失败:", error);
} }
} else {
if (res.status === 250) {
// 使 ElMessage
ElMessage.error("验证码错误");
} else {
console.log("操作返回的信息", res.data.msg);
console.log("hhhhh", res);
}
}
}; };
const rules = ref({ const rules = ref({
phoneNumber: [ phoneNumber: [
{ required: true, message: '请输入手机号', trigger: 'blur' }, { required: true, message: "请输入手机号", trigger: "blur" },
{ pattern: /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/, message: '请输入正确的11位手机号', trigger: 'blur' } {
], pattern:
verificationCode: [ /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
{ required: true, message: '请输入验证码', trigger: 'blur' } message: "请输入正确的11位手机号",
] trigger: "blur",
},
],
verificationCode: [
{ required: true, message: "请输入验证码", trigger: "blur" },
],
}); });
const handleRegister = () => { const handleRegister = () => {
formRef.value?.validate((valid) => { formRef.value?.validate((valid) => {
if (valid) { if (valid) {
register(); register();
} else { } else {
ElMessage.error('请正确填写注册信息!'); ElMessage.error("请正确填写注册信息!");
} }
}); });
}; };
onMounted(() => { onMounted(() => {
const savedCountdown = localStorage.getItem('Countdown'); const savedCountdown = localStorage.getItem("Countdown");
if (savedCountdown) { if (savedCountdown) {
const clicktime = JSON.parse(savedCountdown) as number; const clicktime = JSON.parse(savedCountdown) as number;
const currentTime = new Date().getTime(); const currentTime = new Date().getTime();
const remainingTime = (clicktime - currentTime) / 1000; const remainingTime = (clicktime - currentTime) / 1000;
if (remainingTime > 0) { if (remainingTime > 0) {
sendCode.value = true; sendCode.value = true;
countdown.value = Math.ceil(remainingTime); countdown.value = Math.ceil(remainingTime);
startCountdown(); startCountdown();
} else { } else {
localStorage.removeItem('Countdown'); localStorage.removeItem("Countdown");
sendCode.value = false; sendCode.value = false;
}
} }
}
}); });
onUnmounted(() => { onUnmounted(() => {
if (timer) { if (timer) {
clearInterval(timer); clearInterval(timer);
} }
}); });
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
$primary-color: #007BFF;
$secondary-color: #6C757D;
$border-radius: 8px;
$box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
.register-box { .register-box {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; right: 0;
height: 100%; bottom: 0;
background-color: rgba(0, 0, 0, 0.4); display: flex;
display: flex; justify-content: center;
justify-content: center; align-items: center;
align-items: center; background-color: rgba(0, 0, 0, 0.75);
z-index: 1000101; z-index: 1000101;
} }
.el-message { .el-message {
z-index: 1000102 !important; // z-index z-index: 1000102 !important; // z-index
} }
.register-container {
padding: 35px;
border-radius: $border-radius;
box-shadow: $box-shadow;
background-color: #fff;
width: 400px;
transition: box-shadow 0.3s ease;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
&:hover {
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
}
h4 { .foot{
color: $primary-color; padding-top: 20px;
text-align: center; .btn_sumit{
margin-bottom: 30px; display: block;
font-size: 24px;
}
.el-form-item {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
label{
width: 100px !important;
}
}
.el-input {
width: 100%; width: 100%;
} }
.verifyAndButton { .btn_code{
display: flex; display: block;
width: 100%; width: 60px;
}
button {
width: 100%;
padding: 2px;
background-color: #007BFF;
color: #fff;
border: none;
border-radius: $border-radius;
font-size: 20px;
cursor: pointer;
transition: background-color 0.3s ease;
&:hover {
background-color: #0056b3;
}
}
.register-close {
position: absolute;
top: 10px;
right: 10px;
font-size: 20px;
cursor: pointer;
color: $secondary-color;
&:hover {
color: $primary-color;
}
}
.error-message {
// div
color: red;
margin-top: 5px;
font-size: 12px;
}
p {
color: red;
margin: 10px 0;
} }
} }
.register-container {
padding: 25px;
border-radius: 10px;
background-color: #fff;
width: 500px;
position: relative;
h4 {
color: #666;
text-align: center;
margin-bottom: 30px;
font-size: 24px;
}
.el-input {
width: 100%;
}
.verifyAndButton {
display: flex;
width: 100%;
}
.register-close {
position: absolute;
top: 10px;
right: 10px;
}
p {
color: red;
margin: 10px 0;
}
}
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,200 @@
const formConfig = [
{
type:"input",
key:'contact_name',
label:'联系人',
placeholder:'请输入联系人',
},
{
type:"select",
key:'biz_category',
label:'经营品类',
isReadonly:true,
style:"pointer-events: none",
placeholder:'请选择经营品类',
},
{
type:"input",
key:'store_name',
label:'门店名称',
placeholder:'请输入门店名称',
},
{
type:"select",
key:'mapAddress',
label:'店铺所在地区',
isReadonly:true,
style:"pointer-events: none",
placeholder:'请在地图上选择门店地址',
},
{
type:"input",
key:'store_address',
label:'店铺详细地址',
placeholder:'请输入店铺详细地址',
},
{
type:'upload',
key:'storefrontImg',
label:'门脸图片',
class:"upload-1",
placeholder:'',
imgUrlArr:[],
imgWidth:270,
imgHeight:150
},
{
type:'upload',
key:'surroundingsImg',
class:"upload-2",
label:'环境图片',
placeholder:'',
imgUrlArr:[],
imgWidth:270,
imgHeight:150
},
{
type:"input",
key:'license_number',
label:'许可证编号',
placeholder:'请输入许可证编号',
},
{
type:"input",
key:'biz_license_number',
label:'注册号',
placeholder:'请输入注册号',
},
{
type:"input",
key:'biz_license_company',
label:'公司名称',
placeholder:'请输入公司名称',
},
{
type:"input",
key:'legal_person_name',
label:'法人姓名',
placeholder:'请输入法人姓名',
},
{
type:"input",
key:'legal_person_mobile',
label:'法人手机号',
placeholder:'请输入法人手机号',
},
{
type:"input",
key:'legal_person_id_number',
label:'法人身份证号码',
placeholder:'请输入法人身份证号',
},
{
type:'upload',
key:'biz_license_image',
class:"upload-3",
label:'营业执照图片',
placeholder:'',
imgUrlArr:[],
imgWidth:125,
imgHeight:88
},
{
type:"select",
key:'license_type',
label:'许可证类型',
isReadonly:true,
style:"pointer-events: none",
placeholder:'请选择许可证类型',
},
{
type:"input",
key:'license_number',
label:'许可证编号',
placeholder:'',
},
{
type:"input",
type:'upload',
key:'license_image',
label:'许可证图片',
class:"upload-4",
placeholder:'',
imgUrlArr:[],
imgWidth:125,
imgHeight:88,
imgUpMaxCount:5
},
{
type:'upload',
key:'legal_person_id_images',
label:'法人身份证正面图片',
class:"upload-5",
placeholder:'',
imgUrlArr:[],
imgWidth:180,
imgHeight:110
},
{
type:'upload',
key:'legal_person_id_images2',
label:'法人身份证反面图片',
class:"upload-6",
placeholder:'',
imgUrlArr:[],
imgWidth:180,
imgHeight:110
},
{
type:"select",
key:'bank_name',
label:'开户银行',
isReadonly:true,
style:"pointer-events: none",
placeholder:'请选择开户银行',
},
{
key:'bank_branch_name',
label:'开户支行',
placeholder:'请输入开户支行名称',
},
{
type:"input",
key:'account_number',
label:'银行卡号',
placeholder:'请输入银行卡号',
},
{
type:"input",
key:'account_holder_name',
label:'开户名称',
placeholder:'请输入开户名称',
},
{
type:"input",
key:'individual_id_number',
label:'个人身份证号码',
placeholder:'请输入个人身份证号码',
},
{
type:'upload',
key:'individual_id_images',
label:'个人身份证正面图片',
class:"upload-5",
placeholder:'',
imgUrlArr:[]
},
{
type:'upload',
key:'individual_id_images2',
label:'个人身份证反面图片',
class:"upload-5",
placeholder:'',
imgUrlArr:[]
},
]
export default {
formConfig,
}

View File

@ -546,10 +546,10 @@
> >
</el-form-item> </el-form-item>
<template v-if="applyFormData.bank_image"> <template v-if="applyFormData.bank_image">
<el-form-item label="账户姓名" prop="account_holder_name"> <el-form-item label="开户名称" prop="account_holder_name">
<el-input v-model="applyFormData.account_holder_name" /> <el-input v-model="applyFormData.account_holder_name" />
</el-form-item> </el-form-item>
<el-form-item label="收款账户号码" prop="account_number"> <el-form-item label="银行卡号" prop="account_number">
<el-input v-model="applyFormData.account_number" /> <el-input v-model="applyFormData.account_number" />
</el-form-item> </el-form-item>
<el-form-item label="开户银行" prop="bank_branch_name"> <el-form-item label="开户银行" prop="bank_branch_name">
@ -561,7 +561,6 @@
:remote-method="bankListRemoteMethod" :remote-method="bankListRemoteMethod"
v-model="applyFormData.bank_branch_name" v-model="applyFormData.bank_branch_name"
placeholder="搜索银行名称" placeholder="搜索银行名称"
size="large"
placement="top-start" placement="top-start"
style="width: 350px" style="width: 350px"
:options="bankList2" :options="bankList2"
@ -607,7 +606,6 @@ import {
GetPostion, GetPostion,
GetBank, GetBank,
merchApply, merchApply,
re_apply,
GetAppDistrict, GetAppDistrict,
} from "@/api/login"; } from "@/api/login";
@ -806,93 +804,13 @@ const rules = reactive({
], ],
// bank_branch_name: [{ required: true, message: '', trigger: 'blur' }], // bank_branch_name: [{ required: true, message: '', trigger: 'blur' }],
account_number: [ account_number: [
{ required: true, message: "请输入收款账户号码", trigger: "blur" }, { required: true, message: "请输入银行卡号", trigger: "blur" },
], ],
account_holder_name: [ account_holder_name: [
{ required: true, message: "请输入账户姓名", trigger: "blur" }, { required: true, message: "请输入开户名称", trigger: "blur" },
], ],
}); });
const handleReApply = async () => {
const {
bank_name,
bank_district,
bank_area,
openning_bank_code,
clearing_bank_code,
account_number,
account_holder_name,
biz_category,
biz_license_company,
biz_license_image,
biz_license_number,
biz_second_category,
city_id,
contact_name,
county_id,
entity_type,
environment_image,
front_facade_image,
individual_id_images,
individual_id_images2,
individual_id_number,
legal_person_id_images,
legal_person_id_images2,
legal_person_id_number,
legal_person_mobile,
legal_person_name,
license_image,
license_number,
license_type,
login_mobile,
province_id,
store_address,
store_latitude,
store_longitude,
store_name,
store_area,
} = applyFormData;
const res = await re_apply({
id: 15,
bank_name,
bank_district,
bank_area,
openning_bank_code,
clearing_bank_code,
account_number,
account_holder_name,
biz_category,
biz_license_company,
biz_license_image,
biz_license_number,
biz_second_category,
city_id,
contact_name,
county_id,
entity_type,
environment_image,
front_facade_image,
individual_id_images,
individual_id_images2,
individual_id_number,
legal_person_id_images,
legal_person_id_images2,
legal_person_id_number,
legal_person_mobile,
legal_person_name,
license_image,
license_number,
license_type,
login_mobile,
province_id,
store_address: store_area.replace(/\//g, "") + store_address,
store_latitude,
store_longitude,
store_name,
store_area,
});
};
const handleMerchApply = async () => { const handleMerchApply = async () => {
const { const {
bank_name, bank_name,
@ -978,8 +896,8 @@ const checkForm = async () => {
}); });
if (isValid) { if (isValid) {
handleReApply(); // handleReApply();
// handleMerchApply handleMerchApply
} }
}; };
@ -1244,7 +1162,7 @@ const getOcrText = async (batchNo, type) => {
resolve(imgOcrRes?.data); resolve(imgOcrRes?.data);
} }
loading.value = false; loading.value = false;
}, 1000); }, 2000);
}); });
}; };
@ -1275,6 +1193,7 @@ const handleOcrText = async (batchNo, imgType) => {
} }
loading.value = false; loading.value = false;
formRef.value.validate()
}; };
const handleUploadSuccess = async (response, file, fileList, field) => { const handleUploadSuccess = async (response, file, fileList, field) => {
@ -1315,6 +1234,8 @@ const handleUploadSuccess = async (response, file, fileList, field) => {
ElMessage.error(response.msg || "文件上传失败"); ElMessage.error(response.msg || "文件上传失败");
loading.value = false; loading.value = false;
} }
formRef.value.validate()
}; };
const handleUploadError = (error, file) => { const handleUploadError = (error, file) => {