Просмотр исходного кода

Merge remote-tracking branch 'origin/development_new' into development_new

spy 2 недель назад
Родитель
Сommit
ea99484bca

+ 3 - 3
src/api/modules/licenseManagement.ts

@@ -14,7 +14,7 @@ export const getFoodBusinessLicense = params => {
 
 // 获取娱乐经营许可证
 export const getEntertainmentBusinessLicense = params => {
-  return http.get(PORT_NONE + `/license/queryEntertainmentLicenceList`, params);
+  return http.get(PORT_NONE + `/license/queryEntertainmentLicenseList`, params);
 };
 
 // 获取合同图片列表
@@ -34,7 +34,7 @@ export const getChangeRecords = params => {
 
 // 获取娱乐经营许可证变更记录
 export const getEntertainmentChangeRecords = params => {
-  return http.get(PORT_NONE + `/license/queryEntertainmentLicenceByStatusList`, params);
+  return http.get(PORT_NONE + `/license/queryEntertainmentByStatusList`, params);
 };
 // 获取合同审核状态
 export const getStoreContractStatus = params => {
@@ -48,7 +48,7 @@ export const getStoreFoodLicenceStatus = params => {
 
 // 获取娱乐经营许可证审核状态
 export const getStoreEntertainmentLicenceStatus = params => {
-  return http.get(PORT_NONE + `/license/getStoreEntertainmentLicenceStatus`, params);
+  return http.get(PORT_NONE + `/license/queryStoreEntertainmentStatus`, params);
 };
 
 // 提交食品经营许可证审核

+ 6 - 2
src/layouts/components/Header/ToolBarRight.vue

@@ -26,8 +26,12 @@ import Avatar from "./components/Avatar.vue";
 import { localGet } from "@/utils/index";
 
 const userStore = useUserStore();
-const username = computed(() => userStore.userInfo.name);
-const userInfo = localGet("geeker-user")?.userInfo || {};
+// 使用 computed 来获取响应式的用户信息,优先使用 store 中的数据,否则从本地存储获取
+const userInfo = computed(() => {
+  return userStore.userInfo && Object.keys(userStore.userInfo).length > 0
+    ? userStore.userInfo
+    : localGet("geeker-user")?.userInfo || {};
+});
 </script>
 
 <style scoped lang="scss">

+ 27 - 1
src/layouts/components/Header/components/Avatar.vue

@@ -18,7 +18,7 @@
     </template>
   </el-dropdown>
   <!-- infoDialog -->
-  <InfoDialog ref="infoRef" @avatar-updated="getUserInfo" />
+  <InfoDialog ref="infoRef" @avatar-updated="handleAvatarUpdated" />
   <!-- passwordDialog -->
   <PasswordDialog ref="passwordRef" />
 </template>
@@ -66,10 +66,36 @@ const avatarUrl = computed(() => {
   return headImg.value && headImg.value !== null && headImg.value !== "" ? headImg.value : defaultAvatar;
 });
 
+// 处理头像更新事件
+const handleAvatarUpdated = async (newAvatarUrl?: string) => {
+  console.log("收到头像更新事件,新头像URL:", newAvatarUrl);
+  const userInfo = localGet("geeker-user")?.userInfo || {};
+  if (newAvatarUrl && newAvatarUrl.trim() !== "") {
+    // 如果传递了新的头像URL,直接更新
+    headImg.value = newAvatarUrl;
+    if (userInfo.phone) {
+      localSet(`avatar_${userInfo.phone}`, newAvatarUrl);
+      console.log("直接更新头像URL:", newAvatarUrl, "当前 headImg.value:", headImg.value);
+    }
+  } else {
+    // 如果没有传递URL或URL为空,则重新获取用户信息
+    console.log("头像URL为空,重新获取用户信息");
+    await getUserInfo();
+  }
+};
+
 // 获取用户信息
 const getUserInfo = async () => {
   const userInfo = localGet("geeker-user")?.userInfo || {};
   if (userInfo.phone) {
+    // 先检查登录时存储的用户信息中是否有头像
+    const loginAvatarUrl = userInfo.headImg || userInfo.avatar || "";
+    if (loginAvatarUrl && loginAvatarUrl.trim() !== "") {
+      headImg.value = loginAvatarUrl;
+      localSet(`avatar_${userInfo.phone}`, loginAvatarUrl);
+      console.log("从登录信息中获取头像URL:", loginAvatarUrl);
+    }
+
     try {
       const res: any = await getMerchantByPhone({ phone: userInfo.phone });
       console.log("API返回数据:", res);

+ 58 - 6
src/layouts/components/Header/components/InfoDialog.vue

@@ -47,14 +47,16 @@ import { ElMessage, type FormInstance, type UploadUserFile, UploadRequestOptions
 import { Plus } from "@element-plus/icons-vue";
 import { getMerchantByPhone, updateMerchantUserInfo } from "@/api/modules/homeEntry";
 import { uploadImg } from "@/api/modules/newLoginApi";
-import { localGet } from "@/utils/index";
+import { localGet, localSet } from "@/utils/index";
 import defaultAvatar from "@/assets/images/avatar.gif";
 import { head } from "lodash";
+import { useUserStore } from "@/stores/modules/user";
 
 const emit = defineEmits<{
-  avatarUpdated: [];
+  avatarUpdated: [avatarUrl?: string];
 }>();
 
+const userStore = useUserStore();
 const userInfo = localGet("geeker-user")?.userInfo || {};
 const dialogVisible = ref(false);
 
@@ -82,6 +84,7 @@ const getUserInfo = async () => {
     const headImg = res.data.headImg;
     if (headImg && headImg !== null && headImg !== "") {
       // 如果有头像,使用用户头像
+      headImg1.value = headImg; // 初始化 headImg1
       form.avatarList = [
         {
           name: "avatar",
@@ -91,6 +94,7 @@ const getUserInfo = async () => {
       ];
     } else {
       // 如果 headImg 为 null 或空,使用默认头像
+      headImg1.value = ""; // 清空 headImg1
       form.avatarList = [
         {
           name: "avatar",
@@ -115,6 +119,11 @@ const handleHttpUpload = async (options: UploadRequestOptions) => {
     const fileUrl = res?.data?.fileUrl || res?.data?.[0] || res?.fileUrl;
     if (fileUrl) {
       headImg1.value = fileUrl;
+      // 更新 form.avatarList 中对应文件的 URL
+      if (form.avatarList && form.avatarList.length > 0) {
+        form.avatarList[0].url = fileUrl;
+        form.avatarList[0].response = { fileUrl };
+      }
       // 调用 onSuccess 回调,传入响应数据
       options.onSuccess({ fileUrl });
     } else {
@@ -127,20 +136,63 @@ const handleHttpUpload = async (options: UploadRequestOptions) => {
 };
 const getSaveUserInfo = async () => {
   try {
+    // 获取头像URL:优先使用新上传的,否则从 avatarList 中获取,最后为空字符串
+    let avatarUrl = headImg1.value;
+    console.log("保存前 headImg1.value:", headImg1.value);
+    console.log("保存前 form.avatarList:", form.avatarList);
+
+    // 如果 headImg1.value 为空,尝试从 form.avatarList 中获取
+    if (!avatarUrl && form.avatarList && form.avatarList.length > 0) {
+      const avatarFile = form.avatarList[0];
+      // 从 file.url 或 file.response 中获取 URL
+      const fileUrl = avatarFile.url || (avatarFile.response as any)?.fileUrl || "";
+      // 排除默认头像
+      if (fileUrl && fileUrl !== defaultAvatar) {
+        avatarUrl = fileUrl;
+        // 同时更新 headImg1.value,以便后续使用
+        headImg1.value = fileUrl;
+      }
+    }
+
+    console.log("保存时使用的头像URL:", avatarUrl);
+
     const res: any = await updateMerchantUserInfo({
       id: userId.value,
       nickName: form.nickname,
-      headImg: headImg1.value ? headImg1.value : "",
+      headImg: avatarUrl || "",
       accountBlurb: form.intro
     });
 
     if (res.code == 200) {
       ElMessage.success(res.msg || "保存成功");
       dialogVisible.value = false;
-      // 可以刷新用户信息
+      // 通知父组件头像已更新,传递新的头像URL(优先使用保存的头像URL)
+      const finalAvatarUrl = avatarUrl && avatarUrl.trim() !== "" ? avatarUrl : res.data?.headImg || "";
+      console.log("保存成功,传递给父组件的头像URL:", finalAvatarUrl);
+      emit("avatarUpdated", finalAvatarUrl);
+
+      // 更新本地存储和 userStore 中的用户信息
+      try {
+        const merchantRes: any = await getMerchantByPhone({ phone: userInfo.phone });
+        if (merchantRes && merchantRes.code == 200 && merchantRes.data) {
+          // 更新本地存储
+          const geekerUser = localGet("geeker-user");
+          if (geekerUser) {
+            geekerUser.userInfo = {
+              ...geekerUser.userInfo,
+              ...merchantRes.data
+            };
+            localSet("geeker-user", geekerUser);
+            // 更新 userStore
+            userStore.setUserInfo(geekerUser.userInfo);
+          }
+        }
+      } catch (error) {
+        console.error("获取更新后的用户信息失败:", error);
+      }
+
+      // 刷新用户信息(用于更新对话框中的数据)
       getUserInfo();
-      // 通知父组件头像已更新
-      emit("avatarUpdated");
     } else {
       ElMessage.error(res.msg || "保存失败,请重试");
     }

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

@@ -1,1296 +0,0 @@
-<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>
-
-              <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>
-            </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 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" }],
-  businessSection: [{ required: true, message: "请选择经营板块", trigger: "change" }],
-  businessSecondMeal: [{ 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({
-  businessSecondMeal: 0,
-  storeName: "",
-  storeCapacity: 1,
-  storeArea: "1",
-  isChain: 0,
-  storeDetailAddress: "",
-  region: [],
-  administrativeRegionProvinceAdcode: "",
-  administrativeRegionCityAdcode: "",
-  administrativeRegionDistrictAdcode: "",
-  storeAddress: "",
-  storeBlurb: "",
-  businessSection: "1",
-  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 && Array.isArray(res.data) && res.data.length > 0) {
-        // 从正面(第一个元素)获取姓名
-        const frontData = res.data[0]?.face?.data;
-        // 从反面(第二个元素)获取身份证号,如果没有第二个元素则从正面获取
-        const backData = res.data[1]?.face?.data || frontData;
-
-        // 提取姓名
-        const name = frontData?.name || "";
-
-        // 提取身份证号,优先从反面获取,如果没有则从正面获取
-        let idCard = backData?.idNumber || frontData?.idNumber || "";
-
-        // 如果从 data 中获取不到,尝试从 prism_keyValueInfo 中查找
-        if (!idCard && res.data[1]?.face?.prism_keyValueInfo) {
-          const idNumberInfo = res.data[1].face.prism_keyValueInfo.find((item: any) => item.key === "idNumber" && item.value);
-          if (idNumberInfo) {
-            idCard = idNumberInfo.value;
-          }
-        }
-
-        // 如果反面没有,尝试从正面查找
-        if (!idCard && res.data[0]?.face?.prism_keyValueInfo) {
-          const idNumberInfo = res.data[0].face.prism_keyValueInfo.find((item: any) => item.key === "idNumber" && item.value);
-          if (idNumberInfo) {
-            idCard = idNumberInfo.value;
-          }
-        }
-
-        ocrResult.value = {
-          name: name,
-          idCard: idCard
-        };
-
-        // 更新本地存储中的用户信息
-        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: 670px;
-        padding: 20px;
-        margin: 60px auto;
-        .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>

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

@@ -1,99 +0,0 @@
-<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>

+ 170 - 35
src/views/home/components/go-flow.vue

@@ -31,7 +31,7 @@
               list-type="picture-card"
               :limit="1"
               :on-exceed="handleExceed"
-              :on-success="handleUploadSuccess"
+              :on-success="(response, file) => handleUploadSuccess(response, file, 'ID_CARD')"
               :on-preview="handlePictureCardPreview"
               :on-remove="handleRemove"
               accept="image/*"
@@ -55,7 +55,7 @@
               list-type="picture-card"
               :limit="1"
               :on-exceed="handleExceed"
-              :on-success="handleUploadSuccess"
+              :on-success="(response, file) => handleUploadSuccess(response, file, 'ID_CARD')"
               :on-preview="handlePictureCardPreview"
               :on-remove="handleRemove"
               accept="image/*"
@@ -222,7 +222,7 @@
                   list-type="picture-card"
                   :limit="1"
                   :on-exceed="handleExceed"
-                  :on-success="handleUploadSuccess"
+                  :on-success="(response, file) => handleUploadSuccess(response, file, 'BUSINESS_LICENSE')"
                   :on-preview="handlePictureCardPreview"
                 >
                   <el-icon><Plus /></el-icon>
@@ -239,7 +239,7 @@
                   list-type="picture-card"
                   :limit="20"
                   :on-exceed="handleExceed"
-                  :on-success="handleUploadSuccess"
+                  :on-success="(response, file) => handleUploadSuccess(response, file, '')"
                   :on-preview="handlePictureCardPreview"
                 >
                   <el-icon><Plus /></el-icon>
@@ -256,7 +256,7 @@
                   list-type="picture-card"
                   :limit="1"
                   :on-exceed="handleExceed"
-                  :on-success="handleUploadSuccess"
+                  :on-success="(response, file) => handleUploadSuccess(response, file, 'FOOD_MANAGE_LICENSE')"
                   :on-preview="handlePictureCardPreview"
                 >
                   <el-icon><Plus /></el-icon>
@@ -273,7 +273,7 @@
                   list-type="picture-card"
                   :limit="1"
                   :on-exceed="handleExceed"
-                  :on-success="handleUploadSuccess"
+                  :on-success="(response, file) => handleUploadSuccess(response, file, 'BUSINESS_LICENSE')"
                   :on-preview="handlePictureCardPreview"
                 >
                   <el-icon><Plus /></el-icon>
@@ -370,9 +370,44 @@ const ocrResult = ref<{
   idCard?: string;
 }>({});
 
+// 食品经营许可证到期时间(从 OCR 结果中提取)
+const foodLicenceExpirationTime = ref<string>("");
+// 娱乐经营许可证到期时间(从 OCR 结果中提取)
+const entertainmentLicenceExpirationTime = ref<string>("");
+
 // 是否正在识别中
 const isOcrProcessing = ref(false);
 
+// 日期格式转换函数:支持两种格式
+// 1. "20220508" -> "2022-05-08"
+// 2. "2024年01月14日" -> "2024-01-14"
+const formatDate = (dateStr: string): string => {
+  if (!dateStr) {
+    return "";
+  }
+
+  // 处理中文日期格式:2024年01月14日
+  if (dateStr.includes("年") && dateStr.includes("月") && dateStr.includes("日")) {
+    const match = dateStr.match(/(\d{4})年(\d{1,2})月(\d{1,2})日/);
+    if (match) {
+      const year = match[1];
+      const month = match[2].padStart(2, "0"); // 补零,确保是两位数
+      const day = match[3].padStart(2, "0"); // 补零,确保是两位数
+      return `${year}-${month}-${day}`;
+    }
+  }
+
+  // 处理8位数字格式:20220508
+  if (dateStr.length === 8 && /^\d{8}$/.test(dateStr)) {
+    const year = dateStr.substring(0, 4);
+    const month = dateStr.substring(4, 6);
+    const day = dateStr.substring(6, 8);
+    return `${year}-${month}-${day}`;
+  }
+
+  return "";
+};
+
 // 计算是否已上传完成(正反面都上传完成)
 const isIdCardUploadComplete = computed(() => {
   return idCardFrontList.value.length > 0 && idCardBackList.value.length > 0;
@@ -733,6 +768,21 @@ const getBusinessSectionList = async () => {
     const res: any = await getFirstLevelList({});
     if (res && res.code === 200 && res.data) {
       businessSectionList.value = res.data;
+      // 如果有数据,自动加载第一个经营板块的二级分类(经营种类)
+      if (res.data && res.data.length > 0) {
+        const firstSection = res.data[0];
+        const firstDictId = firstSection.dictId || firstSection.id;
+        if (firstDictId) {
+          try {
+            const secondRes: any = await getSecondLevelList({ parentDictId: String(firstDictId) });
+            if (secondRes && (secondRes.code === 200 || secondRes.code === "200") && secondRes.data) {
+              secondLevelList.value = secondRes.data;
+            }
+          } catch (error) {
+            console.error("获取二级分类失败:", error);
+          }
+        }
+      }
     }
   } catch (error) {
     console.error("获取一级分类失败:", error);
@@ -896,39 +946,88 @@ const handleHttpUpload = async (options: UploadRequestOptions) => {
 };
 
 // 自动调用 OCR 识别
-const autoOcrRecognition = async () => {
-  // 检查正反面是否都已上传完成
-  if (idCardFrontList.value.length === 0 || idCardBackList.value.length === 0) {
+const autoOcrRecognition = async (ocrType: string) => {
+  // 如果正在识别中,不重复调用
+  if (isOcrProcessing.value) {
     return;
   }
 
-  const frontFile = idCardFrontList.value[0];
-  const backFile = idCardBackList.value[0];
+  let imageUrls = "";
+  let fileList: UploadUserFile[] = [];
 
-  // 验证上传的文件是否成功
-  if (frontFile.status !== "success" || !frontFile.url || backFile.status !== "success" || !backFile.url) {
-    return;
-  }
+  // 根据不同的 ocrType 获取对应的图片 URL
+  if (ocrType === "ID_CARD") {
+    // 身份证:需要检查正反面是否都已上传完成
+    if (idCardFrontList.value.length === 0 || idCardBackList.value.length === 0) {
+      return;
+    }
 
-  // 获取身份证正反面的 URL
-  const frontUrl = getFileUrls(idCardFrontList.value)[0] || "";
-  const backUrl = getFileUrls(idCardBackList.value)[0] || "";
+    const frontFile = idCardFrontList.value[0];
+    const backFile = idCardBackList.value[0];
 
-  if (!frontUrl || !backUrl) {
-    return;
-  }
+    // 验证上传的文件是否成功
+    if (frontFile.status !== "success" || !frontFile.url || backFile.status !== "success" || !backFile.url) {
+      return;
+    }
 
-  // 如果正在识别中,不重复调用
-  if (isOcrProcessing.value) {
+    // 获取身份证正反面的 URL
+    const frontUrl = getFileUrls(idCardFrontList.value)[0] || "";
+    const backUrl = getFileUrls(idCardBackList.value)[0] || "";
+
+    if (!frontUrl || !backUrl) {
+      return;
+    }
+
+    // 将正反面 URL 用逗号分隔
+    imageUrls = `${frontUrl},${backUrl}`;
+  } else if (ocrType === "BUSINESS_LICENSE") {
+    // 营业执照或娱乐经营许可证:检查是否已上传
+    // 优先检查营业执照,如果没有再检查娱乐经营许可证
+    let fileList: UploadUserFile[] = [];
+    if (step2Form.businessLicenseAddress.length > 0) {
+      fileList = step2Form.businessLicenseAddress;
+    } else if (step2Form.disportLicenceImgList.length > 0) {
+      fileList = step2Form.disportLicenceImgList;
+    } else {
+      return;
+    }
+
+    const file = fileList[0];
+    if (file.status !== "success" || !file.url) {
+      return;
+    }
+
+    const fileUrl = getFileUrls(fileList)[0] || "";
+    if (!fileUrl) {
+      return;
+    }
+
+    imageUrls = fileUrl;
+  } else if (ocrType === "FOOD_MANAGE_LICENSE") {
+    // 食品经营许可证:检查是否已上传
+    if (step2Form.foodLicenceImgList.length === 0) {
+      return;
+    }
+
+    const file = step2Form.foodLicenceImgList[0];
+    if (file.status !== "success" || !file.url) {
+      return;
+    }
+
+    const fileUrl = getFileUrls(step2Form.foodLicenceImgList)[0] || "";
+    if (!fileUrl) {
+      return;
+    }
+
+    imageUrls = fileUrl;
+  } else {
+    // 其他类型不进行 OCR
     return;
   }
 
-  // 将正反面 URL 用逗号分隔
-  const imageUrls = `${frontUrl},${backUrl}`;
-
   let params = {
     imageUrls: imageUrls,
-    ocrType: "ID_CARD",
+    ocrType: ocrType,
     storeId: userInfo.storeId,
     storeUserId: userInfo.id
   };
@@ -937,8 +1036,8 @@ const autoOcrRecognition = async () => {
     isOcrProcessing.value = true;
     const res: any = await ocrRequestUrl(params);
     if (res && (res.code === 200 || res.code === "200")) {
-      // 保存识别结果
-      if (res.data && Array.isArray(res.data) && res.data.length > 0) {
+      // 只有身份证类型才需要保存识别结果到 ocrResult
+      if (ocrType === "ID_CARD" && res.data && Array.isArray(res.data) && res.data.length > 0) {
         // 从正面(第一个元素)获取姓名
         const frontData = res.data[0]?.face?.data;
         // 从反面(第二个元素)获取身份证号,如果没有第二个元素则从正面获取
@@ -984,27 +1083,61 @@ const autoOcrRecognition = async () => {
         }
 
         ElMessage.success("身份证识别成功");
+      } else if (ocrType === "BUSINESS_LICENSE") {
+        // 判断是营业执照还是娱乐经营许可证
+        const isBusinessLicense = step2Form.businessLicenseAddress.length > 0;
+
+        // 提取 validToDate 字段(娱乐经营许可证)
+        if (!isBusinessLicense && res.data && Array.isArray(res.data) && res.data.length > 0) {
+          const validToDate = res.data[0]?.validToDate || "";
+          if (validToDate) {
+            entertainmentLicenceExpirationTime.value = formatDate(validToDate);
+            console.log(entertainmentLicenceExpirationTime.value);
+          }
+        }
+
+        if (isBusinessLicense) {
+          ElMessage.success("营业执照识别成功");
+        } else {
+          ElMessage.success("娱乐经营许可证识别成功");
+        }
+      } else if (ocrType === "FOOD_MANAGE_LICENSE") {
+        // 提取食品经营许可证的 validToDate 字段
+        if (res.data && Array.isArray(res.data) && res.data.length > 0) {
+          const validToDate = res.data[0]?.validToDate || "";
+          if (validToDate) {
+            console.log(formatDate(validToDate));
+            foodLicenceExpirationTime.value = formatDate(validToDate);
+            console.log(foodLicenceExpirationTime.value);
+          }
+        }
+        ElMessage.success("食品经营许可证识别成功");
       }
     } else {
       console.warn("OCR 识别失败:", res?.msg);
+      ElMessage.error(res?.msg || "识别失败,请重试");
     }
   } catch (error) {
-    console.error("身份证识别失败:", error);
+    console.error("OCR 识别失败:", error);
+    ElMessage.error("识别失败,请重试");
   } finally {
     isOcrProcessing.value = false;
   }
 };
 
 // 文件上传成功回调
-const handleUploadSuccess = (response: any, uploadFile: UploadUserFile) => {
+const handleUploadSuccess = (response: any, uploadFile: UploadUserFile, ocrType: string) => {
   if (response?.fileUrl) {
     uploadFile.url = response.fileUrl;
   }
 
-  // 延迟一下,确保文件状态已更新,然后检查是否需要自动 OCR
-  setTimeout(() => {
-    autoOcrRecognition();
-  }, 100);
+  // 只有指定的类型才进行 OCR 识别
+  if (ocrType && (ocrType === "ID_CARD" || ocrType === "BUSINESS_LICENSE" || ocrType === "FOOD_MANAGE_LICENSE")) {
+    // 延迟一下,确保文件状态已更新,然后检查是否需要自动 OCR
+    setTimeout(() => {
+      autoOcrRecognition(ocrType);
+    }, 100);
+  }
 };
 
 // 图片预览处理函数
@@ -1185,6 +1318,8 @@ const handleSubmit = async () => {
       }
 
       const params = {
+        foodLicenceExpirationTime: foodLicenceExpirationTime.value, //食品经营许可证到期时间
+        entertainmentLicenceExpirationTime: entertainmentLicenceExpirationTime.value, //娱乐经营许可证到期时间
         businessClassifyList: step2Form.businessSecondLevel, //三级分类
         mealProvided: step2Form.businessSecondMeal, //是否提供餐食
         entertainmentLicenseAddress: disportLicenceUrls, //娱乐经营许可证

+ 2 - 2
src/views/licenseManagement/businessLicense.vue

@@ -15,7 +15,7 @@
       </div>
     </div>
     <div v-else class="empty-contract">
-      <el-empty description="暂无合同图片" :image-size="100" />
+      <el-empty description="暂无营业执照" :image-size="100" />
     </div>
   </div>
 </template>
@@ -41,7 +41,7 @@ const initData = async () => {
   };
   const res: any = await getBusinessLicense(params);
   if (res.code == 200) {
-    licenseImage.value = res.data[0].imgUrl;
+    licenseImage.value = res.data[0]?.imgUrl;
   }
 };
 </script>

+ 8 - 5
src/views/licenseManagement/contractManagement.vue

@@ -1,9 +1,7 @@
 <template>
   <div class="card content-box">
     <div class="content-section">
-      <div class="tip-text">
-        如需续约合同或更改合同图片请在此处上传,重新上传之后需要重新进行审核,审核通过后,新的合同图片将会覆盖之前的合同
-      </div>
+      <div class="tip-text">店铺到期时间:{{ expirationTime || "--" }}</div>
       <div class="action-buttons">
         <el-button type="primary" @click="handleReplace"> 更换 </el-button>
         <el-button type="primary" @click="handleViewChangeRecord"> 查看变更记录 </el-button>
@@ -154,6 +152,7 @@ const statusMap: Record<number, { name: string; class: string }> = {
 };
 
 const contractList = ref<any>([]);
+const expirationTime = ref<string>("");
 const replaceDialogVisible = ref(false);
 const changeRecordDialogVisible = ref(false);
 const fileList = ref<UploadFile[]>([]);
@@ -203,6 +202,10 @@ const initData = async () => {
   const res: any = await getContractImages(params);
   if (res.code == 200) {
     contractList.value = res.data;
+    // 如果返回的数据中包含到期时间,从第一个合同项中获取
+    if (res.data && res.data.length > 0 && res.data[0]?.expirationTime) {
+      expirationTime.value = res.data[0].expirationTime;
+    }
   }
 };
 
@@ -215,7 +218,7 @@ const handleReplace = async () => {
     id: localGet("createdId")
   };
   const res: any = await getStoreContractStatus(params);
-  if (res.data.renewContractStatus === 2) {
+  if (res.data.renewContractStatus == 2) {
     ElMessage.warning("合同审核中,请耐心等待");
   } else {
     replaceDialogVisible.value = true;
@@ -614,9 +617,9 @@ const getStatusName = (status: number) => {
 }
 .content-section {
   display: flex;
-  gap: 50px;
   align-items: center;
   justify-content: space-between;
+  width: 100%;
   margin-top: 20px;
   margin-bottom: 50px;
 }

+ 28 - 8
src/views/licenseManagement/entertainmentLicense.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="card content-box">
     <div class="content-section">
-      <div class="tip-text">娱乐经营许可证到期时间:{{ entertainmentLicenseExpireTime || "--" }}</div>
+      <div class="tip-text">娱乐经营许可证到期时间:{{ expirationTime || "--" }}</div>
       <div class="action-buttons">
         <el-button type="primary" @click="handleReplace"> 更换 </el-button>
         <el-button type="primary" @click="handleViewChangeRecord"> 查看变更记录 </el-button>
@@ -9,7 +9,15 @@
     </div>
     <div class="license-container" v-if="licenseImage">
       <div class="license-display">
-        <el-image :src="licenseImage" fit="contain" class="license-image" :preview-src-list="[licenseImage]" />
+        <el-image :src="licenseImage" fit="contain" class="license-image" :preview-src-list="[licenseImage]">
+          <template #error>
+            <div class="empty-image-box">
+              <el-icon class="empty-icon">
+                <Picture />
+              </el-icon>
+            </div>
+          </template>
+        </el-image>
       </div>
     </div>
     <div v-else class="empty-license">
@@ -132,7 +140,7 @@ const statusMap: Record<number, { name: string; class: string }> = {
 };
 
 const id = localGet("createdId");
-const entertainmentLicenseExpireTime = ref<string>("");
+const expirationTime = ref<string>("");
 const licenseImage = ref<string>("");
 const replaceDialogVisible = ref(false);
 const changeRecordDialogVisible = ref(false);
@@ -179,8 +187,8 @@ const initData = async () => {
   };
   const res: any = await getEntertainmentBusinessLicense(params);
   if (res.code == 200) {
-    licenseImage.value = res.data[0].imgUrl;
-    entertainmentLicenseExpireTime.value = res.data[0].expireTime;
+    licenseImage.value = res.data[0]?.imgUrl;
+    expirationTime.value = res.data[0]?.expirationTime;
   }
 };
 
@@ -193,7 +201,7 @@ const handleReplace = async () => {
     id: localGet("createdId")
   };
   const res: any = await getStoreEntertainmentLicenceStatus(params);
-  if (res.data.entertainmentLicenceStatus === 2) {
+  if (res.data.entertainmentStatus == 2) {
     ElMessage.warning("娱乐经营许可证审核中,请耐心等待");
   } else {
     replaceDialogVisible.value = true;
@@ -600,14 +608,13 @@ const getStatusText = (status: string) => {
 }
 .content-section {
   display: flex;
-  gap: 50px;
   align-items: center;
   justify-content: space-between;
+  width: 100%;
   margin-top: 20px;
   margin-bottom: 50px;
 }
 .tip-text {
-  margin-right: 450px;
   font-size: 18px;
   color: var(--el-text-color-regular);
 }
@@ -634,6 +641,19 @@ const getStatusText = (status: string) => {
   border-radius: 8px;
   box-shadow: 0 2px 12px rgb(0 0 0 / 10%);
 }
+.empty-image-box {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 100%;
+  height: 100%;
+  background-color: var(--el-fill-color-lighter);
+  border-radius: 8px;
+  .empty-icon {
+    font-size: 64px;
+    color: var(--el-text-color-placeholder);
+  }
+}
 .empty-license {
   display: flex;
   align-items: center;

+ 28 - 7
src/views/licenseManagement/foodBusinessLicense.vue

@@ -1,9 +1,7 @@
 <template>
   <div class="card content-box">
     <div class="content-section">
-      <div class="tip-text">
-        如需变更请在此处上传,重新上传之后需要重新进行审核,审核通过后,新的食品经营许可证将会覆盖之前的食品经营许可证
-      </div>
+      <div class="tip-text">食品经营许可证到期时间:{{ expirationTime || "--" }}</div>
       <div class="action-buttons">
         <el-button type="primary" @click="handleReplace"> 更换 </el-button>
         <el-button type="primary" @click="handleViewChangeRecord"> 查看变更记录 </el-button>
@@ -11,7 +9,15 @@
     </div>
     <div class="license-container" v-if="licenseImage">
       <div class="license-display">
-        <el-image :src="licenseImage" fit="contain" class="license-image" :preview-src-list="[licenseImage]" />
+        <el-image :src="licenseImage" fit="contain" class="license-image" :preview-src-list="[licenseImage]">
+          <template #error>
+            <div class="empty-image-box">
+              <el-icon class="empty-icon">
+                <Picture />
+              </el-icon>
+            </div>
+          </template>
+        </el-image>
       </div>
     </div>
     <div v-else class="empty-license">
@@ -136,6 +142,7 @@ const statusMap: Record<number, { name: string; class: string }> = {
 const id = localGet("createdId");
 
 const licenseImage = ref<string>("");
+const expirationTime = ref<string>("");
 const replaceDialogVisible = ref(false);
 const changeRecordDialogVisible = ref(false);
 const fileList = ref<UploadFile[]>([]);
@@ -181,7 +188,8 @@ const initData = async () => {
   };
   const res: any = await getFoodBusinessLicense(params);
   if (res.code == 200) {
-    licenseImage.value = res.data[0].imgUrl;
+    licenseImage.value = res.data[0]?.imgUrl;
+    expirationTime.value = res.data[0]?.expirationTime;
   }
 };
 
@@ -194,7 +202,7 @@ const handleReplace = async () => {
     id: localGet("createdId")
   };
   const res: any = await getStoreFoodLicenceStatus(params);
-  if (res.data.foodLicenceStatus === 2) {
+  if (res.data.foodLicenceStatus == 2) {
     ElMessage.warning("食品经营许可证审核中,请耐心等待");
   } else {
     replaceDialogVisible.value = true;
@@ -601,9 +609,9 @@ const getStatusText = (status: string) => {
 }
 .content-section {
   display: flex;
-  gap: 50px;
   align-items: center;
   justify-content: space-between;
+  width: 100%;
   margin-top: 20px;
   margin-bottom: 50px;
 }
@@ -634,6 +642,19 @@ const getStatusText = (status: string) => {
   border-radius: 8px;
   box-shadow: 0 2px 12px rgb(0 0 0 / 10%);
 }
+.empty-image-box {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 100%;
+  height: 100%;
+  background-color: var(--el-fill-color-lighter);
+  border-radius: 8px;
+  .empty-icon {
+    font-size: 64px;
+    color: var(--el-text-color-placeholder);
+  }
+}
 .empty-license {
   display: flex;
   align-items: center;

+ 30 - 0
src/views/login/index.vue

@@ -610,6 +610,7 @@ import {
   registerAccount,
   registerCheck
 } from "@/api/modules/newLoginApi";
+import { getMerchantByPhone } from "@/api/modules/homeEntry";
 import { localGet, localRemove, localSet } from "@/utils";
 import * as path from "node:path";
 import { checkMenuClickPermission } from "@/utils/permission";
@@ -929,6 +930,35 @@ const handleLogin = async () => {
         } else {
           localRemove("businessSection");
         }
+
+        // 登录成功后,立即获取完整的用户信息(包括头像)
+        if (res.data.phone) {
+          try {
+            const merchantRes: any = await getMerchantByPhone({ phone: res.data.phone });
+            if (merchantRes && merchantRes.code == 200 && merchantRes.data) {
+              // 更新用户信息到本地存储
+              const updatedUserInfo = {
+                ...userInfo,
+                userInfo: {
+                  ...userInfo.userInfo,
+                  ...merchantRes.data
+                }
+              };
+              localSet("geeker-user", updatedUserInfo);
+              userStore.setUserInfo(updatedUserInfo.userInfo);
+
+              // 如果有头像,缓存头像URL
+              const avatarUrl = merchantRes.data.headImg || merchantRes.data.avatar || "";
+              if (avatarUrl && avatarUrl.trim() !== "") {
+                localSet(`avatar_${res.data.phone}`, avatarUrl);
+              }
+            }
+          } catch (error) {
+            console.error("获取用户信息失败:", error);
+            // 即使获取失败,也不影响登录流程
+          }
+        }
+
         sessionStorage.removeItem("ticketManagement_activeName");
         await initDynamicRouter();