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

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>
<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-form-item>
<el-form-item label="收款账户号码" prop="account_number">
<el-form-item label="银行卡号" prop="account_number">
<el-input v-model="applyFormData.account_number" />
</el-form-item>
<el-form-item label="开户银行" prop="bank_branch_name">
@ -561,7 +561,6 @@
:remote-method="bankListRemoteMethod"
v-model="applyFormData.bank_branch_name"
placeholder="搜索银行名称"
size="large"
placement="top-start"
style="width: 350px"
:options="bankList2"
@ -607,7 +606,6 @@ import {
GetPostion,
GetBank,
merchApply,
re_apply,
GetAppDistrict,
} from "@/api/login";
@ -806,93 +804,13 @@ const rules = reactive({
],
// bank_branch_name: [{ required: true, message: '', trigger: 'blur' }],
account_number: [
{ required: true, message: "请输入收款账户号码", trigger: "blur" },
{ required: true, message: "请输入银行卡号", trigger: "blur" },
],
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 {
bank_name,
@ -978,8 +896,8 @@ const checkForm = async () => {
});
if (isValid) {
handleReApply();
// handleMerchApply
// handleReApply();
handleMerchApply
}
};
@ -1244,7 +1162,7 @@ const getOcrText = async (batchNo, type) => {
resolve(imgOcrRes?.data);
}
loading.value = false;
}, 1000);
}, 2000);
});
};
@ -1275,6 +1193,7 @@ const handleOcrText = async (batchNo, imgType) => {
}
loading.value = false;
formRef.value.validate()
};
const handleUploadSuccess = async (response, file, fileList, field) => {
@ -1315,6 +1234,8 @@ const handleUploadSuccess = async (response, file, fileList, field) => {
ElMessage.error(response.msg || "文件上传失败");
loading.value = false;
}
formRef.value.validate()
};
const handleUploadError = (error, file) => {