|
|
@@ -0,0 +1,1259 @@
|
|
|
+<template>
|
|
|
+ <div class="form-container">
|
|
|
+ <div>
|
|
|
+ <!-- 返回按钮 -->
|
|
|
+ <el-button class="back-btn" @click="handleBack"> 返回 </el-button>
|
|
|
+ <!-- 进度条 -->
|
|
|
+ <div class="progress-container">
|
|
|
+ <el-steps :active="currentStep" style="max-width: 1500px" align-center>
|
|
|
+ <el-step v-for="(item, index) in entryList" :key="index">
|
|
|
+ <template #title>
|
|
|
+ <div class="step-title-wrapper">
|
|
|
+ <span class="step-title">{{ item.title }}</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-step>
|
|
|
+ </el-steps>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 第一步:个人实名 - 身份证正反面上传 -->
|
|
|
+ <div v-if="currentStep === 1" class="step1-content">
|
|
|
+ <div class="form-content">
|
|
|
+ <h3 class="section-title">身份证正反面</h3>
|
|
|
+ <div class="id-card-upload-container">
|
|
|
+ <!-- 正面 -->
|
|
|
+ <div class="upload-item">
|
|
|
+ <div class="upload-label">正面</div>
|
|
|
+ <el-upload
|
|
|
+ v-model:file-list="idCardFrontList"
|
|
|
+ :http-request="handleHttpUpload"
|
|
|
+ list-type="picture-card"
|
|
|
+ :limit="1"
|
|
|
+ :on-exceed="handleExceed"
|
|
|
+ :on-success="handleUploadSuccess"
|
|
|
+ :on-preview="handlePictureCardPreview"
|
|
|
+ :on-remove="handleRemove"
|
|
|
+ accept="image/*"
|
|
|
+ class="id-card-upload"
|
|
|
+ :class="{ 'upload-complete': idCardFrontList.length > 0 }"
|
|
|
+ >
|
|
|
+ <template v-if="idCardFrontList.length === 0">
|
|
|
+ <div class="upload-placeholder">
|
|
|
+ <span class="placeholder-text">示例图</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-upload>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 反面 -->
|
|
|
+ <div class="upload-item">
|
|
|
+ <div class="upload-label">反面</div>
|
|
|
+ <el-upload
|
|
|
+ v-model:file-list="idCardBackList"
|
|
|
+ :http-request="handleHttpUpload"
|
|
|
+ list-type="picture-card"
|
|
|
+ :limit="1"
|
|
|
+ :on-exceed="handleExceed"
|
|
|
+ :on-success="handleUploadSuccess"
|
|
|
+ :on-preview="handlePictureCardPreview"
|
|
|
+ :on-remove="handleRemove"
|
|
|
+ accept="image/*"
|
|
|
+ class="id-card-upload"
|
|
|
+ :class="{ 'upload-complete': idCardBackList.length > 0 }"
|
|
|
+ >
|
|
|
+ <template v-if="idCardBackList.length === 0">
|
|
|
+ <div class="upload-placeholder">
|
|
|
+ <span class="placeholder-text">示例图</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-upload>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- OCR 识别结果展示 -->
|
|
|
+ <div class="ocr-result-container" v-if="isIdCardUploadComplete">
|
|
|
+ <div class="ocr-result-item" v-if="isOcrProcessing">
|
|
|
+ <span class="label">识别中:</span>
|
|
|
+ <span class="value">正在识别身份证信息,请稍候...</span>
|
|
|
+ </div>
|
|
|
+ <template v-else>
|
|
|
+ <div class="ocr-result-item" v-if="ocrResult.name">
|
|
|
+ <span class="label">姓名:</span>
|
|
|
+ <span class="value">{{ ocrResult.name }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="ocr-result-item" v-if="ocrResult.idCard">
|
|
|
+ <span class="label">身份证号:</span>
|
|
|
+ <span class="value">{{ ocrResult.idCard }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="ocr-result-tip" v-if="!ocrResult.name && !ocrResult.idCard">请等待身份证识别完成</div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 按钮 -->
|
|
|
+ <div class="form-actions">
|
|
|
+ <el-button type="primary" size="large" @click="handleNextStep"> 下一步 </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 第二步:填写信息 -->
|
|
|
+ <div v-if="currentStep === 2">
|
|
|
+ <!-- 表单内容 -->
|
|
|
+ <div class="form-content step2-form">
|
|
|
+ <el-form :model="step2Form" :rules="step2Rules" ref="step2FormRef" label-width="125px">
|
|
|
+ <div class="form-row">
|
|
|
+ <!-- 左列 -->
|
|
|
+ <div class="form-col">
|
|
|
+ <el-form-item label="店铺名称" prop="storeName">
|
|
|
+ <el-input v-model="step2Form.storeName" placeholder="请输入店铺名称" maxlength="30" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="容纳人数" prop="storeCapacity">
|
|
|
+ <el-input-number v-model="step2Form.storeCapacity" :min="1" :max="9999" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="门店面积" prop="storeArea">
|
|
|
+ <el-radio-group v-model="step2Form.storeArea">
|
|
|
+ <el-radio label="小于20平米" value="1"> 小于20平米 </el-radio>
|
|
|
+ <el-radio label="20-50平米" value="2"> 20-50平米 </el-radio>
|
|
|
+ <el-radio label="50-100平米" value="3"> 50-100平米 </el-radio>
|
|
|
+ <el-radio label="100-300平米" value="4"> 100-300平米 </el-radio>
|
|
|
+ <el-radio label="500-1000平米" value="5"> 500-1000平米 </el-radio>
|
|
|
+ <el-radio label="大于1000平米" value="6"> 大于1000平米 </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="所在地区" prop="region">
|
|
|
+ <el-cascader :props="areaProps" v-model="step2Form.region" style="width: 100%" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="详细地址" prop="storeDetailAddress">
|
|
|
+ <el-input v-model="step2Form.storeDetailAddress" type="textarea" :rows="3" placeholder="请输入" maxlength="255" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="门店简介" prop="storeBlurb">
|
|
|
+ <el-input v-model="step2Form.storeBlurb" type="textarea" :rows="3" placeholder="请输入" maxlength="300" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="经营板块" prop="businessSection">
|
|
|
+ <el-radio-group v-model="step2Form.businessSection" @change="changeBusinessSector">
|
|
|
+ <el-radio v-for="businessSection in businessSectionList" :value="businessSection.id" :key="businessSection.id">
|
|
|
+ {{ businessSection.dictDetail }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="经营种类" prop="businessSecondLevel" v-if="secondLevelList.length > 0">
|
|
|
+ <el-radio-group v-model="step2Form.businessSecondLevel" @change="changeBusinessSecondLevel">
|
|
|
+ <el-radio v-for="item in secondLevelList" :value="item.dictId" :key="item.dictId">
|
|
|
+ {{ item.dictDetail }}
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 如果没有三级分类,则显示二级分类作为经营种类 -->
|
|
|
+ <el-form-item label="分类" prop="businessTypes" v-if="secondLevelList.length > 0 && thirdLevelList.length === 0">
|
|
|
+ <el-checkbox-group v-model="step2Form.businessTypes">
|
|
|
+ <el-checkbox v-for="item in secondLevelList" :key="item.dictId" :label="item.dictDetail" :value="item.dictId" />
|
|
|
+ </el-checkbox-group>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 右列 -->
|
|
|
+ <div class="form-col">
|
|
|
+ <el-form-item label="门店营业状态" prop="businessType">
|
|
|
+ <el-radio-group v-model="step2Form.businessType">
|
|
|
+ <el-radio label="正常营业"> 正常营业 </el-radio>
|
|
|
+ <el-radio label="暂停营业"> 暂停营业 </el-radio>
|
|
|
+ <el-radio label="筹建中"> 筹建中 </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="经度" prop="storePositionLongitude" v-show="latShow">
|
|
|
+ <el-input disabled v-model="step2Form.storePositionLongitude" placeholder="请填写经度" clearable />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="纬度" prop="storePositionLatitude" v-show="latShow">
|
|
|
+ <el-input disabled v-model="step2Form.storePositionLatitude" placeholder="请填写纬度" clearable />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="经纬度查询" prop="address">
|
|
|
+ <el-select
|
|
|
+ v-model="step2Form.address"
|
|
|
+ filterable
|
|
|
+ placeholder="请输入地址进行查询"
|
|
|
+ remote
|
|
|
+ reserve-keyword
|
|
|
+ :remote-method="getLonAndLat"
|
|
|
+ @change="selectAddress"
|
|
|
+ >
|
|
|
+ <el-option v-for="item in addressList" :key="item.id" :label="item.name" :value="item.location">
|
|
|
+ <span style="float: left">{{ item.name }}</span>
|
|
|
+ <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">{{ item.district }}</span>
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="营业执照" prop="businessLicenseAddress">
|
|
|
+ <el-upload
|
|
|
+ v-model:file-list="step2Form.businessLicenseAddress"
|
|
|
+ :http-request="handleHttpUpload"
|
|
|
+ list-type="picture-card"
|
|
|
+ :limit="1"
|
|
|
+ :on-exceed="handleExceed"
|
|
|
+ :on-success="handleUploadSuccess"
|
|
|
+ :on-preview="handlePictureCardPreview"
|
|
|
+ >
|
|
|
+ <el-icon><Plus /></el-icon>
|
|
|
+ <template #tip>
|
|
|
+ <div class="el-upload__tip">({{ step2Form.businessLicenseAddress.length }}/1)</div>
|
|
|
+ </template>
|
|
|
+ </el-upload>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="合同图片" prop="contractImageList">
|
|
|
+ <el-upload
|
|
|
+ v-model:file-list="step2Form.contractImageList"
|
|
|
+ :http-request="handleHttpUpload"
|
|
|
+ list-type="picture-card"
|
|
|
+ :limit="20"
|
|
|
+ :on-exceed="handleExceed"
|
|
|
+ :on-success="handleUploadSuccess"
|
|
|
+ :on-preview="handlePictureCardPreview"
|
|
|
+ >
|
|
|
+ <el-icon><Plus /></el-icon>
|
|
|
+ <template #tip>
|
|
|
+ <div class="el-upload__tip">({{ step2Form.contractImageList.length }}/20)</div>
|
|
|
+ </template>
|
|
|
+ </el-upload>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="食品经营许可证" prop="foodLicenceImgList">
|
|
|
+ <el-upload
|
|
|
+ v-model:file-list="step2Form.foodLicenceImgList"
|
|
|
+ :http-request="handleHttpUpload"
|
|
|
+ list-type="picture-card"
|
|
|
+ :limit="1"
|
|
|
+ :on-exceed="handleExceed"
|
|
|
+ :on-success="handleUploadSuccess"
|
|
|
+ :on-preview="handlePictureCardPreview"
|
|
|
+ >
|
|
|
+ <el-icon><Plus /></el-icon>
|
|
|
+ <template #tip>
|
|
|
+ <div class="el-upload__tip">({{ step2Form.foodLicenceImgList.length }}/1)</div>
|
|
|
+ </template>
|
|
|
+ </el-upload>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="娱乐经营许可证" prop="disportLicenceImgList">
|
|
|
+ <el-upload
|
|
|
+ v-model:file-list="step2Form.disportLicenceImgList"
|
|
|
+ :http-request="handleHttpUpload"
|
|
|
+ list-type="picture-card"
|
|
|
+ :limit="1"
|
|
|
+ :on-exceed="handleExceed"
|
|
|
+ :on-success="handleUploadSuccess"
|
|
|
+ :on-preview="handlePictureCardPreview"
|
|
|
+ >
|
|
|
+ <el-icon><Plus /></el-icon>
|
|
|
+ <template #tip>
|
|
|
+ <div class="el-upload__tip">({{ step2Form.disportLicenceImgList.length }}/1)</div>
|
|
|
+ </template>
|
|
|
+ </el-upload>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 按钮 -->
|
|
|
+ <div class="form-actions">
|
|
|
+ <el-button type="primary" size="large" @click="handleSubmit"> 提交 </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 图片预览 -->
|
|
|
+ <el-image-viewer
|
|
|
+ v-if="imageViewerVisible"
|
|
|
+ :url-list="imageViewerUrlList"
|
|
|
+ :initial-index="imageViewerInitialIndex"
|
|
|
+ @close="imageViewerVisible = false"
|
|
|
+ />
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, reactive, watch, onMounted, computed } from "vue";
|
|
|
+import {
|
|
|
+ ElMessage,
|
|
|
+ ElMessageBox,
|
|
|
+ type FormInstance,
|
|
|
+ type FormRules,
|
|
|
+ UploadProps,
|
|
|
+ UploadUserFile,
|
|
|
+ UploadRequestOptions
|
|
|
+} from "element-plus";
|
|
|
+import { Plus } from "@element-plus/icons-vue";
|
|
|
+
|
|
|
+import {
|
|
|
+ applyStore,
|
|
|
+ getMerchantByPhone,
|
|
|
+ getFirstLevelList,
|
|
|
+ getSecondLevelList,
|
|
|
+ getThirdLevelList
|
|
|
+} from "@/api/modules/homeEntry";
|
|
|
+import { getInputPrompt, getDistrict, uploadImg, ocrRequestUrl } from "@/api/modules/newLoginApi";
|
|
|
+import { localGet, localSet } from "@/utils/index";
|
|
|
+import { useAuthStore } from "@/stores/modules/auth";
|
|
|
+
|
|
|
+const authStore = useAuthStore();
|
|
|
+const userInfo = localGet("geeker-user")?.userInfo || {};
|
|
|
+const latShow = ref(false);
|
|
|
+
|
|
|
+// 图片预览相关
|
|
|
+const imageViewerVisible = ref(false);
|
|
|
+const imageViewerUrlList = ref<string[]>([]);
|
|
|
+const imageViewerInitialIndex = ref(0);
|
|
|
+
|
|
|
+const entryList = ref([
|
|
|
+ {
|
|
|
+ title: "个人实名"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: "填写信息"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: "等待审核"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: "入驻成功"
|
|
|
+ }
|
|
|
+]);
|
|
|
+
|
|
|
+// 身份证正反面上传列表
|
|
|
+const idCardFrontList = ref<UploadUserFile[]>([]);
|
|
|
+const idCardBackList = ref<UploadUserFile[]>([]);
|
|
|
+
|
|
|
+// OCR 识别结果
|
|
|
+const ocrResult = ref<{
|
|
|
+ name?: string;
|
|
|
+ idCard?: string;
|
|
|
+}>({});
|
|
|
+
|
|
|
+// 是否正在识别中
|
|
|
+const isOcrProcessing = ref(false);
|
|
|
+
|
|
|
+// 计算是否已上传完成(正反面都上传完成)
|
|
|
+const isIdCardUploadComplete = computed(() => {
|
|
|
+ return idCardFrontList.value.length > 0 && idCardBackList.value.length > 0;
|
|
|
+});
|
|
|
+// 下一步 - 验证身份证正反面是否已上传
|
|
|
+const handleNextStep = async () => {
|
|
|
+ // 识别成功,进入下一步
|
|
|
+ setStep(2);
|
|
|
+};
|
|
|
+
|
|
|
+const step2Rules: FormRules = {
|
|
|
+ storeName: [{ required: true, message: "请输入店铺名称", trigger: "blur" }],
|
|
|
+ storeCapacity: [{ required: true, message: "请输入容纳人数", trigger: "blur" }],
|
|
|
+ storeArea: [{ required: true, message: "请选择门店面积", trigger: "change" }],
|
|
|
+ storeBlurb: [{ required: true, message: "请输入门店简介", trigger: "change" }],
|
|
|
+ storeIntro: [{ required: true, message: "请输入门店简介", trigger: "blur" }],
|
|
|
+ businessSection: [{ required: true, message: "请选择经营板块", trigger: "change" }],
|
|
|
+ businessTypes: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: "请选择经营种类",
|
|
|
+ trigger: "change",
|
|
|
+ validator: (rule: any, value: any, callback: any) => {
|
|
|
+ if (!value || value.length === 0) {
|
|
|
+ callback(new Error("请选择经营种类"));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ address: [{ required: true, message: "请输入经纬度", trigger: "blur" }],
|
|
|
+ businessLicenseAddress: [{ required: true, message: "请上传营业执照", trigger: "change" }],
|
|
|
+ contractImageList: [{ required: true, message: "请上传合同图片", trigger: "change" }],
|
|
|
+ foodLicenceImgList: [{ required: true, message: "请上传食品经营许可证", trigger: "change" }],
|
|
|
+ disportLicenceImgList: [{ required: true, message: "请上传娱乐经营许可证", trigger: "change" }]
|
|
|
+};
|
|
|
+
|
|
|
+//地址集合
|
|
|
+const addressList = ref<any[]>([]);
|
|
|
+//查询地址名称
|
|
|
+const queryAddress = ref<string>("");
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ currentStep: {
|
|
|
+ type: Number,
|
|
|
+ default: 1
|
|
|
+ },
|
|
|
+ storeApplicationStatus: {
|
|
|
+ type: Number,
|
|
|
+ default: 0
|
|
|
+ }
|
|
|
+});
|
|
|
+const emit = defineEmits(["update:currentStep", "update:get-user-info"]);
|
|
|
+
|
|
|
+// 调用父组件的 getUserInfo 方法
|
|
|
+const callGetUserInfo = () => {
|
|
|
+ emit("update:get-user-info");
|
|
|
+};
|
|
|
+
|
|
|
+// 内部步骤状态,和父组件同步
|
|
|
+const currentStep = ref<number>(props.currentStep || 1);
|
|
|
+const storeApplicationStatus = ref<number>(props.storeApplicationStatus || 0);
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => props.currentStep,
|
|
|
+ val => {
|
|
|
+ if (typeof val === "number") currentStep.value = val;
|
|
|
+ }
|
|
|
+);
|
|
|
+watch(
|
|
|
+ () => props.storeApplicationStatus,
|
|
|
+ val => {
|
|
|
+ if (typeof val === "number") storeApplicationStatus.value = val;
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+// 隐藏财务管理菜单的函数
|
|
|
+const hideFinancialManagementMenu = () => {
|
|
|
+ const hideMenus = (menuList: any[]) => {
|
|
|
+ menuList.forEach(menu => {
|
|
|
+ if (menu.name && menu.name === "financialManagement") {
|
|
|
+ menu.meta.isHide = true;
|
|
|
+ }
|
|
|
+ if (menu.children && menu.children.length > 0) {
|
|
|
+ hideMenus(menu.children);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+ if (authStore.authMenuList && authStore.authMenuList.length > 0) {
|
|
|
+ hideMenus(authStore.authMenuList);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 显示财务管理菜单的函数
|
|
|
+const showFinancialManagementMenu = () => {
|
|
|
+ const showMenus = (menuList: any[]) => {
|
|
|
+ menuList.forEach(menu => {
|
|
|
+ if (menu.name && menu.name === "financialManagement") {
|
|
|
+ menu.meta.isHide = false;
|
|
|
+ }
|
|
|
+ if (menu.children && menu.children.length > 0) {
|
|
|
+ showMenus(menu.children);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+ if (authStore.authMenuList && authStore.authMenuList.length > 0) {
|
|
|
+ showMenus(authStore.authMenuList);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 更新缓存中的 storeId
|
|
|
+const updateStoreIdInCache = async () => {
|
|
|
+ try {
|
|
|
+ const geekerUser = localGet("geeker-user");
|
|
|
+ if (!geekerUser || !geekerUser.userInfo || !geekerUser.userInfo.phone) {
|
|
|
+ console.error("用户信息不存在");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const phone = geekerUser.userInfo.phone;
|
|
|
+ const res: any = await getMerchantByPhone({ phone });
|
|
|
+ if (res && res.code == 200 && res.data && res.data.storeId) {
|
|
|
+ geekerUser.userInfo.storeId = res.data.storeId;
|
|
|
+ localSet("geeker-user", geekerUser);
|
|
|
+ if (res.data.storeId) {
|
|
|
+ localSet("createdId", res.data.storeId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("更新 storeId 缓存失败:", error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 监听步骤和审核状态
|
|
|
+watch([() => currentStep.value, () => storeApplicationStatus.value], ([step, status]) => {
|
|
|
+ if (step === 3 && (status === 0 || status === 2)) {
|
|
|
+ updateStoreIdInCache();
|
|
|
+ }
|
|
|
+ if (status === 2) {
|
|
|
+ hideFinancialManagementMenu();
|
|
|
+ }
|
|
|
+ if (status === 1) {
|
|
|
+ showFinancialManagementMenu();
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+// 监听菜单列表变化
|
|
|
+watch(
|
|
|
+ () => authStore.authMenuList.length,
|
|
|
+ newLength => {
|
|
|
+ if (newLength > 0) {
|
|
|
+ if (storeApplicationStatus.value === 2) {
|
|
|
+ hideFinancialManagementMenu();
|
|
|
+ }
|
|
|
+ if (storeApplicationStatus.value === 1) {
|
|
|
+ showFinancialManagementMenu();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getBusinessSectionList();
|
|
|
+ callGetUserInfo();
|
|
|
+ if (currentStep.value === 3 && (storeApplicationStatus.value === 0 || storeApplicationStatus.value === 2)) {
|
|
|
+ updateStoreIdInCache();
|
|
|
+ }
|
|
|
+ if (storeApplicationStatus.value === 2) {
|
|
|
+ hideFinancialManagementMenu();
|
|
|
+ } else if (storeApplicationStatus.value === 1) {
|
|
|
+ showFinancialManagementMenu();
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const setStep = (val: number) => {
|
|
|
+ currentStep.value = val;
|
|
|
+ emit("update:currentStep", val);
|
|
|
+};
|
|
|
+
|
|
|
+// 第二步表单
|
|
|
+const step2FormRef = ref<FormInstance>();
|
|
|
+const step2Form = reactive({
|
|
|
+ storeName: "",
|
|
|
+ storeCapacity: 1,
|
|
|
+ storeArea: "1",
|
|
|
+ isChain: 0,
|
|
|
+ storeDetailAddress: "",
|
|
|
+ region: [],
|
|
|
+ administrativeRegionProvinceAdcode: "",
|
|
|
+ administrativeRegionCityAdcode: "",
|
|
|
+ administrativeRegionDistrictAdcode: "",
|
|
|
+ storeAddress: "",
|
|
|
+ storeBlurb: "",
|
|
|
+ businessSection: "",
|
|
|
+ businessSectionName: "",
|
|
|
+ businessSecondLevel: "",
|
|
|
+ businessTypes: [],
|
|
|
+ businessTypesList: [],
|
|
|
+ businessStatus: 0,
|
|
|
+ storeStatus: 1,
|
|
|
+ businessType: "正常营业",
|
|
|
+ storePositionLongitude: "",
|
|
|
+ storePositionLatitude: "",
|
|
|
+ businessLicenseAddress: [] as UploadUserFile[],
|
|
|
+ contractImageList: [] as UploadUserFile[],
|
|
|
+ foodLicenceImgList: [] as UploadUserFile[],
|
|
|
+ disportLicenceImgList: [] as UploadUserFile[],
|
|
|
+ address: ""
|
|
|
+});
|
|
|
+
|
|
|
+// 返回按钮
|
|
|
+const handleBack = () => {
|
|
|
+ if (currentStep.value === 1) {
|
|
|
+ setStep(0);
|
|
|
+ } else if (currentStep.value === 2) {
|
|
|
+ setStep(1);
|
|
|
+ } else if (currentStep.value === 3) {
|
|
|
+ setStep(2);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 地区选择
|
|
|
+const areaProps: any = {
|
|
|
+ lazy: true,
|
|
|
+ async lazyLoad(node, resolve) {
|
|
|
+ const { level } = node;
|
|
|
+ try {
|
|
|
+ let param = { adCode: node.data.adCode ? node.data.adCode : "" };
|
|
|
+ const response: any = await getDistrict(param as any);
|
|
|
+ const nodes = (response?.data?.districts?.[0]?.districts || []).map((item: any) => ({
|
|
|
+ value: item.adcode,
|
|
|
+ adCode: item.adcode,
|
|
|
+ label: item.name,
|
|
|
+ leaf: level >= 2
|
|
|
+ }));
|
|
|
+ resolve(nodes);
|
|
|
+ } catch (error) {
|
|
|
+ resolve([]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => step2Form.region,
|
|
|
+ (newVal: any[]) => {
|
|
|
+ if (newVal.length > 0) {
|
|
|
+ step2Form.administrativeRegionProvinceAdcode = newVal[0];
|
|
|
+ step2Form.administrativeRegionCityAdcode = newVal[1];
|
|
|
+ step2Form.administrativeRegionDistrictAdcode = newVal[2];
|
|
|
+ }
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+//经营板块 - 一级分类
|
|
|
+const businessSectionList = ref<any[]>([]);
|
|
|
+const getBusinessSectionList = async () => {
|
|
|
+ try {
|
|
|
+ const res: any = await getFirstLevelList({});
|
|
|
+ if (res && res.code === 200 && res.data) {
|
|
|
+ businessSectionList.value = res.data;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取一级分类失败:", error);
|
|
|
+ ElMessage.error("获取经营板块失败");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 二级分类列表
|
|
|
+const secondLevelList = ref<any[]>([]);
|
|
|
+// 三级分类列表
|
|
|
+const thirdLevelList = ref<any[]>([]);
|
|
|
+
|
|
|
+// 一级分类变化时,加载二级分类
|
|
|
+const changeBusinessSector = async (dictId: string | number | boolean | undefined) => {
|
|
|
+ const dictIdStr = String(dictId || "");
|
|
|
+ if (!dictIdStr) {
|
|
|
+ secondLevelList.value = [];
|
|
|
+ thirdLevelList.value = [];
|
|
|
+ step2Form.businessSecondLevel = "";
|
|
|
+ step2Form.businessTypes = [];
|
|
|
+ step2Form.businessTypesList = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新一级分类信息
|
|
|
+ const selectedSection = businessSectionList.value.find((item: any) => item.dictId === dictIdStr);
|
|
|
+ if (selectedSection) {
|
|
|
+ step2Form.businessSection = selectedSection.dictId;
|
|
|
+ step2Form.businessSectionName = selectedSection.dictDetail;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清空二级和三级分类
|
|
|
+ secondLevelList.value = [];
|
|
|
+ thirdLevelList.value = [];
|
|
|
+ step2Form.businessSecondLevel = "";
|
|
|
+ step2Form.businessTypes = [];
|
|
|
+ step2Form.businessTypesList = [];
|
|
|
+
|
|
|
+ // 加载二级分类
|
|
|
+ try {
|
|
|
+ const res: any = await getSecondLevelList({ parentDictId: dictIdStr });
|
|
|
+ if (res && res.code === 200 && res.data) {
|
|
|
+ secondLevelList.value = res.data;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取二级分类失败:", error);
|
|
|
+ ElMessage.error("获取经营种类失败");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 二级分类变化时,加载三级分类
|
|
|
+const changeBusinessSecondLevel = async (dictId: string | number | boolean | undefined) => {
|
|
|
+ const dictIdStr = String(dictId || "");
|
|
|
+ if (!dictIdStr) {
|
|
|
+ thirdLevelList.value = [];
|
|
|
+ step2Form.businessTypes = [];
|
|
|
+ step2Form.businessTypesList = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清空三级分类
|
|
|
+ thirdLevelList.value = [];
|
|
|
+ step2Form.businessTypes = [];
|
|
|
+ step2Form.businessTypesList = [];
|
|
|
+
|
|
|
+ // 加载三级分类
|
|
|
+ try {
|
|
|
+ const res: any = await getThirdLevelList({ parentDictId: dictIdStr });
|
|
|
+ if (res && res.code === 200 && res.data) {
|
|
|
+ thirdLevelList.value = res.data;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取三级分类失败:", error);
|
|
|
+ // 如果没有三级分类,不显示错误,因为可能该二级分类下没有三级分类
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 经纬度查询
|
|
|
+const getLonAndLat = async (keyword: string) => {
|
|
|
+ if (keyword) {
|
|
|
+ let param = {
|
|
|
+ addressName: keyword
|
|
|
+ };
|
|
|
+ let res: any = await getInputPrompt(param as any);
|
|
|
+ if (res.code == "200") {
|
|
|
+ addressList.value = res?.data?.tips || [];
|
|
|
+ } else {
|
|
|
+ ElMessage.error("查询失败!");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ addressList.value = [];
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const selectAddress = async (param: any) => {
|
|
|
+ if (!step2Form.address || typeof step2Form.address !== "string") {
|
|
|
+ ElMessage.warning("地址格式不正确,请重新选择");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!step2Form.address.includes(",")) {
|
|
|
+ ElMessage.warning("地址格式不正确,缺少经纬度信息");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let locationList = step2Form.address.split(",");
|
|
|
+
|
|
|
+ if (locationList.length < 2) {
|
|
|
+ ElMessage.warning("地址格式不正确,无法获取经纬度");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ addressList.value.forEach((item: any) => {
|
|
|
+ if (item.location == step2Form.address) {
|
|
|
+ queryAddress.value = item.name;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ step2Form.storePositionLongitude = locationList[0]?.trim() || "";
|
|
|
+ step2Form.storePositionLatitude = locationList[1]?.trim() || "";
|
|
|
+
|
|
|
+ if (!step2Form.storePositionLongitude || !step2Form.storePositionLatitude) {
|
|
|
+ ElMessage.warning("无法获取有效的经纬度信息");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ latShow.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+//文件上传
|
|
|
+const handleHttpUpload = async (options: UploadRequestOptions) => {
|
|
|
+ let formData = new FormData();
|
|
|
+ formData.append("file", options.file);
|
|
|
+ try {
|
|
|
+ const res: any = await uploadImg(formData);
|
|
|
+ const fileUrl = res?.data?.fileUrl || res?.data?.[0] || res?.fileUrl;
|
|
|
+ if (fileUrl) {
|
|
|
+ options.onSuccess({ fileUrl });
|
|
|
+ } else {
|
|
|
+ throw new Error("上传失败:未获取到文件URL");
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ options.onError(error as any);
|
|
|
+ ElMessage.error("文件上传失败,请重试");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 自动调用 OCR 识别
|
|
|
+const autoOcrRecognition = async () => {
|
|
|
+ // 检查正反面是否都已上传完成
|
|
|
+ if (idCardFrontList.value.length === 0 || idCardBackList.value.length === 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const frontFile = idCardFrontList.value[0];
|
|
|
+ const backFile = idCardBackList.value[0];
|
|
|
+
|
|
|
+ // 验证上传的文件是否成功
|
|
|
+ if (frontFile.status !== "success" || !frontFile.url || backFile.status !== "success" || !backFile.url) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取身份证正反面的 URL
|
|
|
+ const frontUrl = getFileUrls(idCardFrontList.value)[0] || "";
|
|
|
+ const backUrl = getFileUrls(idCardBackList.value)[0] || "";
|
|
|
+
|
|
|
+ if (!frontUrl || !backUrl) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果正在识别中,不重复调用
|
|
|
+ if (isOcrProcessing.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将正反面 URL 用逗号分隔
|
|
|
+ const imageUrls = `${frontUrl},${backUrl}`;
|
|
|
+
|
|
|
+ let params = {
|
|
|
+ imageUrls: imageUrls,
|
|
|
+ ocrType: "ID_CARD",
|
|
|
+ storeId: userInfo.storeId,
|
|
|
+ storeUserId: userInfo.id
|
|
|
+ };
|
|
|
+
|
|
|
+ try {
|
|
|
+ isOcrProcessing.value = true;
|
|
|
+ const res: any = await ocrRequestUrl(params);
|
|
|
+ if (res && (res.code === 200 || res.code === "200")) {
|
|
|
+ // 保存识别结果
|
|
|
+ if (res.data) {
|
|
|
+ console.log(res.data[0]);
|
|
|
+ ocrResult.value = {
|
|
|
+ name: res.data.name || res.data.realName || "",
|
|
|
+ idCard: res.data.idCard || res.data.idNumber || res.data.idNo || ""
|
|
|
+ };
|
|
|
+
|
|
|
+ // 更新本地存储中的用户信息
|
|
|
+ const geekerUser = localGet("geeker-user");
|
|
|
+ if (geekerUser && geekerUser.userInfo) {
|
|
|
+ if (ocrResult.value.name) {
|
|
|
+ geekerUser.userInfo.name = ocrResult.value.name;
|
|
|
+ }
|
|
|
+ if (ocrResult.value.idCard) {
|
|
|
+ geekerUser.userInfo.idCard = ocrResult.value.idCard;
|
|
|
+ }
|
|
|
+ localSet("geeker-user", geekerUser);
|
|
|
+ }
|
|
|
+
|
|
|
+ ElMessage.success("身份证识别成功");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.warn("OCR 识别失败:", res?.msg);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("身份证识别失败:", error);
|
|
|
+ } finally {
|
|
|
+ isOcrProcessing.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 文件上传成功回调
|
|
|
+const handleUploadSuccess = (response: any, uploadFile: UploadUserFile) => {
|
|
|
+ if (response?.fileUrl) {
|
|
|
+ uploadFile.url = response.fileUrl;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 延迟一下,确保文件状态已更新,然后检查是否需要自动 OCR
|
|
|
+ setTimeout(() => {
|
|
|
+ autoOcrRecognition();
|
|
|
+ }, 100);
|
|
|
+};
|
|
|
+
|
|
|
+// 图片预览处理函数
|
|
|
+const handlePictureCardPreview = (file: UploadUserFile) => {
|
|
|
+ if (file.status === "uploading" && file.url) {
|
|
|
+ imageViewerUrlList.value = [file.url];
|
|
|
+ imageViewerInitialIndex.value = 0;
|
|
|
+ imageViewerVisible.value = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let urlList: string[] = [];
|
|
|
+ let currentFileList: UploadUserFile[] = [];
|
|
|
+
|
|
|
+ // 判断是哪个上传组件的文件
|
|
|
+ if (idCardFrontList.value.some((f: UploadUserFile) => f.uid === file.uid)) {
|
|
|
+ currentFileList = idCardFrontList.value;
|
|
|
+ } else if (idCardBackList.value.some((f: UploadUserFile) => f.uid === file.uid)) {
|
|
|
+ currentFileList = idCardBackList.value;
|
|
|
+ } else if (step2Form.businessLicenseAddress.some((f: UploadUserFile) => f.uid === file.uid)) {
|
|
|
+ currentFileList = step2Form.businessLicenseAddress;
|
|
|
+ } else if (step2Form.contractImageList.some((f: UploadUserFile) => f.uid === file.uid)) {
|
|
|
+ currentFileList = step2Form.contractImageList;
|
|
|
+ } else if (step2Form.foodLicenceImgList.some((f: UploadUserFile) => f.uid === file.uid)) {
|
|
|
+ currentFileList = step2Form.foodLicenceImgList;
|
|
|
+ } else if (step2Form.disportLicenceImgList.some((f: UploadUserFile) => f.uid === file.uid)) {
|
|
|
+ currentFileList = step2Form.disportLicenceImgList;
|
|
|
+ }
|
|
|
+
|
|
|
+ urlList = currentFileList
|
|
|
+ .filter((item: UploadUserFile) => item.status === "success" && (item.url || (item.response as any)?.fileUrl))
|
|
|
+ .map((item: UploadUserFile) => item.url || (item.response as any)?.fileUrl);
|
|
|
+
|
|
|
+ const currentUrl = file.url || (file.response as any)?.fileUrl;
|
|
|
+ const currentIndex = urlList.findIndex((url: string) => url === currentUrl);
|
|
|
+
|
|
|
+ if (currentIndex < 0) {
|
|
|
+ ElMessage.warning("图片尚未上传完成,无法预览");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ imageViewerUrlList.value = urlList;
|
|
|
+ imageViewerInitialIndex.value = currentIndex;
|
|
|
+ imageViewerVisible.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+// 文件移除处理
|
|
|
+const handleRemove = (file: UploadUserFile) => {
|
|
|
+ // 文件移除时,清空 OCR 识别结果
|
|
|
+ ocrResult.value = {};
|
|
|
+ isOcrProcessing.value = false;
|
|
|
+};
|
|
|
+
|
|
|
+// 提取文件列表中的URL
|
|
|
+const getFileUrls = (fileList: UploadUserFile[]): string[] => {
|
|
|
+ return fileList
|
|
|
+ .map((file: UploadUserFile) => {
|
|
|
+ const response = file.response as any;
|
|
|
+ return file.url || response?.fileUrl || "";
|
|
|
+ })
|
|
|
+ .filter((url: string) => url);
|
|
|
+};
|
|
|
+
|
|
|
+// 根据adcode获取地区详细信息
|
|
|
+const getDistrictInfo = async (adcode: string) => {
|
|
|
+ try {
|
|
|
+ const response: any = await getDistrict({ adCode: adcode } as any);
|
|
|
+ const district = response?.data?.districts?.[0];
|
|
|
+ if (district) {
|
|
|
+ return {
|
|
|
+ citycode: district.citycode ? [district.citycode] : [],
|
|
|
+ adcode: district.adcode,
|
|
|
+ level: district.level,
|
|
|
+ center: district.center,
|
|
|
+ name: district.name,
|
|
|
+ districts: []
|
|
|
+ };
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取地区信息失败:", error);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+};
|
|
|
+
|
|
|
+// 构建whereAddress数组
|
|
|
+const buildWhereAddress = async (regionCodes: string[]) => {
|
|
|
+ const whereAddress: any[] = [];
|
|
|
+ if (regionCodes && regionCodes.length > 0) {
|
|
|
+ for (const code of regionCodes) {
|
|
|
+ const districtInfo = await getDistrictInfo(code);
|
|
|
+ if (districtInfo) {
|
|
|
+ whereAddress.push(districtInfo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return whereAddress;
|
|
|
+};
|
|
|
+
|
|
|
+// 提交
|
|
|
+const handleSubmit = async () => {
|
|
|
+ if (!step2FormRef.value) return;
|
|
|
+
|
|
|
+ await step2FormRef.value.validate(async valid => {
|
|
|
+ if (valid) {
|
|
|
+ const businessLicenseUrls = getFileUrls(step2Form.businessLicenseAddress);
|
|
|
+ const contractImageUrls = getFileUrls(step2Form.contractImageList);
|
|
|
+ const foodLicenceUrls = getFileUrls(step2Form.foodLicenceImgList);
|
|
|
+ const disportLicenceUrls = getFileUrls(step2Form.disportLicenceImgList);
|
|
|
+
|
|
|
+ const whereAddress = await buildWhereAddress(step2Form.region);
|
|
|
+
|
|
|
+ let storeStatus = 1;
|
|
|
+ if (step2Form.businessType === "正常营业") {
|
|
|
+ storeStatus = 1;
|
|
|
+ } else if (step2Form.businessType === "暂停营业") {
|
|
|
+ storeStatus = 0;
|
|
|
+ } else if (step2Form.businessType === "筹建中") {
|
|
|
+ storeStatus = 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ const storeAreaNum = typeof step2Form.storeArea === "string" ? parseInt(step2Form.storeArea) : step2Form.storeArea;
|
|
|
+
|
|
|
+ const addressObj = {
|
|
|
+ address: queryAddress.value || "",
|
|
|
+ longitude: parseFloat(step2Form.storePositionLongitude) || 0,
|
|
|
+ latitude: parseFloat(step2Form.storePositionLatitude) || 0
|
|
|
+ };
|
|
|
+
|
|
|
+ const storePosition =
|
|
|
+ step2Form.storePositionLongitude && step2Form.storePositionLatitude
|
|
|
+ ? `${step2Form.storePositionLongitude},${step2Form.storePositionLatitude}`
|
|
|
+ : "";
|
|
|
+
|
|
|
+ let fullStoreAddress = "";
|
|
|
+ if (whereAddress.length > 0) {
|
|
|
+ const provinceName = whereAddress[0]?.name || "";
|
|
|
+ const cityName = whereAddress[1]?.name || "";
|
|
|
+ const districtName = whereAddress[2]?.name || "";
|
|
|
+ fullStoreAddress = `${provinceName}${cityName}${districtName}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取身份证正反面URL
|
|
|
+ const idCardFrontUrl = getFileUrls(idCardFrontList.value)[0] || "";
|
|
|
+ const idCardBackUrl = getFileUrls(idCardBackList.value)[0] || "";
|
|
|
+
|
|
|
+ // 处理经营种类:优先使用三级分类,如果没有三级分类则使用二级分类
|
|
|
+ let finalBusinessTypes: string[] = [];
|
|
|
+ if (step2Form.businessTypes.length > 0) {
|
|
|
+ // 有三级分类选择
|
|
|
+ finalBusinessTypes = step2Form.businessTypes;
|
|
|
+ } else if (step2Form.businessSecondLevel) {
|
|
|
+ // 没有三级分类,使用二级分类
|
|
|
+ finalBusinessTypes = [step2Form.businessSecondLevel];
|
|
|
+ } else {
|
|
|
+ // 都没有,使用旧的逻辑
|
|
|
+ finalBusinessTypes = step2Form.businessTypesList;
|
|
|
+ }
|
|
|
+
|
|
|
+ const params = {
|
|
|
+ storeTel: userInfo.phone,
|
|
|
+ storeName: step2Form.storeName,
|
|
|
+ storeCapacity: step2Form.storeCapacity,
|
|
|
+ storeArea: storeAreaNum,
|
|
|
+ isChain: step2Form.isChain,
|
|
|
+ storeDetailAddress: step2Form.storeDetailAddress,
|
|
|
+ storeBlurb: step2Form.storeBlurb,
|
|
|
+ businessSection: step2Form.businessSection,
|
|
|
+ businessTypesList: finalBusinessTypes,
|
|
|
+ storeStatus: storeStatus,
|
|
|
+ businessStatus: step2Form.businessStatus,
|
|
|
+ address: addressObj,
|
|
|
+ businessLicenseAddress: businessLicenseUrls,
|
|
|
+ contractImageList: contractImageUrls,
|
|
|
+ foodLicenceImgList: foodLicenceUrls,
|
|
|
+ disportLicenceUrls: disportLicenceUrls,
|
|
|
+ storeAddress: fullStoreAddress,
|
|
|
+ whereAddress: whereAddress,
|
|
|
+ updatedTime: null,
|
|
|
+ queryAddress: queryAddress.value,
|
|
|
+ storePosition: storePosition,
|
|
|
+ storePositionLatitude: parseFloat(step2Form.storePositionLatitude) || 0,
|
|
|
+ storePositionLongitude: parseFloat(step2Form.storePositionLongitude) || 0,
|
|
|
+ businessSectionName: step2Form.businessSectionName,
|
|
|
+ businessTypes: finalBusinessTypes,
|
|
|
+ foodLicenceUrl: foodLicenceUrls.length > 0 ? foodLicenceUrls[0] : "",
|
|
|
+ userAccount: userInfo.id,
|
|
|
+ administrativeRegionProvinceAdcode: step2Form.administrativeRegionProvinceAdcode,
|
|
|
+ administrativeRegionCityAdcode: step2Form.administrativeRegionCityAdcode,
|
|
|
+ administrativeRegionDistrictAdcode: step2Form.administrativeRegionDistrictAdcode,
|
|
|
+ idCardFrontUrl: idCardFrontUrl,
|
|
|
+ idCardBackUrl: idCardBackUrl
|
|
|
+ };
|
|
|
+
|
|
|
+ ElMessageBox.confirm("确认提交入驻申请吗?", "提示", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning"
|
|
|
+ })
|
|
|
+ .then(async () => {
|
|
|
+ try {
|
|
|
+ const res: any = await applyStore(params);
|
|
|
+ if (res && res.code == 200) {
|
|
|
+ storeApplicationStatus.value = 0;
|
|
|
+ ElMessage.success(res.msg);
|
|
|
+ callGetUserInfo();
|
|
|
+ setStep(0);
|
|
|
+ } else {
|
|
|
+ ElMessage.error(res.msg || "提交失败");
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("提交失败,请重试");
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ // 取消提交
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ ElMessage.error("请完善表单信息");
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 文件上传超出限制
|
|
|
+const handleExceed = () => {
|
|
|
+ ElMessage.warning("文件数量超出限制");
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+// 表单页面样式
|
|
|
+.form-container {
|
|
|
+ min-height: calc(100vh - 100px);
|
|
|
+ padding: 30px;
|
|
|
+ background: #ffffff;
|
|
|
+ border-radius: 8px;
|
|
|
+ .back-btn {
|
|
|
+ margin-bottom: 30px;
|
|
|
+ color: #606266;
|
|
|
+ border-color: #dcdfe6;
|
|
|
+ }
|
|
|
+ .progress-container {
|
|
|
+ margin-bottom: 40px;
|
|
|
+ :deep(.el-step__head.is-process .el-step__icon) {
|
|
|
+ color: #909399;
|
|
|
+ border-color: #909399 !important;
|
|
|
+ }
|
|
|
+ :deep(.el-steps) {
|
|
|
+ .is-finish {
|
|
|
+ .el-step__icon {
|
|
|
+ color: #ffffff;
|
|
|
+ background-color: #6c8ff8 !important;
|
|
|
+ border-color: #6c8ff8 !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .el-step__head {
|
|
|
+ .el-step__icon {
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .el-step__title {
|
|
|
+ .step-title-wrapper {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+ align-items: center;
|
|
|
+ .step-title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #6c8ff8;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 第一步内容样式
|
|
|
+ .step1-content {
|
|
|
+ .form-content {
|
|
|
+ max-width: 800px;
|
|
|
+ margin: 0 auto 40px;
|
|
|
+ .section-title {
|
|
|
+ margin-bottom: 30px;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ .id-card-upload-container {
|
|
|
+ display: flex;
|
|
|
+ gap: 40px;
|
|
|
+ align-items: flex-start;
|
|
|
+ justify-content: center;
|
|
|
+ :deep(.el-upload-list--picture-card) {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ .upload-item {
|
|
|
+ flex: 1;
|
|
|
+ max-width: 300px;
|
|
|
+ .upload-label {
|
|
|
+ margin-bottom: 12px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ .id-card-upload {
|
|
|
+ width: 100%;
|
|
|
+ :deep(.el-upload) {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 100%;
|
|
|
+ height: 200px;
|
|
|
+ cursor: pointer;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ transition: all 0.3s;
|
|
|
+ &:hover {
|
|
|
+ border-color: #6c8ff8;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 当上传完成后隐藏上传按钮
|
|
|
+ &.upload-complete {
|
|
|
+ :deep(.el-upload) {
|
|
|
+ display: none !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ :deep(.el-upload-list) {
|
|
|
+ .el-upload-list__item {
|
|
|
+ width: 100%;
|
|
|
+ height: 200px;
|
|
|
+ margin: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .upload-placeholder {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ .placeholder-text {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // OCR 识别结果展示样式
|
|
|
+ .ocr-result-container {
|
|
|
+ width: 635px;
|
|
|
+ padding: 20px;
|
|
|
+ margin: 60px auto;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ border-radius: 8px;
|
|
|
+ .ocr-result-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 16px;
|
|
|
+ font-size: 16px;
|
|
|
+ line-height: 1.5;
|
|
|
+ &:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+ .label {
|
|
|
+ min-width: 100px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #606266;
|
|
|
+ }
|
|
|
+ .value {
|
|
|
+ flex: 1;
|
|
|
+ color: #303133;
|
|
|
+ word-break: break-all;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .ocr-result-tip {
|
|
|
+ padding: 10px 0;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #909399;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .form-content {
|
|
|
+ max-width: 800px;
|
|
|
+ margin: 0 auto;
|
|
|
+ &.step2-form {
|
|
|
+ max-width: 100%;
|
|
|
+ .form-row {
|
|
|
+ display: flex;
|
|
|
+ gap: 40px;
|
|
|
+ .form-col {
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .form-actions {
|
|
|
+ display: flex;
|
|
|
+ gap: 20px;
|
|
|
+ justify-content: center;
|
|
|
+ padding-top: 30px;
|
|
|
+ margin-top: 40px;
|
|
|
+ border-top: 1px solid #e4e7ed;
|
|
|
+ .el-button {
|
|
|
+ width: 200px;
|
|
|
+ height: 44px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #ffffff;
|
|
|
+ background: #6c8ff8;
|
|
|
+ border: none;
|
|
|
+ border-radius: 4px;
|
|
|
+ outline: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|