zhuli 2 週間 前
コミット
299b892126

+ 13 - 0
src/api/modules/homeEntry.ts

@@ -106,3 +106,16 @@ export const getCheckPayPasswordTwo = params => {
 export const checkMenuPermissions = params => {
   return http.get(PORT_NONE + `/storePlatformLogin/getExpirationTime`, params);
 };
+// 经营板块三级分类接口 - 一级分类
+export const getFirstLevelList = params => {
+  return http.get(PORT_NONE + `/businessSection/getFirstLevelList`, params);
+};
+// 经营板块三级分类接口 - 二级分类
+export const getSecondLevelList = (params: { parentDictId: string }) => {
+  return http.get(PORT_NONE + `/businessSection/getSecondLevelList`, params, { loading: false });
+};
+
+// 经营板块三级分类接口 - 三级分类
+export const getThirdLevelList = (params: { parentDictId: string }) => {
+  return http.get(PORT_NONE + `/businessSection/getThirdLevelList`, params, { loading: false });
+};

+ 6 - 0
src/api/modules/newLoginApi.ts

@@ -42,6 +42,7 @@ export const getBusinessSection = () => {
 export const getBusinessSectionTypes = (params: { parentId: string }) => {
   return httpLogin.get(`/alienStore/store/info/getBusinessSectionTypes`, params);
 };
+
 //经纬度查询
 export const getInputPrompt = params => {
   return httpLogin.get(`/alienStore/gaode/getInputPrompt`, params);
@@ -59,3 +60,8 @@ export const uploadImg = (params: FormData) => {
 export const getCheckSmsCode = params => {
   return httpLogin.get(`/alienStore/ali/checkSmsCode`, params);
 };
+
+//ocr
+export const ocrRequestUrl = params => {
+  return httpLogin.post<Upload.ResFileUrl>(`/alienStore/ali/ocrRequestUrl`, params);
+};

+ 70 - 0
src/assets/json/authMenuList.json

@@ -602,6 +602,76 @@
           }
         }
       ]
+    },
+    {
+      "path": "/barManagement",
+      "name": "barManagement",
+      "component": "/barManagement/index",
+      "meta": {
+        "icon": "Shop",
+        "title": "酒吧",
+        "isLink": "",
+        "isHide": false,
+        "isFull": false,
+        "isAffix": false,
+        "isKeepAlive": false
+      }
+    },
+    {
+      "path": "/footManagement",
+      "name": "footManagement",
+      "component": "/footManagement/index",
+      "meta": {
+        "icon": "User",
+        "title": "按摩足疗",
+        "isLink": "",
+        "isHide": false,
+        "isFull": false,
+        "isAffix": false,
+        "isKeepAlive": false
+      }
+    },
+    {
+      "path": "/hairManagement",
+      "name": "hairManagement",
+      "component": "/hairManagement/index",
+      "meta": {
+        "icon": "Star",
+        "title": "丽人美发",
+        "isLink": "",
+        "isHide": false,
+        "isFull": false,
+        "isAffix": false,
+        "isKeepAlive": false
+      }
+    },
+    {
+      "path": "/fitnessManagement",
+      "name": "fitnessManagement",
+      "component": "/fitnessManagement/index",
+      "meta": {
+        "icon": "Trophy",
+        "title": "运动健身",
+        "isLink": "",
+        "isHide": false,
+        "isFull": false,
+        "isAffix": false,
+        "isKeepAlive": false
+      }
+    },
+    {
+      "path": "/spaManagement",
+      "name": "spaManagement",
+      "component": "/spaManagement/index",
+      "meta": {
+        "icon": "Sunny",
+        "title": "洗浴汗蒸",
+        "isLink": "",
+        "isHide": false,
+        "isFull": false,
+        "isAffix": false,
+        "isKeepAlive": false
+      }
     }
   ],
   "msg": "成功"

+ 1259 - 0
src/views/barManagement/go-flow.vue

@@ -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>

+ 99 - 0
src/views/barManagement/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <div id="home">
+    <!--已入驻-->
+    <go-examine v-if="isExaime" />
+    <!-- 第一步  未入驻 -->
+    <go-enter
+      :current-step="currentStep"
+      :store-application-status="storeApplicationStatus"
+      @update:current-step="handleUpdateCurrentStep"
+    />
+    <!-- 第二步 
+      @update:get-user-info="getUserInfo"-->
+    <go-flow
+      :current-step="currentStep"
+      @update:current-step="handleUpdateCurrentStep"
+      :store-application-status="storeApplicationStatus"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, watch } from "vue";
+import { localGet, localSet } from "@/utils/index";
+import goEnter from "../home/components/go-enter.vue";
+import goFlow from "./go-flow.vue";
+import goExamine from "../home/components/go-examine.vue";
+import { getMerchantByPhone, getDetail } from "@/api/modules/homeEntry";
+import { is } from "@/utils/is";
+import { useAuthStore } from "@/stores/modules/auth";
+
+const authStore = useAuthStore();
+const isEntry = ref<boolean>(false);
+const isExaime = ref<boolean>(false);
+
+onMounted(() => {
+  //   getUserInfo();
+});
+
+// 当前步骤:0-首页,1-第一步,2-第二步
+const currentStep = ref(0);
+const storeId = ref<Number | undefined>(undefined);
+// 处理更新currentStep事件
+const handleUpdateCurrentStep = (step: number) => {
+  currentStep.value = step;
+};
+let storeApplicationStatus = ref<number | undefined>(undefined);
+
+// const getUserInfo = async () => {
+//   try {
+//     const geekerUser = localGet("geeker-user");
+//     if (!geekerUser || !geekerUser.userInfo || !geekerUser.userInfo.phone) {
+//       console.error("用户信息不存在");
+//       return;
+//     }
+//     let param = {
+//       phone: geekerUser.userInfo.phone
+//     };
+//     const res: any = await getMerchantByPhone(param);
+//     storeId.value = res.data.storeId;
+//     if (res && res.code == 200 && res.data) {
+//       // 更新缓存中的 storeId
+//       geekerUser.userInfo.storeId = res.data.storeId;
+//       localSet("geeker-user", geekerUser);
+//       // 同时更新 createdId 缓存
+//       if (res.data.storeId) {
+//         localSet("createdId", res.data.storeId);
+//       }
+//       if (res.data.storeId == null) {
+//         isEntry.value = true;
+//       }
+//       if (res.data.storeId != null) {
+//         let param1 = {
+//           id: res.data.storeId
+//         };
+//         const resStore: any = await getDetail(param1);
+//         if (resStore && resStore.code == 200 && resStore.data) {
+//         //   storeApplicationStatus.value = resStore.data.storeApplicationStatus;
+//         //   // 如果是等待审核(0)或审核拒绝(2),且当前步骤为0,显示 go-enter 组件
+//         //   // 如果用户已经主动跳转到其他步骤,则不重置步骤
+//         //   if ((storeApplicationStatus.value == 0 || storeApplicationStatus.value == 2) && currentStep.value === 0) {
+//         //     currentStep.value = 0;
+//         //   }
+
+//           if (resStore.data.storeApplicationStatus !== 1 && res.data.storeId != null) {
+//             //storeId && storeDetail.storeApplicationStatus === 1
+//             isEntry.value = true;
+//           } else {
+//             isExaime.value = true;
+//           }
+//         }
+//       }
+//     }
+//   } catch (error) {
+//     console.error(error);
+//   }
+// };
+</script>
+
+<style scoped lang="scss"></style>

+ 1252 - 0
src/views/fitnessManagement/go-flow.vue

@@ -0,0 +1,1252 @@
+<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': isIdCardUploadComplete }"
+            >
+              <template v-if="idCardFrontList.length === 0 && !isIdCardUploadComplete">
+                <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': isIdCardUploadComplete }"
+            >
+              <template v-if="idCardBackList.length === 0 && !isIdCardUploadComplete">
+                <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="businessSecondMeal">
+                <el-radio-group v-model="step2Form.businessSecondMeal">
+                  <el-radio v-for="item in secondMealList" :value="item.value" :key="item.key">
+                    {{ item.dictDetail }}
+                  </el-radio>
+                </el-radio-group>
+              </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>
+            </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 secondMealList = ref([
+  { key: 0, value: 0, dictDetail: "提供" },
+  { key: 1, value: 1, dictDetail: "不提供" }
+]);
+
+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" }],
+  businessSecondMeal: [{ required: true, message: "请选择是否提供餐食", trigger: "change" }],
+  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" }]
+};
+
+//地址集合
+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({
+  businessSecondMeal: 0,
+  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[],
+  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;
+  }
+
+  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 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>

+ 99 - 0
src/views/fitnessManagement/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <div id="home">
+    <!--已入驻-->
+    <go-examine v-if="isExaime" />
+    <!-- 第一步  未入驻 -->
+    <go-enter
+      :current-step="currentStep"
+      :store-application-status="storeApplicationStatus"
+      @update:current-step="handleUpdateCurrentStep"
+    />
+    <!-- 第二步 
+      @update:get-user-info="getUserInfo"-->
+    <go-flow
+      :current-step="currentStep"
+      @update:current-step="handleUpdateCurrentStep"
+      :store-application-status="storeApplicationStatus"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, watch } from "vue";
+import { localGet, localSet } from "@/utils/index";
+import goEnter from "../home/components/go-enter.vue";
+import goFlow from "./go-flow.vue";
+import goExamine from "../home/components/go-examine.vue";
+import { getMerchantByPhone, getDetail } from "@/api/modules/homeEntry";
+import { is } from "@/utils/is";
+import { useAuthStore } from "@/stores/modules/auth";
+
+const authStore = useAuthStore();
+const isEntry = ref<boolean>(false);
+const isExaime = ref<boolean>(false);
+
+onMounted(() => {
+  //   getUserInfo();
+});
+
+// 当前步骤:0-首页,1-第一步,2-第二步
+const currentStep = ref(0);
+const storeId = ref<Number | undefined>(undefined);
+// 处理更新currentStep事件
+const handleUpdateCurrentStep = (step: number) => {
+  currentStep.value = step;
+};
+let storeApplicationStatus = ref<number | undefined>(undefined);
+
+// const getUserInfo = async () => {
+//   try {
+//     const geekerUser = localGet("geeker-user");
+//     if (!geekerUser || !geekerUser.userInfo || !geekerUser.userInfo.phone) {
+//       console.error("用户信息不存在");
+//       return;
+//     }
+//     let param = {
+//       phone: geekerUser.userInfo.phone
+//     };
+//     const res: any = await getMerchantByPhone(param);
+//     storeId.value = res.data.storeId;
+//     if (res && res.code == 200 && res.data) {
+//       // 更新缓存中的 storeId
+//       geekerUser.userInfo.storeId = res.data.storeId;
+//       localSet("geeker-user", geekerUser);
+//       // 同时更新 createdId 缓存
+//       if (res.data.storeId) {
+//         localSet("createdId", res.data.storeId);
+//       }
+//       if (res.data.storeId == null) {
+//         isEntry.value = true;
+//       }
+//       if (res.data.storeId != null) {
+//         let param1 = {
+//           id: res.data.storeId
+//         };
+//         const resStore: any = await getDetail(param1);
+//         if (resStore && resStore.code == 200 && resStore.data) {
+//         //   storeApplicationStatus.value = resStore.data.storeApplicationStatus;
+//         //   // 如果是等待审核(0)或审核拒绝(2),且当前步骤为0,显示 go-enter 组件
+//         //   // 如果用户已经主动跳转到其他步骤,则不重置步骤
+//         //   if ((storeApplicationStatus.value == 0 || storeApplicationStatus.value == 2) && currentStep.value === 0) {
+//         //     currentStep.value = 0;
+//         //   }
+
+//           if (resStore.data.storeApplicationStatus !== 1 && res.data.storeId != null) {
+//             //storeId && storeDetail.storeApplicationStatus === 1
+//             isEntry.value = true;
+//           } else {
+//             isExaime.value = true;
+//           }
+//         }
+//       }
+//     }
+//   } catch (error) {
+//     console.error(error);
+//   }
+// };
+</script>
+
+<style scoped lang="scss"></style>

+ 1252 - 0
src/views/footManagement/go-flow.vue

@@ -0,0 +1,1252 @@
+<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': isIdCardUploadComplete }"
+            >
+              <template v-if="idCardBackList.length === 0 && !isIdCardUploadComplete">
+                <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="businessSecondMeal">
+                <el-radio-group v-model="step2Form.businessSecondMeal">
+                  <el-radio v-for="item in secondMealList" :value="item.value" :key="item.key">
+                    {{ item.dictDetail }}
+                  </el-radio>
+                </el-radio-group>
+              </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>
+            </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 secondMealList = ref([
+  { key: 0, value: 0, dictDetail: "提供" },
+  { key: 1, value: 1, dictDetail: "不提供" }
+]);
+
+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" }],
+  businessSecondMeal: [{ required: true, message: "请选择是否提供餐食", trigger: "change" }],
+  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" }]
+};
+
+//地址集合
+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({
+  businessSecondMeal: 0,
+  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[],
+  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;
+  }
+
+  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 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>

+ 99 - 0
src/views/footManagement/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <div id="home">
+    <!--已入驻-->
+    <go-examine v-if="isExaime" />
+    <!-- 第一步  未入驻 -->
+    <go-enter
+      :current-step="currentStep"
+      :store-application-status="storeApplicationStatus"
+      @update:current-step="handleUpdateCurrentStep"
+    />
+    <!-- 第二步 
+      @update:get-user-info="getUserInfo"-->
+    <go-flow
+      :current-step="currentStep"
+      @update:current-step="handleUpdateCurrentStep"
+      :store-application-status="storeApplicationStatus"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, watch } from "vue";
+import { localGet, localSet } from "@/utils/index";
+import goEnter from "../home/components/go-enter.vue";
+import goFlow from "./go-flow.vue";
+import goExamine from "../home/components/go-examine.vue";
+import { getMerchantByPhone, getDetail } from "@/api/modules/homeEntry";
+import { is } from "@/utils/is";
+import { useAuthStore } from "@/stores/modules/auth";
+
+const authStore = useAuthStore();
+const isEntry = ref<boolean>(false);
+const isExaime = ref<boolean>(false);
+
+onMounted(() => {
+  //   getUserInfo();
+});
+
+// 当前步骤:0-首页,1-第一步,2-第二步
+const currentStep = ref(0);
+const storeId = ref<Number | undefined>(undefined);
+// 处理更新currentStep事件
+const handleUpdateCurrentStep = (step: number) => {
+  currentStep.value = step;
+};
+let storeApplicationStatus = ref<number | undefined>(undefined);
+
+// const getUserInfo = async () => {
+//   try {
+//     const geekerUser = localGet("geeker-user");
+//     if (!geekerUser || !geekerUser.userInfo || !geekerUser.userInfo.phone) {
+//       console.error("用户信息不存在");
+//       return;
+//     }
+//     let param = {
+//       phone: geekerUser.userInfo.phone
+//     };
+//     const res: any = await getMerchantByPhone(param);
+//     storeId.value = res.data.storeId;
+//     if (res && res.code == 200 && res.data) {
+//       // 更新缓存中的 storeId
+//       geekerUser.userInfo.storeId = res.data.storeId;
+//       localSet("geeker-user", geekerUser);
+//       // 同时更新 createdId 缓存
+//       if (res.data.storeId) {
+//         localSet("createdId", res.data.storeId);
+//       }
+//       if (res.data.storeId == null) {
+//         isEntry.value = true;
+//       }
+//       if (res.data.storeId != null) {
+//         let param1 = {
+//           id: res.data.storeId
+//         };
+//         const resStore: any = await getDetail(param1);
+//         if (resStore && resStore.code == 200 && resStore.data) {
+//         //   storeApplicationStatus.value = resStore.data.storeApplicationStatus;
+//         //   // 如果是等待审核(0)或审核拒绝(2),且当前步骤为0,显示 go-enter 组件
+//         //   // 如果用户已经主动跳转到其他步骤,则不重置步骤
+//         //   if ((storeApplicationStatus.value == 0 || storeApplicationStatus.value == 2) && currentStep.value === 0) {
+//         //     currentStep.value = 0;
+//         //   }
+
+//           if (resStore.data.storeApplicationStatus !== 1 && res.data.storeId != null) {
+//             //storeId && storeDetail.storeApplicationStatus === 1
+//             isEntry.value = true;
+//           } else {
+//             isExaime.value = true;
+//           }
+//         }
+//       }
+//     }
+//   } catch (error) {
+//     console.error(error);
+//   }
+// };
+</script>
+
+<style scoped lang="scss"></style>

+ 1252 - 0
src/views/hairManagement/go-flow.vue

@@ -0,0 +1,1252 @@
+<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': isIdCardUploadComplete }"
+            >
+              <template v-if="idCardBackList.length === 0 && !isIdCardUploadComplete">
+                <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="businessSecondMeal">
+                <el-radio-group v-model="step2Form.businessSecondMeal">
+                  <el-radio v-for="item in secondMealList" :value="item.value" :key="item.key">
+                    {{ item.dictDetail }}
+                  </el-radio>
+                </el-radio-group>
+              </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>
+            </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 secondMealList = ref([
+  { key: 0, value: 0, dictDetail: "提供" },
+  { key: 1, value: 1, dictDetail: "不提供" }
+]);
+
+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" }],
+  businessSecondMeal: [{ required: true, message: "请选择是否提供餐食", trigger: "change" }],
+  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" }]
+};
+
+//地址集合
+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({
+  businessSecondMeal: 0,
+  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[],
+  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;
+  }
+
+  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 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>

+ 99 - 0
src/views/hairManagement/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <div id="home">
+    <!--已入驻-->
+    <go-examine v-if="isExaime" />
+    <!-- 第一步  未入驻 -->
+    <go-enter
+      :current-step="currentStep"
+      :store-application-status="storeApplicationStatus"
+      @update:current-step="handleUpdateCurrentStep"
+    />
+    <!-- 第二步 
+      @update:get-user-info="getUserInfo"-->
+    <go-flow
+      :current-step="currentStep"
+      @update:current-step="handleUpdateCurrentStep"
+      :store-application-status="storeApplicationStatus"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, watch } from "vue";
+import { localGet, localSet } from "@/utils/index";
+import goEnter from "../home/components/go-enter.vue";
+import goFlow from "./go-flow.vue";
+import goExamine from "../home/components/go-examine.vue";
+import { getMerchantByPhone, getDetail } from "@/api/modules/homeEntry";
+import { is } from "@/utils/is";
+import { useAuthStore } from "@/stores/modules/auth";
+
+const authStore = useAuthStore();
+const isEntry = ref<boolean>(false);
+const isExaime = ref<boolean>(false);
+
+onMounted(() => {
+  //   getUserInfo();
+});
+
+// 当前步骤:0-首页,1-第一步,2-第二步
+const currentStep = ref(0);
+const storeId = ref<Number | undefined>(undefined);
+// 处理更新currentStep事件
+const handleUpdateCurrentStep = (step: number) => {
+  currentStep.value = step;
+};
+let storeApplicationStatus = ref<number | undefined>(undefined);
+
+// const getUserInfo = async () => {
+//   try {
+//     const geekerUser = localGet("geeker-user");
+//     if (!geekerUser || !geekerUser.userInfo || !geekerUser.userInfo.phone) {
+//       console.error("用户信息不存在");
+//       return;
+//     }
+//     let param = {
+//       phone: geekerUser.userInfo.phone
+//     };
+//     const res: any = await getMerchantByPhone(param);
+//     storeId.value = res.data.storeId;
+//     if (res && res.code == 200 && res.data) {
+//       // 更新缓存中的 storeId
+//       geekerUser.userInfo.storeId = res.data.storeId;
+//       localSet("geeker-user", geekerUser);
+//       // 同时更新 createdId 缓存
+//       if (res.data.storeId) {
+//         localSet("createdId", res.data.storeId);
+//       }
+//       if (res.data.storeId == null) {
+//         isEntry.value = true;
+//       }
+//       if (res.data.storeId != null) {
+//         let param1 = {
+//           id: res.data.storeId
+//         };
+//         const resStore: any = await getDetail(param1);
+//         if (resStore && resStore.code == 200 && resStore.data) {
+//         //   storeApplicationStatus.value = resStore.data.storeApplicationStatus;
+//         //   // 如果是等待审核(0)或审核拒绝(2),且当前步骤为0,显示 go-enter 组件
+//         //   // 如果用户已经主动跳转到其他步骤,则不重置步骤
+//         //   if ((storeApplicationStatus.value == 0 || storeApplicationStatus.value == 2) && currentStep.value === 0) {
+//         //     currentStep.value = 0;
+//         //   }
+
+//           if (resStore.data.storeApplicationStatus !== 1 && res.data.storeId != null) {
+//             //storeId && storeDetail.storeApplicationStatus === 1
+//             isEntry.value = true;
+//           } else {
+//             isExaime.value = true;
+//           }
+//         }
+//       }
+//     }
+//   } catch (error) {
+//     console.error(error);
+//   }
+// };
+</script>
+
+<style scoped lang="scss"></style>

+ 1252 - 0
src/views/spaManagement/go-flow.vue

@@ -0,0 +1,1252 @@
+<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': isIdCardUploadComplete }"
+            >
+              <template v-if="idCardBackList.length === 0 && !isIdCardUploadComplete">
+                <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="businessSecondMeal">
+                <el-radio-group v-model="step2Form.businessSecondMeal">
+                  <el-radio v-for="item in secondMealList" :value="item.value" :key="item.key">
+                    {{ item.dictDetail }}
+                  </el-radio>
+                </el-radio-group>
+              </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>
+            </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 secondMealList = ref([
+  { key: 0, value: 0, dictDetail: "提供" },
+  { key: 1, value: 1, dictDetail: "不提供" }
+]);
+
+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" }],
+  businessSecondMeal: [{ required: true, message: "请选择是否提供餐食", trigger: "change" }],
+  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" }]
+};
+
+//地址集合
+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({
+  businessSecondMeal: 0,
+  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[],
+  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;
+  }
+
+  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 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>

+ 99 - 0
src/views/spaManagement/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <div id="home">
+    <!--已入驻-->
+    <go-examine v-if="isExaime" />
+    <!-- 第一步  未入驻 -->
+    <go-enter
+      :current-step="currentStep"
+      :store-application-status="storeApplicationStatus"
+      @update:current-step="handleUpdateCurrentStep"
+    />
+    <!-- 第二步 
+      @update:get-user-info="getUserInfo"-->
+    <go-flow
+      :current-step="currentStep"
+      @update:current-step="handleUpdateCurrentStep"
+      :store-application-status="storeApplicationStatus"
+    />
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, watch } from "vue";
+import { localGet, localSet } from "@/utils/index";
+import goEnter from "../home/components/go-enter.vue";
+import goFlow from "./go-flow.vue";
+import goExamine from "../home/components/go-examine.vue";
+import { getMerchantByPhone, getDetail } from "@/api/modules/homeEntry";
+import { is } from "@/utils/is";
+import { useAuthStore } from "@/stores/modules/auth";
+
+const authStore = useAuthStore();
+const isEntry = ref<boolean>(false);
+const isExaime = ref<boolean>(false);
+
+onMounted(() => {
+  //   getUserInfo();
+});
+
+// 当前步骤:0-首页,1-第一步,2-第二步
+const currentStep = ref(0);
+const storeId = ref<Number | undefined>(undefined);
+// 处理更新currentStep事件
+const handleUpdateCurrentStep = (step: number) => {
+  currentStep.value = step;
+};
+let storeApplicationStatus = ref<number | undefined>(undefined);
+
+// const getUserInfo = async () => {
+//   try {
+//     const geekerUser = localGet("geeker-user");
+//     if (!geekerUser || !geekerUser.userInfo || !geekerUser.userInfo.phone) {
+//       console.error("用户信息不存在");
+//       return;
+//     }
+//     let param = {
+//       phone: geekerUser.userInfo.phone
+//     };
+//     const res: any = await getMerchantByPhone(param);
+//     storeId.value = res.data.storeId;
+//     if (res && res.code == 200 && res.data) {
+//       // 更新缓存中的 storeId
+//       geekerUser.userInfo.storeId = res.data.storeId;
+//       localSet("geeker-user", geekerUser);
+//       // 同时更新 createdId 缓存
+//       if (res.data.storeId) {
+//         localSet("createdId", res.data.storeId);
+//       }
+//       if (res.data.storeId == null) {
+//         isEntry.value = true;
+//       }
+//       if (res.data.storeId != null) {
+//         let param1 = {
+//           id: res.data.storeId
+//         };
+//         const resStore: any = await getDetail(param1);
+//         if (resStore && resStore.code == 200 && resStore.data) {
+//         //   storeApplicationStatus.value = resStore.data.storeApplicationStatus;
+//         //   // 如果是等待审核(0)或审核拒绝(2),且当前步骤为0,显示 go-enter 组件
+//         //   // 如果用户已经主动跳转到其他步骤,则不重置步骤
+//         //   if ((storeApplicationStatus.value == 0 || storeApplicationStatus.value == 2) && currentStep.value === 0) {
+//         //     currentStep.value = 0;
+//         //   }
+
+//           if (resStore.data.storeApplicationStatus !== 1 && res.data.storeId != null) {
+//             //storeId && storeDetail.storeApplicationStatus === 1
+//             isEntry.value = true;
+//           } else {
+//             isExaime.value = true;
+//           }
+//         }
+//       }
+//     }
+//   } catch (error) {
+//     console.error(error);
+//   }
+// };
+</script>
+
+<style scoped lang="scss"></style>