website/src/views/start/start.vue

677 lines
30 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="signUp-container">
<h1>免费开店</h1>
<!-- 步骤条 -->
<div class="steps-container" style="margin: 20px;">
<el-steps :active="active" finish-status="success" align-center>
<el-step title="第一步:填写店铺信息" />
<el-step title="第二步:填写资质信息" />
<el-step title="第三步:填写收款信息" />
</el-steps>
</div>
<div class="form-submit">
<el-form :model="applyFormData" :rules="rules" ref="formRef" label-width="120px" style="max-width: 600px">
<div v-show="active === 1">
<!-- 第一步表单内容 -->
<el-form-item label="联系人" prop="contact_name">
<el-input v-model="applyFormData.contact_name" placeholder="请输入联系人姓名" />
</el-form-item>
<el-form-item label="联系电话" prop="login_mobile">
<el-input v-model="applyFormData.login_mobile" placeholder="请输入联系人电话" disabled />
</el-form-item>
<el-form-item label="经营品类" prop="biz_category">
<el-cascader v-model="applyFormData.biz_category" :options="cascaderOptions"
placeholder="请选择经营品类" :show-all-levels="false" @change="handleChangeBizCategory"
clearable />
</el-form-item>
<el-form-item label="门店名称" prop="store_name">
<el-input v-model="applyFormData.store_name" placeholder="请输入门店名称" />
</el-form-item>
<el-form-item label="地图地址" prop="map_address">
<el-cascader v-model="applyFormData.map_address" :options="cascaderOptions2"
@change="handleChange" />
</el-form-item>
<el-form-item label="搜索定位" prop="position">
<el-autocomplete v-model="applyFormData.position" :fetch-suggestions="querySearch"
value-key="value" :options="autocompleteOptions" @select="handleSelect">
<template #default="{ item }">
<div class="auto-item" v-if="item">
<div>
<p>{{ item.name }}</p> <!-- 显示名称 -->
</div>
<div>
<span>{{ item.address }}</span> <!-- 显示地址 -->
</div>
</div>
</template>
</el-autocomplete>
</el-form-item>
<el-form-item label="详细地址" prop="store_address">
<el-input v-model="applyFormData.store_address" placeholder="请输入详细地址" />
</el-form-item>
<el-form-item :label="getLabel('front_facade_image', 1)" prop="front_facade_image">
<el-upload ref="uploadRef" multiple :limit="1" list-type="picture-card" :auto-upload="true"
v-model="applyFormData.front_facade_image"
:on-remove="(file, fileList) => handleRemove(file, fileList, 'front_facade_image')"
:on-success="(response, file, fileList) => handleUploadSuccess(response, file, fileList, 'front_facade_image')"
:on-error="handleUploadError" :on-exceed="handleExceed" :before-upload="beforeUpload"
:action="uploadUrl" name="upfile"
:class="{ 'upload-hidden': isUploadHidden('front_facade_image') }">
<el-icon class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item :label="getLabel('environment_image', 1)" prop="environment_image">
<el-upload ref="uploadRef" multiple :limit="1" list-type="picture-card" :auto-upload="true"
v-model="applyFormData.environment_image"
:on-remove="(file, fileList) => handleRemove(file, fileList, 'environment_image')"
:on-success="(response, file, fileList) => handleUploadSuccess(response, file, fileList, 'environment_image')"
:on-error="handleUploadError" :before-upload="beforeUpload" :action="uploadUrl"
name="upfile" :class="{ 'upload-hidden': isUploadHidden('environment_image') }">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</div>
<div v-show="active === 2">
<el-form-item label="选择身份" prop="entity_type">
<el-radio-group v-model="applyFormData.entity_type" @change="clearOtherFields">
<el-radio :value="1">企业</el-radio>
<el-radio :value="2">个人</el-radio>
</el-radio-group>
</el-form-item>
<div v-if="applyFormData.entity_type === 1">
<!-- <el-form-item label="许可证类型" prop="license_type">
<el-select v-model="applyFormData.license_type" value-key="" placeholder="请选择类型" clearable
@change="">
<el-option v-for="item in optionsPermitType" :key="item.value2" :label="item.label"
:value="item.value2">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="许可证编号" prop="license_number">
<el-input v-model="applyFormData.license_number" placeholder="请输入许可证编号" />
</el-form-item> -->
<!-- <el-form-item label="营业执照编号" prop="biz_license_number">
<el-input v-model="applyFormData.biz_license_number" placeholder="请输入营业执照编号" />
</el-form-item> -->
<el-form-item label="营业执照公司名" prop="biz_license_company">
<el-input v-model="applyFormData.biz_license_company" placeholder="请输入营业执照公司名" />
</el-form-item>
<el-form-item label="负责人姓名" prop="legal_person_name">
<el-input v-model="applyFormData.legal_person_name" placeholder="请输入负责人姓名" />
</el-form-item>
<!-- <el-form-item label="负责人手机号" prop="legal_person_mobile">
<el-input v-model="applyFormData.legal_person_mobile" placeholder="请输入法人手机号" />
</el-form-item> -->
<!-- <el-form-item label="负责身份证号" prop="legal_person_id_number">
<el-input v-model="applyFormData.legal_person_id_number" placeholder="请输入法人身份证号" />
</el-form-item> -->
<el-form-item :label="getLabel('biz_license_image', 1)" prop="biz_license_image">
<el-upload ref="uploadRef" multiple :limit="1" list-type="picture-card" :auto-upload="true"
v-model="applyFormData.biz_license_image"
:on-remove="(file, fileList) => handleRemove(file, fileList, 'biz_license_image')"
:on-success="(response, file, fileList) => handleUploadSuccess(response, file, fileList, 'biz_license_image')"
:on-error="handleUploadError" :before-upload="beforeUpload" :action="uploadUrl"
name="upfile" :class="{ 'upload-hidden': isUploadHidden('biz_license_image') }">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item :label="getLabel('license_image', 5)" prop="license_image">
<el-upload ref="uploadRef" multiple :limit="5" list-type="picture-card" :auto-upload="true"
v-model="applyFormData.license_image"
:on-remove="(file, fileList) => handleRemove(file, fileList, 'license_image')"
:on-success="(response, file, fileList) => handleUploadSuccess(response, file, fileList, 'license_image')"
:on-error="handleUploadError" :before-upload="beforeUpload" :action="uploadUrl"
name="upfile" :class="{ 'upload-hidden': isUploadHidden('license_image') }">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<!-- 法人身份证正反面 -->
<el-form-item :label="getLabel('legal_person_id_images', 1)" prop="legal_person_id_images">
<el-upload ref="uploadRef" :limit="1" list-type="picture-card" :auto-upload="true"
v-model="applyFormData.legal_person_id_images"
:on-remove="(file, fileList) => handleRemove(file, fileList, 'legal_person_id_images')"
:on-success="(response, file, fileList) => handleUploadSuccess(response, file, fileList, 'legal_person_id_images')"
:on-error="handleUploadError" :before-upload="beforeUpload" :action="uploadUrl"
name="upfile" :class="{ 'upload-hidden': isUploadHidden('legal_person_id_images') }">
<el-icon class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item :label="getLabel('legal_person_id_images2', 1)" prop="legal_person_id_images2">
<el-upload ref="uploadRef" :limit="1" list-type="picture-card" :auto-upload="true"
v-model="applyFormData.legal_person_id_images2"
:on-remove="(file, fileList) => handleRemove(file, fileList, 'legal_person_id_images2')"
:on-success="(response, file, fileList) => handleUploadSuccess(response, file, fileList, 'legal_person_id_images2')"
:on-error="handleUploadError" :before-upload="beforeUpload" :action="uploadUrl"
name="upfile" :class="{ 'upload-hidden': isUploadHidden('legal_person_id_images2') }">
<el-icon class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</div>
<div v-if="applyFormData.entity_type === 2">
<el-form-item label="个人身份证号" prop="individual_id_number">
<el-input v-model="applyFormData.individual_id_number" placeholder="请输入个人身份证号" />
</el-form-item>
<!-- 个人身份证正反面 -->
<el-form-item :label="getLabel('individual_id_images', 1)" prop="individual_id_images">
<el-upload ref="uploadRef" :limit="1" list-type="picture-card" :auto-upload="true"
v-model="applyFormData.individual_id_images"
:on-remove="(file, fileList) => handleRemove(file, fileList, 'individual_id_images')"
:on-success="(response, file, fileList) => handleUploadSuccess(response, file, fileList, 'individual_id_images')"
:on-error="handleUploadError" :before-upload="beforeUpload" :action="uploadUrl"
name="upfile" :class="{ 'upload-hidden': isUploadHidden('individual_id_images') }">
<el-icon class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<el-form-item :label="getLabel('individual_id_images2', 1)" prop="individual_id_images2">
<el-upload ref="uploadRef" :limit="1" list-type="picture-card" :auto-upload="true"
v-model="applyFormData.individual_id_images2"
:on-remove="(file, fileList) => handleRemove(file, fileList, 'individual_id_images2')"
:on-success="(response, file, fileList) => handleUploadSuccess(response, file, fileList, 'individual_id_images2')"
:on-error="handleUploadError" :before-upload="beforeUpload" :action="uploadUrl"
name="upfile" :class="{ 'upload-hidden': isUploadHidden('individual_id_images2') }">
<el-icon class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</div>
</div>
<div v-show="active === 3">
<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-input v-model="applyFormData.account_number" />
</el-form-item>
<el-form-item label="开户银行" prop="bank_name">
<el-select v-model="applyFormData.bank_name" placeholder="请选择银行" size="large"
style="width: 240px">
<el-option v-for="bank in bankList2" :key="bank.id" :label="bank.bank_name"
:value="bank.bank_name" />
</el-select>
</el-form-item>
<el-form-item label="支行名称" prop="bank_branch_name">
<el-input v-model="applyFormData.bank_branch_name" />
</el-form-item>
</div>
</el-form>
<div class="form-button">
<el-button v-if="active > 1" style="margin-top: 12px" @click="pre" class="custom-button">上一步</el-button>
<el-button v-if="active < 3" style="margin-top: 12px;float: right;" @click="next"
class="custom-button">下一步</el-button>
<el-button v-if="active === 3" style="margin-top: 12px;float: right;" @click="merchToApply"
class="custom-button">提交</el-button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted, watch } from 'vue'
import cityData from '../../stores/cityData';
import type { CityDataStructure } from '../../stores/cityData';
import { ElMessage } from 'element-plus';
import { useUserStore } from '@/stores/userStore';
import { Plus } from '@element-plus/icons-vue'
import { GetStoreCategories, transformStoreCategories, GetPostion, GetBank, merchApply, GetAppDistrict } from '@/api/login';
const active = ref(1);
const formRef = ref(null);
const applyFormData = reactive({
bank_name: '',
bank_branch_name: '',
account_number: '',
account_holder_name: '',
biz_category: null,
biz_license_company: '',
biz_license_image: '',
biz_license_number: '',
biz_second_category: null,
city_id: null,
contact_name: '',
county_id: null,
entity_type: 1,
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: null,
login_mobile: localStorage.getItem("mobilePhone"),
province_id: null,
store_address: '',
map_address: '',
position: '',
store_latitude: null,
store_longitude: null,
store_name: '',
mapAddressLabel: '',
license_imageToString: '',
user_status: ''
});
const optionsPermitType = [
{
value2: '1',
label: '许可证',
},
{
value2: '2',
label: '特许证件',
},
{
value2: '3',
label: '其他证件',
}
]
const rules = reactive({
contact_name: [{ required: true, message: '请输入联系人姓名', trigger: 'blur' }],
biz_category: [{ required: true, message: '请选择经营品类', trigger: 'change' }],
store_name: [{ required: true, message: '请输入门店名称', trigger: 'blur' }],
map_address: [{ required: true, message: '请选择地图地址', trigger: 'change' }],
position: [{ required: true, message: '请选择地图地址', trigger: 'change' }],
store_address: [{ required: true, message: '请输入详细地址', trigger: 'blur' }],
front_facade_image: [{ required: true, message: '请上传门脸图', trigger: 'change' }],
environment_image: [{ required: true, message: '请上传环境图', trigger: 'change' }],
entity_type: [{ required: true, message: '请选择身份', trigger: 'change' }],
license_type: [{ required: true, message: '请选择许可证类型', trigger: 'change' }],
license_number: [{ required: true, message: '请输入许可证编号', trigger: 'blur' }],
biz_license_number: [{ required: true, message: '请输入营业执照编号', trigger: 'blur' }],
biz_license_company: [{ required: true, message: '请输入营业执照公司名', trigger: 'blur' }],
legal_person_name: [{ required: true, message: '请输入负责人姓名', trigger: 'blur' }],
legal_person_mobile: [{ required: true, message: '请输入负责人手机号', trigger: 'blur' }],
legal_person_id_number: [{ required: true, message: '请输入负责人身份证号', trigger: 'blur' }],
biz_license_image: [{ required: true, message: '请上传营业执照', trigger: 'change' }],
// license_image: [{ required: true, message: '请上传许可证', trigger: 'change' }],
legal_person_id_images: [{ required: true, message: '请上传负责人身份证正面', trigger: 'change' }],
legal_person_id_images2: [{ required: true, message: '请上传负责人身份证反面', trigger: 'change' }],
individual_id_number: [{ required: true, message: '请输入个人身份证号', trigger: 'blur' }],
individual_id_images: [{ required: true, message: '请上传个人身份证正面', trigger: 'change' }],
individual_id_images2: [{ required: true, message: '请上传个人身份证反面', trigger: 'change' }],
bank_name: [{ required: true, message: '请选择银行', trigger: 'change' }],
// bank_branch_name: [{ required: true, message: '请输入支行名称', trigger: 'blur' }],
account_number: [{ required: true, message: '请输入收款账户号码', trigger: 'blur' }],
account_holder_name: [{ required: true, message: '请输入账户姓名', trigger: 'blur' }]
});
const checkForm = async () => {
const isValid = await (formRef.value as any).validate((valid) => {
return valid;
});
if (isValid) {
console.log("可以通过");
} else {
ElMessage.error('请完善当前页面的表单信息');
}
};
const next = () => {
if (active.value < 3) {
active.value++;
window.scrollTo({
top: 0, //回到顶部
left: 0,
behavior: "smooth",
})
}
}
const pre = () => {
if (active.value > 1) {
active.value--;
window.scrollTo({
top: 0, //回到顶部
left: 0,
behavior: "smooth",
})
}
};
const getLabel = (field: string, limit: number) => {
const labels = {
front_facade_image: '门脸图',
environment_image: '环境图',
biz_license_image: '营业执照',
license_image: '许可证',
legal_person_id_images: '负责人身份证正面',
legal_person_id_images2: '负责人身份证反面',
individual_id_images: '个人身份证正面',
individual_id_images2: '个人身份证反面'
};
if (field === 'license_image') {
return `${labels[field]}(${applyFormData[field].length}/${limit})`;
} else {
const count = applyFormData[field] ? 1 : 0;
return `${labels[field]}(${count}/${limit})`;
}
};
const userStore = useUserStore();
const showAll = () => {
applyFormData.license_imageToString = applyFormData.license_image.map(url => `${url}`).join(',');
};
const merchToApply = async () => {
showAll();
checkForm();
const res = await merchApply(applyFormData);
if (res && res.data.status === 200) {
// ElMessage.success('成功入驻');
location.reload()
console.log('成功入驻', res);
} else {
console.log(res.data);
ElMessage.error(res.data.msg);
}
};
const selectedValue = ref([]);
const value = ref([]);
const processData = () => {
const { provinceData, cityData: cityList, areaData } = cityData;
return provinceData.map((province, provinceIndex) => {
const provinceItem = {
...province,
children: cityList[provinceIndex].map((city, cityIndex) => {
const cityItem = {
...city
};
if (areaData[provinceIndex] && areaData[provinceIndex][cityIndex]) {
cityItem.children = areaData[provinceIndex][cityIndex];
}
return cityItem;
})
};
return provinceItem;
});
};
const cascaderOptions = ref([]);
const cascaderOptions2 = ref(processData());
const cityData2 = ref<CityDataStructure>();
const cascaderOptions3 = ref();
//hover触发选择
const cascaderProps = ref({
value: 'value',
label: 'label',
children: 'children',
expandTrigger: 'hover' as const
});
const handleChangeBizCategory = (value) => {
if (value && value.length === 2) {
const [bizCategoryId, bizSecondCategoryId] = value;
applyFormData.biz_category = bizCategoryId;
applyFormData.biz_second_category = bizSecondCategoryId;
}
};
interface Bank {
id: number;
bank_name: string;
}
const bankList2 = ref<Bank[]>([]);
onMounted(() => {
GetStoreCategories().then(res => {
if (res.data.code === 0 && res.data.status === 200) {
cascaderOptions.value = transformStoreCategories(res.data.data);
} else {
}
}).catch(err => {
ElMessage.error('获取店铺分类失败');
});
GetBank().then(res => {
if (res.data.code === 0 && res.data.status === 200) {
bankList2.value = res.data.data;
} else {
ElMessage.error('获取银行失败');
}
}).catch(err => {
ElMessage.error('获取银行失败');
});
GetAppDistrict().then(res => {
if (res.data.code === 0 && res.data.status === 200) {
cityData2.value = res.data.data;
console.log(cascaderOptions3.value);
} else {
ElMessage.error('获取银行失败');
}
}).catch(err => {
ElMessage.error('获取银行失败');
});
});
const handleChange = (value) => {
// 假设 cascader 的值是一个数组,格式为 [省份ID, 城市ID, 区县ID]
if (value && value.length === 3) {
const [provinceId, cityId, countyId] = value;
applyFormData.province_id = provinceId;
applyFormData.city_id = cityId;
applyFormData.county_id = countyId;
// // 获取区县名称(可选)
// const targetOption2 = cascaderOptions2.value
// .flatMap(province => province.children)
// .flatMap(city => city.children)
// .find(county => county.value === countyId);
// const label2 = targetOption?.label || '';
// applyFormData.mapAddressLabel2 = label2;
//找市
const targetOption = cascaderOptions2.value
.flatMap(province => province.children)
.find(city => city.value === cityId)
const label = targetOption?.label || '';
applyFormData.mapAddressLabel = label;
}
};
const autocompleteOptions = ref([]);
const querySearch = async (queryString, cb) => {
if (!queryString) {
cb([]);
return;
}
try {
const params = {
query: queryString,
region: applyFormData.mapAddressLabel,
city_limit: true,
ret_coordtype: 'gcj02ll'
};
const response = await GetPostion(params);
console.log("这是response", response);
if (response.status === 200 && response.data.message === 'ok') {
const results = response.data.result
.filter(item => "location" in item)
.map(item => ({
value: item.name, // 确保有 value 属性
label: item.name, // 确保有 label 属性
name: item.name,
address: item.address || '', // 确保 address 属性存在
lat: item.location?.lat || '', // 确保 lat 属性存在
lng: item.location?.lng || '' // 确保 lng 属性存在
}));
cb(results);
} else {
ElMessage.error('搜索失败');
cb([]);
}
} catch (error) {
ElMessage.error('搜索失败');
cb([]);
}
};
const handleSelect = (item) => {
applyFormData.position = item.value;
console.log(item.value);
applyFormData.store_latitude = item.lat;
applyFormData.store_longitude = item.lng;
};
const beforeUpload = (file) => {
const isJPG = file.type === 'image/jpeg';
const isPNG = file.type === 'image/png';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG && !isPNG) {
ElMessage.error('上传的图片必须是JPG或PNG格式');
return false;
}
if (!isLt2M) {
ElMessage.error('上传的图片大小不能超过2MB');
return false;
}
return true;
};
const uploadUrl = ref('https://mall.gpxscs.cn/mobile/shop/oss/upload');
const handleRemove = (file, fileList, field) => {
if (field === 'license_image') {
const removedUrl = file.url;
applyFormData[field] = applyFormData[field].filter(url => url !== removedUrl);
} else {
applyFormData[field] = '';
}
};
const isUploadHidden = (field: string) => {
const limits = {
license_image: 5
};
const limit = limits[field] || 1;
if (field === 'license_image') {
return applyFormData[field].length >= limit;
} else {
return applyFormData[field] !== '' && applyFormData[field] != null;
}
};
const handleExceed = (files, fileList) => {
ElMessage.warning('最多只能上传5张图片');
};
const handleUploadSuccess = (response, file, fileList, field) => {
if (response && response.status === 200 && response.code === 0) {
if (response.data && response.data.url) {
file.url = response.data.url;
if (field === 'license_image') {
applyFormData[field].push(file.url);
} else {
applyFormData[field] = file.url;
}
} else {
ElMessage.error('文件上传成功,但未返回文件 URL');
}
} else {
ElMessage.error(response.msg || '文件上传失败');
}
};
const handleUploadError = (error, file) => {
ElMessage.error('文件上传失败');
};
const clearOtherFields = () => {
if (applyFormData.entity_type === 1) {
// 清空个人部分的字段
applyFormData.individual_id_number = '';
applyFormData.individual_id_images = '';
applyFormData.individual_id_images2 = '';
} else if (applyFormData.entity_type === 2) {
// 清空企业部分的字段
applyFormData.license_type = null;
applyFormData.license_number = '';
applyFormData.biz_license_number = '';
applyFormData.biz_license_company = '';
applyFormData.legal_person_name = '';
applyFormData.legal_person_mobile = '';
applyFormData.legal_person_id_number = '';
applyFormData.biz_license_image = '';
applyFormData.license_image = [];
applyFormData.legal_person_id_images = '';
applyFormData.legal_person_id_images2 = '';
}
};
</script>
<style lang="scss">
.signUp-container {
display: flex;
padding: 30px 0px;
flex-direction: column;
align-items: center;
justify-content: center;
.steps-container {
width: 60%;
}
:deep(.upload-hidden .el-upload--picture-card) {
display: none;
}
.form-submit {
padding: 20px 0;
}
}
.auto-item {
p {
font-size: 15px;
font-weight: 900;
}
span {
font-size: 10px;
}
}
.el-form-item {
label {
width: 126px !important;
}
}
@media (max-width: 768px) {
.el-cascader-menu {
width: 120px;
min-width: 120px;
}
}
</style>