Kaynağa Gözat

Merge branch 'development' into uat

LuTong 1 ay önce
ebeveyn
işleme
2f205a040c
52 değiştirilmiş dosya ile 17542 ekleme ve 410 silme
  1. 3 1
      .env.development
  2. 5 0
      .env.production
  3. 672 0
      src/api/modules/aiImageUpload.ts
  4. 64 0
      src/api/modules/businessInfo.ts
  5. 1 1
      src/api/modules/contractManagement.ts
  6. 112 74
      src/api/modules/newLoginApi.ts
  7. 1 1
      src/api/modules/scheduledService.ts
  8. 11 2
      src/api/modules/storeDecoration.ts
  9. 7 2
      src/api/modules/upload.ts
  10. 23 2
      src/api/upload.js
  11. 4 0
      src/assets/images/aliIcon.svg
  12. 4 0
      src/assets/images/wechartIcon.svg
  13. BIN
      src/assets/images/yyzz.jpg
  14. 185 16
      src/assets/json/authMenuList.json
  15. 3422 0
      src/assets/json/city.json
  16. 15 9
      src/components/Upload/Imgs.vue
  17. 6 20
      src/stores/modules/auth.ts
  18. 8 0
      src/typings/global.d.ts
  19. 29 0
      src/utils/commonCommentList.ts
  20. 20 0
      src/utils/config.ts
  21. 7 7
      src/views/accountRoleManagement/roleManagement/create.vue
  22. 31 21
      src/views/appoinmentManagement/appoinmentInfo.vue
  23. 7 4
      src/views/appoinmentManagement/classifyManagement.vue
  24. 6 1
      src/views/appoinmentManagement/tableManagement.vue
  25. 2 2
      src/views/businessData/compare.vue
  26. 493 0
      src/views/businessInfo/accountInfo.vue
  27. 461 0
      src/views/businessInfo/adminInfo.vue
  28. 4383 0
      src/views/businessInfo/category.json
  29. 154 0
      src/views/businessInfo/createApply.vue
  30. 356 0
      src/views/businessInfo/dataEntry.vue
  31. 257 0
      src/views/businessInfo/industryQualifications.vue
  32. 1114 0
      src/views/businessInfo/manageInfo.vue
  33. 1149 0
      src/views/businessInfo/subjectInfo.vue
  34. 266 0
      src/views/businessInfo/weChartExamine.vue
  35. 15 0
      src/views/businessInfo/weChartIndex.vue
  36. 253 0
      src/views/businessInfo/zfbExamine.vue
  37. 2458 0
      src/views/businessInfo/zfbIndex.vue
  38. 928 0
      src/views/businessInfo/zfbIndexTwo.vue
  39. 30 26
      src/views/dynamicManagement/index.vue
  40. 23 24
      src/views/dynamicManagement/myDynamic.vue
  41. 1 1
      src/views/dynamicManagement/reviewAppeal.vue
  42. 23 22
      src/views/dynamicManagement/userDynamic.vue
  43. 220 3
      src/views/home/components/go-flow.vue
  44. 14 14
      src/views/operationManagement/activityList.vue
  45. 52 16
      src/views/operationManagement/newActivity.vue
  46. 11 1
      src/views/storeDecoration/basicStoreInformation/index.vue
  47. 0 1
      src/views/storeDecoration/businessHours/index.vue
  48. 37 24
      src/views/storeDecoration/officialPhotoAlbum/index.vue
  49. 45 22
      src/views/storeDecoration/personnelConfig/index.vue
  50. 70 43
      src/views/storeDecoration/storeHeadMap/index.vue
  51. 80 46
      src/views/storeDecoration/storeLabel/index.vue
  52. 4 4
      src/views/ticketManagement/index.vue

+ 3 - 1
.env.development

@@ -24,7 +24,9 @@ VITE_API_URL_PLATFORM = /api/alienStorePlatform
 
 
 # 开发环境跨域代理,支持配置多个
 # 开发环境跨域代理,支持配置多个
 # VITE_PROXY = [["/api","https://api.ailien.shop"]] #生产环境
 # VITE_PROXY = [["/api","https://api.ailien.shop"]] #生产环境
-VITE_PROXY = [["/api","http://120.26.186.130:8000"]] # 邹建宇
+# /ai-upload、/ai-moderate 供 Tus 上传与 AI 审核(见 src/utils/config.ts、src/api/modules/aiImageUpload.ts)
+# 图片上传默认走 AI 审核;若需恢复仅 OSS/uploadMore,设置 VITE_UPLOAD_IMAGE_AI_MODERATE=false
+VITE_PROXY = [["/api","http://120.26.186.130:8000"],["/ai-upload","https://upload.ailien.shop:8443"],["/ai-moderate","https://verify.ailien.shop:8444"]] # 邹建宇
 
 
 
 
 # WebSocket 基础地址(分享等能力,与商家端一致)
 # WebSocket 基础地址(分享等能力,与商家端一致)

+ 5 - 0
.env.production

@@ -37,6 +37,11 @@ VITE_PROXY = [["/alienStore","http://120.26.186.130:8000/alienStore"]]
 # AI接口
 # AI接口
 VITE_PROXY_AI = [["/ai-api","http://124.93.18.180:9000"]]
 VITE_PROXY_AI = [["/ai-api","http://124.93.18.180:9000"]]
 
 
+# Tus 上传与内容审核(生产构建默认见 src/utils/config.ts;同源反代时可覆盖)
+# VITE_AI_UPLOAD_BASE = https://upload.ailien.shop:8443
+# VITE_AI_MODERATE_BASE = https://verify.ailien.shop:8444
+# VITE_AI_FILES_PUBLIC_BASE = https://upload.ailien.shop:8443/files
+
 # 接口加密配置
 # 接口加密配置
 # 加密功能总开关
 # 加密功能总开关
 VITE_API_ENCRYPTION_ENABLED = false
 VITE_API_ENCRYPTION_ENABLED = false

+ 672 - 0
src/api/modules/aiImageUpload.ts

@@ -0,0 +1,672 @@
+/**
+ * Web 端:Tus 分片上传 + AI 图片审核(与 Apifox / uni 版协议对齐)
+ */
+import { useUserStore } from "@/stores/modules/user";
+import { ResultEnum } from "@/enums/httpEnum";
+import { AI_UPLOAD_FILES_PUBLIC_BASE, BASE_AI_MODERATE_URL, BASE_AI_URL } from "@/utils/config";
+
+const TUS_VERSION = "1.0.0";
+const TUS_CHUNK_SIZE = 1024 * 1024;
+
+const DEFAULT_MODERATE_USER_TIP = "图片未通过内容审核,请更换后重试";
+
+function authHeader(): string {
+  try {
+    return useUserStore().token || "";
+  } catch {
+    return "";
+  }
+}
+
+function mapModerateReasonToUserMessage(raw?: string | null): string {
+  const s = raw == null ? "" : String(raw).trim();
+  if (!s) return DEFAULT_MODERATE_USER_TIP;
+
+  if (/赌|赌博|casino|gambl/i.test(s)) return "图片涉及赌博等违规内容,请更换后重试";
+  if (/色情|淫秽|porn|sex/i.test(s)) return "图片涉及色情等违规内容,请更换后重试";
+  if (/暴力|血腥|violence|gore/i.test(s)) return "图片涉及暴力等违规内容,请更换后重试";
+  if (/辱骂|谩骂|人身攻击|abuse|insult/i.test(s)) return "图片涉及不文明内容,请更换后重试";
+  if (/政治|谣言/i.test(s)) return "图片涉及违规信息,请更换后重试";
+  if (/广告|spam|营销/i.test(s)) return "图片涉及违规推广内容,请更换后重试";
+  if (/违法|违禁|illegal/i.test(s)) return "图片含违法违规内容,请更换后重试";
+  if (/黄赌毒/i.test(s)) return "请勿上传涉黄、涉赌、涉毒等违规内容";
+  if (/审核|moderat|vlm|violation|flagged/i.test(s)) return DEFAULT_MODERATE_USER_TIP;
+
+  return DEFAULT_MODERATE_USER_TIP;
+}
+
+function pickPayload(res: unknown): unknown {
+  if (res == null) return null;
+  if (typeof res === "object" && !Array.isArray(res) && (res as any).data !== undefined) {
+    return (res as any).data;
+  }
+  return res;
+}
+
+function headerGet(headers: Headers, name: string): string {
+  const v = headers.get(name) || headers.get(name.toLowerCase());
+  return v ? String(v).trim() : "";
+}
+
+function pickUploadIdFromLocation(loc: string): string {
+  if (!loc) return "";
+  const m = String(loc).match(/\/files\/([^/?#]+)/);
+  return m ? decodeURIComponent(m[1]) : "";
+}
+
+export function pickUploadIdFromResponse(res: Response, body?: unknown): string {
+  const h = res.headers;
+  const idHdr = headerGet(h, "upload-id") || headerGet(h, "x-upload-id");
+  if (idHdr) return idHdr;
+  const fromLoc = pickUploadIdFromLocation(headerGet(h, "location"));
+  if (fromLoc) return fromLoc;
+
+  const d = pickPayload(body ?? null);
+  const inner = d && typeof d === "object" && (d as any).data !== undefined ? (d as any).data : d;
+  const x = inner && typeof inner === "object" ? (inner as Record<string, unknown>) : {};
+  const id =
+    (x.upload_id as string) || (x.uploadId as string) || (x.id as string) || (typeof inner === "string" ? inner : "") || "";
+  return id || "";
+}
+
+function pickFileUrlFromBody(body: unknown): string {
+  const fromObj = (o: unknown): string => {
+    if (!o || typeof o !== "object" || Array.isArray(o)) return "";
+    const r = o as Record<string, string>;
+    return r.url || r.file_url || r.fileUrl || r.access_url || r.accessUrl || r.ossUrl || r.cdnUrl || "";
+  };
+  const d = pickPayload(body);
+  let inner = d && typeof d === "object" && (d as any).data !== undefined ? (d as any).data : d;
+  let u = fromObj(inner);
+  if (u) return u;
+  if (inner && typeof inner === "object" && (inner as any).data !== undefined) {
+    u = fromObj((inner as any).data);
+  }
+  if (u) return u;
+  if (typeof inner === "string" && inner.startsWith("http")) return inner;
+  return typeof d === "string" && d.startsWith("http") ? d : "";
+}
+
+/** 创建上传会话 POST /upload */
+export async function createUploadSession(data: {
+  filename: string;
+  size: number;
+}): Promise<{ response: Response; body: unknown }> {
+  const res = await fetch(`${BASE_AI_URL}/upload`, {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+      "Tus-Resumable": TUS_VERSION,
+      Authorization: authHeader()
+    },
+    body: JSON.stringify(data)
+  });
+  let body: unknown = null;
+  const ct = res.headers.get("content-type") || "";
+  if (ct.includes("application/json")) {
+    try {
+      body = await res.json();
+    } catch {
+      body = null;
+    }
+  } else {
+    const t = await res.text();
+    body = t || null;
+  }
+  if (res.status < 200 || res.status >= 300) {
+    const msg =
+      body && typeof body === "object" && (body as any).message
+        ? String((body as any).message)
+        : `创建上传会话失败(${res.status})`;
+    throw new Error(msg);
+  }
+  if (body && typeof body === "object" && (body as any).code !== undefined) {
+    const c = (body as any).code;
+    if (c !== 200 && c !== 0) {
+      throw new Error((body as any).msg || (body as any).message || "创建上传会话失败");
+    }
+  }
+  return { response: res, body };
+}
+
+/** PATCH 二进制分片 */
+export async function patchBinaryToUpload(uploadId: string, arrayBuffer: ArrayBuffer, uploadOffset = 0): Promise<Response> {
+  const url = `${BASE_AI_URL}/files/${encodeURIComponent(uploadId)}`;
+  const res = await fetch(url, {
+    method: "PATCH",
+    headers: {
+      Authorization: authHeader(),
+      "Tus-Resumable": TUS_VERSION,
+      "Content-Type": "application/offset+octet-stream",
+      "Upload-Offset": String(uploadOffset)
+    },
+    body: arrayBuffer
+  });
+  if (res.status >= 200 && res.status < 300) {
+    return res;
+  }
+  const t = await res.text().catch(() => "");
+  throw new Error(`上传失败(${res.status})${t ? ` ${t.slice(0, 200)}` : ""}`);
+}
+
+export async function patchBinaryToUploadChunked(
+  uploadId: string,
+  arrayBuffer: ArrayBuffer,
+  onProgress?: (ratio: number) => void
+): Promise<void> {
+  const total = arrayBuffer.byteLength;
+  if (total === 0) {
+    await patchBinaryToUpload(uploadId, new ArrayBuffer(0), 0);
+    onProgress?.(1);
+    return;
+  }
+  let offset = 0;
+  while (offset < total) {
+    const end = Math.min(offset + TUS_CHUNK_SIZE, total);
+    const chunk = arrayBuffer.slice(offset, end);
+    await patchBinaryToUpload(uploadId, chunk, offset);
+    offset = end;
+    onProgress?.(offset / total);
+  }
+}
+
+/** HEAD /files/{id} */
+export async function getUploadProgress(uploadId: string): Promise<Response> {
+  return fetch(`${BASE_AI_URL}/files/${encodeURIComponent(uploadId)}`, {
+    method: "HEAD",
+    headers: {
+      Authorization: authHeader(),
+      "Tus-Resumable": TUS_VERSION,
+      "Content-Type": "application/octet-stream"
+    }
+  });
+}
+
+/** DELETE /files/{id} */
+export async function deleteUploadSession(uploadId: string): Promise<void> {
+  await fetch(`${BASE_AI_URL}/files/${encodeURIComponent(uploadId)}`, {
+    method: "DELETE",
+    headers: {
+      Authorization: authHeader(),
+      "Tus-Resumable": TUS_VERSION
+    }
+  });
+}
+
+/** POST /upload/{id}/finalize */
+export async function finalizeUploadSession(uploadId: string, data: Record<string, unknown> = {}): Promise<unknown> {
+  const res = await fetch(`${BASE_AI_URL}/upload/${encodeURIComponent(uploadId)}/finalize`, {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json",
+      "Tus-Resumable": TUS_VERSION,
+      Authorization: authHeader()
+    },
+    body: JSON.stringify(data)
+  });
+  let body: unknown = null;
+  const ct = res.headers.get("content-type") || "";
+  if (ct.includes("application/json")) {
+    try {
+      body = await res.json();
+    } catch {
+      body = null;
+    }
+  } else {
+    body = await res.text();
+  }
+  if (res.status < 200 || res.status >= 300) {
+    throw new Error(`上传完成确认失败(${res.status})`);
+  }
+  if (body && typeof body === "object" && (body as any).code !== undefined) {
+    const c = (body as any).code;
+    if (c !== 200 && c !== 0) {
+      throw new Error((body as any).msg || (body as any).message || "上传完成确认失败");
+    }
+  }
+  return body;
+}
+
+export interface ModerateImageParams {
+  text?: string;
+  image_urls?: string | string[];
+  file?: File | null;
+}
+
+/** POST multipart /api/v1/moderate,文件字段名 files */
+export async function moderateImage(params: ModerateImageParams = {}): Promise<any> {
+  const urlsStr = Array.isArray(params.image_urls)
+    ? params.image_urls.filter(Boolean).join(",")
+    : String(params.image_urls ?? "");
+
+  const fd = new FormData();
+  fd.append("text", String(params.text ?? ""));
+  fd.append("image_urls", urlsStr);
+  if (params.file) {
+    fd.append("files", params.file, params.file.name);
+  }
+
+  const res = await fetch(`${BASE_AI_MODERATE_URL}/api/v1/moderate`, {
+    method: "POST",
+    headers: {
+      Authorization: authHeader()
+    },
+    body: fd
+  });
+
+  let body: any = null;
+  const ct = res.headers.get("content-type") || "";
+  if (ct.includes("application/json")) {
+    try {
+      body = await res.json();
+    } catch {
+      body = null;
+    }
+  } else {
+    const t = await res.text();
+    try {
+      body = t ? JSON.parse(t) : null;
+    } catch {
+      body = { raw: t };
+    }
+  }
+
+  if (res.status < 200 || res.status >= 300) {
+    throw new Error(`审核请求失败(${res.status})`);
+  }
+  if (body && typeof body === "object" && body.code !== undefined && body.code !== 200 && body.code !== 0) {
+    throw new Error(body.msg || body.message || "审核请求失败");
+  }
+  return body;
+}
+
+export interface ModerateVideoParams {
+  /** 可选;与图片同一套 Tus 上传后应只传 `video_url`,不在此再传文件 */
+  file?: File | null;
+  filePath?: string;
+  path?: string;
+  /** 服务端视频地址,无 Tus 时可传空字符串 */
+  video_path?: string;
+  /** 标题/简介等 */
+  text?: string;
+  /** 远程 http(s) 视频地址 */
+  video_url?: string;
+}
+
+/**
+ * 仅提交「已上传视频」的审核任务:POST `/api/v1/video/submit`
+ * 与图片共用 Tus 上传拿到地址后,传 `video_url`;`getVideoModerateResult` 查询审核进度/结果。
+ */
+export async function moderateVideo(params: ModerateVideoParams = {}): Promise<any> {
+  const fd = new FormData();
+  fd.append("video_path", String(params.video_path ?? ""));
+  fd.append("text", String(params.text ?? ""));
+  fd.append("video_url", String(params.video_url ?? ""));
+
+  const file = params.file ?? null;
+  if (file) {
+    fd.append("file", file, file.name);
+  }
+
+  const res = await fetch(`${BASE_AI_MODERATE_URL}/api/v1/video/submit`, {
+    method: "POST",
+    headers: {
+      Authorization: authHeader()
+    },
+    body: fd
+  });
+
+  let body: any = null;
+  const ct = res.headers.get("content-type") || "";
+  if (ct.includes("application/json")) {
+    try {
+      body = await res.json();
+    } catch {
+      body = null;
+    }
+  } else {
+    const t = await res.text();
+    try {
+      body = t ? JSON.parse(t) : null;
+    } catch {
+      body = { raw: t };
+    }
+  }
+
+  if (res.status < 200 || res.status >= 300) {
+    throw new Error(`视频审核提交失败(${res.status})`);
+  }
+  if (body && typeof body === "object" && body.code !== undefined && body.code !== 200 && body.code !== 0) {
+    throw new Error(body.msg || body.message || "视频审核提交失败");
+  }
+  return body;
+}
+
+/**
+ * 查询视频审核进度与结果:GET `/api/v1/video/status/{task_id}`
+ * @param data.task_id 或传入字符串即 task_id
+ */
+export async function getVideoModerateResult(data: { task_id?: string } | string): Promise<any> {
+  const taskId = typeof data === "string" ? data : String(data?.task_id ?? "").trim();
+  if (!taskId) {
+    throw new Error("缺少 task_id");
+  }
+
+  const res = await fetch(`${BASE_AI_MODERATE_URL}/api/v1/video/status/${encodeURIComponent(taskId)}`, {
+    method: "GET",
+    headers: {
+      Authorization: authHeader()
+    }
+  });
+
+  let body: any = null;
+  const ct = res.headers.get("content-type") || "";
+  if (ct.includes("application/json")) {
+    try {
+      body = await res.json();
+    } catch {
+      body = null;
+    }
+  } else {
+    const t = await res.text();
+    try {
+      body = t ? JSON.parse(t) : null;
+    } catch {
+      body = { raw: t };
+    }
+  }
+
+  if (res.status < 200 || res.status >= 300) {
+    throw new Error(`查询视频审核状态失败(${res.status})`);
+  }
+  if (body && typeof body === "object" && body.code !== undefined && body.code !== 200 && body.code !== 0) {
+    throw new Error(body.msg || body.message || "查询视频审核状态失败");
+  }
+  return body;
+}
+
+function mapVideoModerateReasonToUserMessage(raw?: string | null): string {
+  return mapModerateReasonToUserMessage(raw).replace(/图片/g, "视频");
+}
+
+function pickVideoTaskIdFromSubmit(res: unknown): string {
+  const r = res as Record<string, any> | null | undefined;
+  if (!r || typeof r !== "object") return "";
+  let cur: any = r.data !== undefined ? r.data : r;
+  if (cur && typeof cur === "object" && cur.data !== undefined) cur = cur.data;
+  if (cur && typeof cur === "object") {
+    return String(cur.task_id ?? cur.taskId ?? cur.taskID ?? "").trim();
+  }
+  return "";
+}
+
+function flattenVideoStatusPayload(body: Record<string, any>): Record<string, any> {
+  const d = body?.data;
+  if (d && typeof d === "object" && !Array.isArray(d)) {
+    return { ...body, ...d };
+  }
+  return body;
+}
+
+function isVideoModerationStatusTerminal(payload: Record<string, any>): boolean {
+  const p = flattenVideoStatusPayload(payload);
+  const s = String(p?.status ?? p?.state ?? "").toLowerCase();
+  const terminal = [
+    "completed",
+    "complete",
+    "success",
+    "succeeded",
+    "done",
+    "finished",
+    "failed",
+    "fail",
+    "rejected",
+    "error",
+    "cancelled",
+    "canceled"
+  ];
+  if (terminal.includes(s)) return true;
+  const r = p?.result;
+  if (r && typeof r === "object" && (r.flagged !== undefined || r.passed !== undefined || r.approved !== undefined)) {
+    return true;
+  }
+  return false;
+}
+
+function isVideoModerationRejectedPayload(payload: Record<string, any>): boolean {
+  const p = flattenVideoStatusPayload(payload);
+  if (p?.flagged === true) return true;
+  const r = p?.result;
+  if (r && typeof r === "object" && r.flagged === true) return true;
+  const s = String(p?.status ?? "").toLowerCase();
+  if (["failed", "fail", "rejected", "error"].includes(s)) return true;
+  return false;
+}
+
+function pickVideoRejectReason(payload: Record<string, any>): string | null {
+  const p = flattenVideoStatusPayload(payload);
+  const r = p?.result;
+  const fromResult = r && typeof r === "object" ? (r.reason ?? r.message) : null;
+  const raw = fromResult ?? p?.reason ?? p?.message ?? p?.msg;
+  return raw != null && typeof raw === "string" ? raw : null;
+}
+
+/**
+ * 是否为视频(MIME 或后缀)。上传与图片同走 Tus;通过后以 `moderateVideo({ video_url })` + 轮询区分审核链路。
+ */
+export function isLikelyVideoFileForAiUpload(file: File): boolean {
+  if (!(file instanceof File)) return false;
+  if (typeof file.type === "string" && file.type.startsWith("video/")) return true;
+  const n = file.name || "";
+  return /\.(mp4|m4v|webm|ogg|mov)(\?.*)?$/i.test(n);
+}
+
+/**
+ * Tus 上传 → finalize → 返回公网 URL(图片/视频同一套上传;不含审核)
+ */
+async function uploadViaTusToPublicUrl(file: File, onProgress?: (p: number) => void): Promise<string> {
+  const report = (n: number) => onProgress?.(Math.min(100, Math.max(0, Math.round(n))));
+  report(5);
+  const buf = await file.arrayBuffer();
+  const size = buf.byteLength;
+  report(18);
+
+  const defaultName = isLikelyVideoFileForAiUpload(file) ? `video_${Date.now()}.mp4` : `img_${Date.now()}.jpg`;
+  const { response: sessionRes, body: sessionBody } = await createUploadSession({
+    filename: file.name || defaultName,
+    size
+  });
+  const uploadId = pickUploadIdFromResponse(sessionRes, sessionBody);
+  if (!uploadId) {
+    throw new Error("创建上传会话失败:未返回 upload_id");
+  }
+
+  const publicUrl = `${AI_UPLOAD_FILES_PUBLIC_BASE}/${uploadId}`;
+
+  report(35);
+  await patchBinaryToUploadChunked(uploadId, buf, ratio => {
+    report(35 + ratio * (82 - 35));
+  });
+  report(82);
+
+  const finalizeBody = await finalizeUploadSession(uploadId, {});
+  report(90);
+
+  const urlFromApi = pickFileUrlFromBody(finalizeBody);
+  const fileUrl = urlFromApi || publicUrl;
+  if (!fileUrl) {
+    throw new Error("上传完成确认失败:未返回文件地址");
+  }
+  return fileUrl;
+}
+
+/**
+ * Tus 已得到视频 URL:`moderateVideo` 仅提交审核(video_url),`getVideoModerateResult` 轮询至结束。
+ */
+async function submitAndAwaitVideoModeration(fileUrl: string, onProgress?: (p: number) => void): Promise<void> {
+  const report = (n: number) => onProgress?.(Math.min(100, Math.max(0, Math.round(n))));
+  const submitRes: any = await moderateVideo({ video_url: fileUrl, text: "", video_path: "" });
+  report(92);
+  const taskId = pickVideoTaskIdFromSubmit(submitRes);
+  const submitFlat =
+    submitRes && typeof submitRes === "object" ? flattenVideoStatusPayload(submitRes as Record<string, any>) : {};
+
+  if (!taskId) {
+    if (isVideoModerationStatusTerminal(submitFlat)) {
+      if (isVideoModerationRejectedPayload(submitFlat)) {
+        throw new Error(mapVideoModerateReasonToUserMessage(pickVideoRejectReason(submitFlat)));
+      }
+      return;
+    }
+    const c = submitRes?.code;
+    if (c === 200 || c === 0) return;
+    throw new Error("视频审核提交未返回任务信息,请稍后重试");
+  }
+
+  const maxMs = 5 * 60 * 1000;
+  const step = 2000;
+  const t0 = Date.now();
+  let pollCount = 0;
+  while (Date.now() - t0 < maxMs) {
+    const raw: any = await getVideoModerateResult(taskId);
+    const flat = raw && typeof raw === "object" ? flattenVideoStatusPayload(raw as Record<string, any>) : {};
+    pollCount += 1;
+    report(Math.min(98, 92 + Math.min(6, pollCount)));
+
+    if (isVideoModerationStatusTerminal(flat)) {
+      if (isVideoModerationRejectedPayload(flat)) {
+        throw new Error(mapVideoModerateReasonToUserMessage(pickVideoRejectReason(flat)));
+      }
+      return;
+    }
+    await new Promise<void>(resolve => setTimeout(resolve, step));
+  }
+  throw new Error("视频审核等待超时,请稍后重试");
+}
+
+export interface UploadFileViaAiOptions {
+  /** 0~100 */
+  onProgress?: (progress: number) => void;
+  /** 为 true 时跳过审核(仅上传) */
+  skipModerate?: boolean;
+}
+
+/**
+ * 图片与视频均:Tus 上传 → finalize 得同一套访问 URL。
+ * 图片再 `moderateImage`;视频再 `moderateVideo({ video_url })` + `getVideoModerateResult` 轮询。`skipModerate` 则只上传不审。
+ */
+export async function uploadFileViaAi(file: File, options: UploadFileViaAiOptions = {}): Promise<string> {
+  const { onProgress, skipModerate } = options;
+
+  const report = (p: number) => {
+    onProgress?.(Math.min(100, Math.max(0, Math.round(p))));
+  };
+
+  try {
+    const fileUrl = await uploadViaTusToPublicUrl(file, onProgress);
+
+    if (!skipModerate) {
+      if (isLikelyVideoFileForAiUpload(file)) {
+        await submitAndAwaitVideoModeration(fileUrl, onProgress);
+      } else {
+        const moderateRes = await moderateImage({
+          text: "",
+          image_urls: fileUrl,
+          file
+        });
+        const first = moderateRes?.results?.[0];
+        if (first?.flagged) {
+          if (first.reason) console.warn("[AI审核]", first.reason);
+          throw new Error(mapModerateReasonToUserMessage(first.reason));
+        }
+      }
+    }
+
+    report(100);
+    return fileUrl;
+  } catch (e) {
+    throw e;
+  }
+}
+
+/** 与 /file/uploadMore 成功态兼容,供 Upload 组件、http 封装统一消费 */
+export type UploadMoreLikeResponse = {
+  code: number;
+  msg: string;
+  data: { fileUrl: string };
+  /** 部分组件直接读顶层 fileUrl */
+  fileUrl: string;
+};
+
+export function isAiImageModerationEnabled(): boolean {
+  return import.meta.env.VITE_UPLOAD_IMAGE_AI_MODERATE !== "false";
+}
+
+/** 图/视频均 Tus 上传;图 moderateImage、视频 moderateVideo(url)+轮询;返回与 uploadMore 相近结构 */
+export async function uploadImageAsUploadMoreResponse(file: File): Promise<UploadMoreLikeResponse> {
+  const fileUrl = await uploadFileViaAi(file);
+  return {
+    code: ResultEnum.SUCCESS,
+    msg: "success",
+    data: { fileUrl },
+    fileUrl
+  };
+}
+
+/**
+ * FormData 内含字段 `file` 且为图片或视频时走 Tus + 对应审核(图 moderateImage,视频 moderateVideo 的 video_url + 轮询),否则走原接口
+ */
+export function runUploadMoreWithOptionalAi<T = UploadMoreLikeResponse>(
+  params: FormData,
+  fallback: () => Promise<T>
+): Promise<T> {
+  if (!isAiImageModerationEnabled()) {
+    return fallback();
+  }
+  const file = params.get("file");
+  if (!(file instanceof File)) {
+    return fallback();
+  }
+  const isImage = typeof file.type === "string" && file.type.startsWith("image/");
+  const isVideo = isLikelyVideoFileForAiUpload(file);
+  if (isImage || isVideo) {
+    return uploadImageAsUploadMoreResponse(file) as Promise<T>;
+  }
+  return fallback();
+}
+
+/** 多文件顺序上传,整体进度 0~100 */
+export async function uploadFilesViaAi(files: File[], options: UploadFileViaAiOptions = {}): Promise<string[]> {
+  const list = files.filter(f => f instanceof File);
+  if (!list.length) return [];
+
+  const n = list.length;
+  const urls: string[] = [];
+  for (let i = 0; i < n; i++) {
+    const u = await uploadFileViaAi(list[i], {
+      ...options,
+      onProgress: p => {
+        const overall = (i / n) * 100 + (p / 100) * (100 / n);
+        options.onProgress?.(overall);
+      }
+    });
+    urls.push(u);
+  }
+  return urls;
+}
+
+/** 与 uni 版 aiApi 命名对齐的聚合对象,便于按需解构 */
+export const aiImageApi = {
+  createUploadSession: (data: { filename: string; size: number }) => createUploadSession(data),
+  patchBinaryToUpload,
+  getUploadProgress,
+  deleteUploadSession,
+  finalizeUploadSession,
+  moderateImage,
+  moderateVideo,
+  getVideoModerateResult,
+  uploadFileViaAi,
+  uploadFilesViaAi
+};
+
+export default aiImageApi;

+ 64 - 0
src/api/modules/businessInfo.ts

@@ -0,0 +1,64 @@
+import httpLogin from "@/api/indexApi";
+
+/**
+ * @name 商家信息
+ */
+
+// 营业执照上传
+export const getUpload = (params: any) => {
+  return httpLogin.post(`alienStore/payment/wechatPartner/v3/merchant/media/upload`, params);
+};
+
+export const getOcrRequestByBase64 = (params: any) => {
+  return httpLogin.post(`alienStore/ali/ocrRequestByBase64`, params);
+};
+
+/** POST,storeId 走 URL 查询参数,请求体为 JSON */
+export const applyment = (data: Record<string, unknown> | object, storeId: string | number) => {
+  return httpLogin.post(`alienStore/payment/wechatPartner/v3/applyment4sub/applyment`, data, {
+    params: { storeId },
+    headers: { "Content-Type": "application/json;charset=UTF-8" }
+  });
+};
+
+/** GET,storeId 为路径参数 */
+export const applymentExamine = (storeId: string | number) => {
+  const id = encodeURIComponent(String(storeId).trim());
+  return httpLogin.get(`alienStore/payment/wechatPartner/applyment/store/${id}`);
+};
+
+export const getPaymentApplyment = (applymentId: string | number) => {
+  const id = encodeURIComponent(String(applymentId).trim());
+  return httpLogin.get(`alienStore/payment/wechatPartner/v3/applyment4sub/applyment/applyment_id/${id}`);
+};
+
+/** 支付宝直付通图片上传:multipart,字段 image_type + image_content(二进制) */
+export interface UploadAlipayImageParams {
+  /** 图片格式扩展名,3~16 字符,如 jpg、png(支持 bmp、jpg、jpeg、png、gif) */
+  imageType: string;
+  /** 图片原始二进制流 */
+  imageContent: Blob | File;
+  storeId?: string | number | null;
+}
+
+export const uploadAlipayImage = (params: UploadAlipayImageParams, axiosConfig?: object) => {
+  const fd = new FormData();
+  const { imageType, imageContent, storeId } = params;
+  if (storeId !== undefined && storeId !== null && String(storeId).trim() !== "") {
+    fd.append("storeId", String(storeId));
+  }
+  fd.append("imageType", imageType);
+  fd.append("imageContent", imageContent);
+  return httpLogin.post(`alienStore/store/alipay/zft/image/upload`, fd, {
+    encrypt: false,
+    ...axiosConfig
+  });
+};
+
+export const getAlipayZftCreate = (params: any) => {
+  return httpLogin.post(`alienStore/store/alipay/zft/create`, params);
+};
+
+export const getAlipayExamine = (params: any) => {
+  return httpLogin.post(`alienStore/store/alipay/zft/order/query`, params);
+};

+ 1 - 1
src/api/modules/contractManagement.ts

@@ -10,7 +10,7 @@ import { LOGIN_URL } from "@/config";
 import router from "@/routers";
 import router from "@/routers";
 
 
 // 合同接口专用配置 - 使用不同的端口
 // 合同接口专用配置 - 使用不同的端口
-const CONTRACT_BASE_URL = "http://120.26.186.130:33333";
+const CONTRACT_BASE_URL = "https://120.26.186.130";
 
 
 // 创建专门用于合同接口的 axios 实例
 // 创建专门用于合同接口的 axios 实例
 // 注意:不使用 withCredentials,因为认证通过 Authorization header 传递,且服务器 CORS 配置为通配符
 // 注意:不使用 withCredentials,因为认证通过 Authorization header 传递,且服务器 CORS 配置为通配符

+ 112 - 74
src/api/modules/newLoginApi.ts

@@ -1,6 +1,7 @@
 import type { Login } from "@/api/interface";
 import type { Login } from "@/api/interface";
 import httpLogin from "@/api/indexApi";
 import httpLogin from "@/api/indexApi";
 import { Upload } from "@/api/interface/index";
 import { Upload } from "@/api/interface/index";
+import { runUploadMoreWithOptionalAi } from "@/api/modules/aiImageUpload";
 // 获取图片验证码
 // 获取图片验证码
 export const getImgCode = () => {
 export const getImgCode = () => {
   return httpLogin.get(
   return httpLogin.get(
@@ -61,9 +62,11 @@ export const getInputPrompt = params => {
 export const getDistrict = params => {
 export const getDistrict = params => {
   return httpLogin.get(`/alienStore/gaode/getDistrict`, params);
   return httpLogin.get(`/alienStore/gaode/getDistrict`, params);
 };
 };
-//文件上传
+//文件上传(图片默认走 Tus + AI 审核,可设 VITE_UPLOAD_IMAGE_AI_MODERATE=false 关闭)
 export const uploadImg = (params: FormData) => {
 export const uploadImg = (params: FormData) => {
-  return httpLogin.post<Upload.ResFileUrl>(`/alienStore/file/uploadMore`, params, { cancel: false });
+  return runUploadMoreWithOptionalAi(params, () =>
+    httpLogin.post<Upload.ResFileUrl>(`/alienStore/file/uploadMore`, params, { cancel: false })
+  );
 };
 };
 // 发布/更新动态(新接口)
 // 发布/更新动态(新接口)
 export const addOrUpdateDynamic = (params: {
 export const addOrUpdateDynamic = (params: {
@@ -208,86 +211,121 @@ export const addAppealNew = (params: FormData | Record<string, unknown>) => {
 };
 };
 
 
 // 动态-------------------------------------------------------------------------------------
 // 动态-------------------------------------------------------------------------------------
-/** 商家端 commonComment/addComment:发表评论/回复(评价回复 sourceType=1,动态评论 sourceType=2) */
-// 发表评论 - 表单形式提交(字符串键值对,非 JSON 对象)
-export const addComment = (data: {
-  commentContent: string;
-  businessType: number;
-  businessId: string | number;
-  storeId: string;
-  phoneId: string;
-  replyId: string;
-  commentStar: string;
-  multipartRequest: string;
-}) => {
-  const formData = new FormData();
-  formData.append("commentContent", data.commentContent);
-  formData.append("businessType", String(data.businessType));
-  formData.append("businessId", String(data.businessId));
-  formData.append("storeId", data.storeId);
-  formData.append("phoneId", data.phoneId);
-  formData.append("replyId", data.replyId);
-  formData.append("commentStar", data.commentStar);
-  formData.append("multipartRequest", data.multipartRequest);
-  return httpLogin.post(`/alienStore/storeComment/saveComment`, formData);
+/** commonComment/addComment 请求体(与接口模型一致;新增评论一般只传部分字段) */
+export interface AddCommonCommentBody {
+  auditReason?: string;
+  /** 0-待审核 1-通过 2-驳回 */
+  auditStatus?: number;
+  /** 1-用户评论 2-商户评论(仅回复) */
+  commentType?: number;
+  content?: string;
+  createdTime?: string;
+  /** 0-未删除 1-已删除 */
+  deleteFlag?: number;
+  extInfo?: string;
+  id?: number;
+  imageUrls?: string;
+  /** 0-否 1-是(仅用户评论生效) */
+  isAnonymous?: number;
+  /** 0-隐藏 1-展示 */
+  isShow?: number;
+  likeCount?: number;
+  /** commentType=2 时必填 */
+  merchantId?: number;
+  /** 0=根评论,>0=回复某条评论 */
+  parentId?: number;
+  replyCount?: number;
+  /** sourceType=1 rating.id;=2 动态ID;=3 打卡;=4 二手商品 */
+  sourceId?: number;
+  /** 1-评价的评论 2-动态 3-打卡 4-二手商品 */
+  sourceType?: number;
+  updatedTime?: string;
+  /** 用户=用户ID,商户=商户运营账号ID */
+  userId?: number;
+}
+
+function omitUndefinedRecord(obj: Record<string, unknown>): Record<string, unknown> {
+  return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined && v !== null));
+}
+
+/** 将可转为整型的 id 字段转为 number,无法转换则返回 undefined */
+function toInt64(v: unknown): number | undefined {
+  if (v === undefined || v === null || v === "") return undefined;
+  const n = Number(v);
+  return Number.isFinite(n) ? Math.trunc(n) : undefined;
+}
+
+function buildSaveCommentBody(params: any): AddCommonCommentBody {
+  const businessType = Number(params.businessType ?? 2);
+  const isRating = businessType === 1;
+  const sourceType = isRating ? 1 : 2;
+  const sourceIdRaw = isRating ? (params.replyId ?? params.businessId) : (params.businessId ?? params.sourceId);
+  const parentId = isRating ? 0 : Number(params.replyId || 0);
+  const merchantRaw = params.merchantId ?? params.storeId ?? (isRating ? params.businessId : undefined);
+
+  const body: AddCommonCommentBody = {
+    userId: toInt64(params.userId ?? params.phoneId),
+    sourceType,
+    sourceId: toInt64(sourceIdRaw),
+    parentId,
+    content: String(params.commentContent ?? params.content ?? ""),
+    commentType: Number(params.commentType ?? 2),
+    merchantId: toInt64(merchantRaw),
+    isAnonymous: params.isAnonymous !== undefined ? Number(params.isAnonymous) : 0
+  };
+
+  if (params.auditReason != null && params.auditReason !== "") body.auditReason = String(params.auditReason);
+  if (params.auditStatus !== undefined) body.auditStatus = Number(params.auditStatus);
+  if (params.createdTime) body.createdTime = String(params.createdTime);
+  if (params.deleteFlag !== undefined) body.deleteFlag = Number(params.deleteFlag);
+  if (params.extInfo != null && params.extInfo !== "") body.extInfo = String(params.extInfo);
+  if (params.id !== undefined && params.id !== null && params.id !== "") {
+    const idNum = toInt64(params.id);
+    if (idNum !== undefined) body.id = idNum;
+  }
+  if (params.imageUrls != null && params.imageUrls !== "") body.imageUrls = String(params.imageUrls);
+  if (params.isShow !== undefined) body.isShow = Number(params.isShow);
+  if (params.likeCount !== undefined) body.likeCount = Number(params.likeCount);
+  if (params.replyCount !== undefined) body.replyCount = Number(params.replyCount);
+  if (params.updatedTime) body.updatedTime = String(params.updatedTime);
+
+  return body;
+}
+
+/** 商家端 commonComment/addComment,请求体字段与接口一致 */
+export const addComment = (data: AddCommonCommentBody) => {
+  const raw: Record<string, unknown> = { ...data };
+  return httpLogin.post(`/alienStore/commonComment/addComment`, omitUndefinedRecord(raw));
 };
 };
 
 
 /**
 /**
- * 发表评论/回复(兼容旧参数,内部转为 addComment)
- * - 评价回复:businessType=1,replyId=评价ID → sourceType=1, sourceId=replyId, parentId=0
- * - 动态评论:businessType=2,businessId=动态ID,replyId 有值为回复评论ID → sourceType=2, sourceId=businessId, parentId=replyId||0
+ * 发表评论/回复(兼容旧入参:businessId、replyId、commentContent、phoneId/userId、businessType、storeId
+ * - businessType=1:评价相关,sourceType=1,sourceId 取 replyId/businessId,parentId=0
+ * - businessType=2:动态,sourceType=2,sourceId=动态 id,parentId=回复的评论 id 或 0
  */
  */
 export const saveComment = (params: any) => {
 export const saveComment = (params: any) => {
-  const businessType = Number(params.businessType ?? 0);
-  const isRating = businessType === 1;
-  const payload = {
-    commentContent: String(params.commentContent ?? params.content ?? ""),
-    businessType: 2,
-    businessId: isRating ? params.replyId : params.businessId,
-    storeId: String(params.storeId ?? ""),
-    phoneId: String(params.userId ?? params.phoneId ?? ""),
-    replyId: String(params.replyId ?? ""),
-    commentStar: "",
-    multipartRequest: ""
-  };
-  return addComment(payload);
+  return addComment(buildSaveCommentBody(params));
 };
 };
 
 
 // 评价-------------------------------------------------------------------------------------
 // 评价-------------------------------------------------------------------------------------
-export const addComment2 = (data: {
-  sourceType: number; // 1-评价的评论 2-动态等
-  sourceId: string | number; // 评价ID或动态ID
-  userId: string;
-  parentId: number; // 0-根评论
-  content: string;
-  commentType: number; // 2-商户评论
-  merchantId: string;
-  isAnonymous?: number;
-}) => {
-  return httpLogin.post(`/alienStore/commonComment/addComment`, {
-    ...data,
-    isAnonymous: data.isAnonymous ?? 0
-  });
-};
-export const saveComment2 = (params: any) => {
-  const businessType = Number(params.businessType ?? 0);
-  const isRating = businessType === 1;
-  const payload = {
-    sourceType: isRating ? 1 : 2,
-    sourceId: isRating ? params.replyId : params.businessId,
-    userId: String(params.userId ?? params.phoneId ?? ""),
-    parentId: isRating ? 0 : Number(params.replyId || 0),
-    content: String(params.commentContent ?? params.content ?? ""),
-    commentType: 2,
-    merchantId: String(params.merchantId ?? params.storeId ?? params.businessId ?? ""),
-    isAnonymous: 0
-  };
-  return addComment2(payload);
-};
-
-//评论列表
-export const commentList = (params: any) => {
-  return httpLogin.get(`/alienStore/storeComment/getList`, params);
+export const addComment2 = (data: AddCommonCommentBody) => addComment(data);
+
+export const saveComment2 = (params: any) => saveComment(params);
+
+/** 评论列表查询(getListBySourceType) */
+export interface CommentListParams {
+  pageNum: number;
+  pageSize: number;
+  /** 来源 id,如动态 id */
+  sourceId: number | string;
+  /** 1-评价 2-动态 3-打卡 4-二手商品 */
+  sourceType: number;
+  /** 可选,评论发布者/当前用户 id */
+  userId?: number;
+}
+
+export const commentList = (params: CommentListParams) => {
+  return httpLogin.get(`/alienStore/commonComment/getListBySourceType`, params);
 };
 };
 
 
 //我的动态
 //我的动态

+ 1 - 1
src/api/modules/scheduledService.ts

@@ -148,7 +148,7 @@ export const reservationCancel = (params: {
 };
 };
 
 
 /** 删除预约 */
 /** 删除预约 */
-export const reservationDelete = (params: { id: number | string }) => {
+export const reservationDelete = (params: { reservationId: number | string }) => {
   const formData = Object.keys(params)
   const formData = Object.keys(params)
     .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(String(params[key as keyof typeof params]))}`)
     .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(String(params[key as keyof typeof params]))}`)
     .join("&");
     .join("&");

+ 11 - 2
src/api/modules/storeDecoration.ts

@@ -3,6 +3,7 @@ import { PORT_NONE } from "@/api/config/servicePort";
 import http from "@/api";
 import http from "@/api";
 import httpApi from "@/api/indexApi";
 import httpApi from "@/api/indexApi";
 import { Upload } from "@/api/interface/index";
 import { Upload } from "@/api/interface/index";
+import { runUploadMoreWithOptionalAi } from "@/api/modules/aiImageUpload";
 
 
 /**
 /**
  * @name 商铺用户模块
  * @name 商铺用户模块
@@ -64,12 +65,16 @@ export const saveOrUpdateDecoration = (params: any) => {
 
 
 // 上传房屋图纸 - 使用 /alienStore/file/uploadMore 接口
 // 上传房屋图纸 - 使用 /alienStore/file/uploadMore 接口
 export const uploadDecorationImage = (params: FormData) => {
 export const uploadDecorationImage = (params: FormData) => {
-  return httpApi.post<Upload.ResFileUrl>(`/alienStore/file/uploadMore`, params, { cancel: false });
+  return runUploadMoreWithOptionalAi(params, () =>
+    httpApi.post<Upload.ResFileUrl>(`/alienStore/file/uploadMore`, params, { cancel: false })
+  );
 };
 };
 
 
 // 聊天图片/视频上传(与商家端一致,使用同一接口)
 // 聊天图片/视频上传(与商家端一致,使用同一接口)
 export const uploadChatFile = (params: FormData) => {
 export const uploadChatFile = (params: FormData) => {
-  return httpApi.post<Upload.ResFileUrl>(`/alienStore/file/uploadMore`, params, { cancel: false });
+  return runUploadMoreWithOptionalAi(params, () =>
+    httpApi.post<Upload.ResFileUrl>(`/alienStore/file/uploadMore`, params, { cancel: false })
+  );
 };
 };
 
 
 // 删除装修需求
 // 删除装修需求
@@ -200,6 +205,10 @@ export const importBarMenuExcel = (formData: FormData, storeId: string | number)
 export const getAllTagType = (params?: any) => {
 export const getAllTagType = (params?: any) => {
   return httpApi.get(`/alienStorePlatform/storePlatformTag/getBusinessRelationTagList`, params);
   return httpApi.get(`/alienStorePlatform/storePlatformTag/getBusinessRelationTagList`, params);
 };
 };
+/** 门店标签列表/数据:GET /alienStore/store/tag/getTagList */
+export const getTagList = (params?: Record<string, any>) => {
+  return httpApi.get(`/alienStore/store/tag/getTagList`, params, { loading: false });
+};
 //获取所有所选标签
 //获取所有所选标签
 export const getAllTag = (params: any) => {
 export const getAllTag = (params: any) => {
   return httpApi.get(`/alienStorePlatform/storePlatformTag/getTagStoreRelationByStoreId`, params);
   return httpApi.get(`/alienStorePlatform/storePlatformTag/getTagStoreRelationByStoreId`, params);

+ 7 - 2
src/api/modules/upload.ts

@@ -1,4 +1,5 @@
 import { Upload } from "@/api/interface/index";
 import { Upload } from "@/api/interface/index";
+import { runUploadMoreWithOptionalAi } from "@/api/modules/aiImageUpload";
 import { PORT1 } from "@/api/config/servicePort";
 import { PORT1 } from "@/api/config/servicePort";
 import { PORT_NONE } from "@/api/config/servicePort";
 import { PORT_NONE } from "@/api/config/servicePort";
 import httpStore from "@/api/indexStore";
 import httpStore from "@/api/indexStore";
@@ -48,12 +49,16 @@ httpStoreAlienStore.interceptors.response.use(
  */
  */
 // 图片上传(默认使用 alienStorePlatform)
 // 图片上传(默认使用 alienStorePlatform)
 export const uploadImg = (params: FormData) => {
 export const uploadImg = (params: FormData) => {
-  return httpStore.post<Upload.ResFileUrl>(PORT_NONE + `/file/uploadMore`, params, { cancel: false });
+  return runUploadMoreWithOptionalAi(params, () =>
+    httpStore.post<Upload.ResFileUrl>(PORT_NONE + `/file/uploadMore`, params, { cancel: false })
+  );
 };
 };
 
 
 // 图片上传(使用 alienStore 前缀,用于价目表等页面)
 // 图片上传(使用 alienStore 前缀,用于价目表等页面)
 export const uploadImgStore = (params: FormData) => {
 export const uploadImgStore = (params: FormData) => {
-  return httpStoreAlienStore.post<Upload.ResFileUrl>(PORT_NONE + `/file/uploadMore`, params, { cancel: false });
+  return runUploadMoreWithOptionalAi(params, () =>
+    httpStoreAlienStore.post<Upload.ResFileUrl>(PORT_NONE + `/file/uploadMore`, params, { cancel: false })
+  );
 };
 };
 
 
 // 视频上传
 // 视频上传

+ 23 - 2
src/api/upload.js

@@ -1,5 +1,6 @@
 import { useUserStore } from "@/stores/modules/user";
 import { useUserStore } from "@/stores/modules/user";
 import { ElMessage } from "element-plus";
 import { ElMessage } from "element-plus";
+import { isAiImageModerationEnabled, uploadFileViaAi, isLikelyVideoFileForAiUpload } from "@/api/modules/aiImageUpload";
 
 
 /**
 /**
  * 门店/文件相关接口基址(与 src/api/modules/upload.ts 中 httpStoreAlienStore 一致)
  * 门店/文件相关接口基址(与 src/api/modules/upload.ts 中 httpStoreAlienStore 一致)
@@ -113,7 +114,8 @@ async function postFileToOss(signRes, file, key) {
 }
 }
 
 
 /**
 /**
- * 上传文件到 OSS:先 GET 获取签名,再 POST 到 OSS host(与 src/api/1.js 逻辑一致,Web 使用 File / FormData)
+ * 上传文件:视频一律走 Tus + moderateVideo / 轮询(uploadFileViaAi),不走 OSS;
+ * 开启 AI 时图片走 Tus+审核,否则图片与其它类型走 OSS 直传。
  * @param {File | File[] | FileList} files 浏览器文件对象;支持单个 File、数组或 FileList
  * @param {File | File[] | FileList} files 浏览器文件对象;支持单个 File、数组或 FileList
  * @param {string} [fileType] 文件类型(如 'image' | 'video'),用于在文件名无后缀时推断格式
  * @param {string} [fileType] 文件类型(如 'image' | 'video'),用于在文件名无后缀时推断格式
  * @param {{ showLoading?: boolean }} [options] showLoading 为 true 时用 ElMessage 提示上传中(非阻塞)
  * @param {{ showLoading?: boolean }} [options] showLoading 为 true 时用 ElMessage 提示上传中(非阻塞)
@@ -133,11 +135,30 @@ export async function uploadFilesToOss(files, fileType, options = {}) {
   }
   }
 
 
   try {
   try {
-    const signRes = await fetchOssSignature();
+    let signRes = null;
     const uploadedUrls = [];
     const uploadedUrls = [];
+    const useAiImage = isAiImageModerationEnabled();
 
 
     for (let i = 0; i < fileArr.length; i++) {
     for (let i = 0; i < fileArr.length; i++) {
       const file = fileArr[i];
       const file = fileArr[i];
+      const isImageBranch = fileType === "image" || (!fileType && file.type && String(file.type).startsWith("image/"));
+      const isVideoBranch = fileType === "video" || isLikelyVideoFileForAiUpload(file);
+
+      if (isVideoBranch) {
+        const url = await uploadFileViaAi(file, { skipModerate: !useAiImage });
+        uploadedUrls.push(url);
+        continue;
+      }
+
+      if (useAiImage && isImageBranch) {
+        const url = await uploadFileViaAi(file);
+        uploadedUrls.push(url);
+        continue;
+      }
+
+      if (!signRes) {
+        signRes = await fetchOssSignature();
+      }
       const filePath = file.name || "";
       const filePath = file.name || "";
       const ext = getFileExtension(filePath, fileType);
       const ext = getFileExtension(filePath, fileType);
       const rawBase = filePath.split("/").pop() || "";
       const rawBase = filePath.split("/").pop() || "";

+ 4 - 0
src/assets/images/aliIcon.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="20" height="20" rx="4" fill="#3386FF"/>
+<path d="M10.5571 10.6307C4.93455 8.36098 3.27909 9.70237 2.82724 9.96026C-0.936511 12.6944 2.57633 15.7896 3.17853 15.9959C7.14401 16.9245 9.75374 15.1705 11.5108 13.0039C11.6613 13.1062 11.7115 13.1062 11.8119 13.1586C13.0165 13.8293 18.8891 16.6666 18.8891 16.6666V13.2618C17.9856 13.2618 14.8235 12.1269 12.4642 11.353C13.6688 9.08325 14.1207 6.91664 14.1207 6.91664H10.0552V5.31736H14.924V4.64667H10.0552V2.22217H7.84678V4.59509H3.42964V5.31736H7.84678V6.91664H4.08302V7.58734H11.6615M9.55321 12.3328C6.79253 15.9443 3.48082 14.8092 2.92761 14.6029C1.62264 14.1388 1.17079 11.7658 2.82724 10.992C5.58793 10.0634 8.04731 11.0943 9.80413 12.0237C9.72697 12.1321 9.64316 12.2353 9.55321 12.3328Z" fill="white"/>
+</svg>

+ 4 - 0
src/assets/images/wechartIcon.svg

@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="20" height="20" rx="4" fill="#04DC00"/>
+<path d="M9.1038 11.4409C8.37226 11.8425 8.26376 11.2155 8.26376 11.2155L7.34693 9.10871C6.99416 8.1076 7.65225 8.65732 7.65225 8.65732C7.65225 8.65732 8.21691 9.07797 8.64546 9.3343C9.07378 9.59063 9.562 9.40955 9.562 9.40955L15.5558 6.68528C14.4499 5.33031 12.6232 4.44434 10.5551 4.44434C7.18006 4.44434 4.44434 6.80212 4.44434 9.71077C4.44434 11.3838 5.35022 12.8728 6.76124 13.838L6.50677 15.2784C6.50677 15.2784 6.38273 15.6989 6.81264 15.5038C7.10558 15.3708 7.85241 14.8943 8.29697 14.6043C8.99586 14.8441 9.75728 14.9773 10.5555 14.9773C13.9303 14.9773 16.6666 12.6195 16.6666 9.71078C16.6666 8.86829 16.436 8.07265 16.0276 7.36643C14.1179 8.49784 9.67621 11.1272 9.1038 11.4409Z" fill="white"/>
+</svg>

BIN
src/assets/images/yyzz.jpg


+ 185 - 16
src/assets/json/authMenuList.json

@@ -410,7 +410,7 @@
           "component": "/storeDecoration/officialPhotoAlbum/index",
           "component": "/storeDecoration/officialPhotoAlbum/index",
           "meta": {
           "meta": {
             "icon": "Files",
             "icon": "Files",
-            "title": "官方相册",
+            "title": "相册",
             "isLink": "",
             "isLink": "",
             "isHide": false,
             "isHide": false,
             "isFull": false,
             "isFull": false,
@@ -1318,20 +1318,6 @@
           }
           }
         },
         },
         {
         {
-          "path": "/appoinmentManagement/appoinmentInfo",
-          "name": "appoinmentInfo",
-          "component": "/appoinmentManagement/appoinmentInfo",
-          "meta":{
-            "icon": "ChatDotSquare",
-            "title": "预定信息",
-            "isLink": "",
-            "isHide": false,
-            "isFull": false,
-            "isAffix": false,
-            "isKeepAlive": false
-          }
-        },
-        {
           "path": "/appoinmentManagement/infoManagement",
           "path": "/appoinmentManagement/infoManagement",
           "name": "infoManagement",
           "name": "infoManagement",
           "component": "/appoinmentManagement/infoManagement",
           "component": "/appoinmentManagement/infoManagement",
@@ -1347,7 +1333,7 @@
         }
         }
       ]
       ]
     },
     },
-     {
+      {
       "path": "/appoinmentManagement/appoinmentInfo",
       "path": "/appoinmentManagement/appoinmentInfo",
       "name": "appoinmentInfo",
       "name": "appoinmentInfo",
       "component": "/appoinmentManagement/appoinmentInfo",
       "component": "/appoinmentManagement/appoinmentInfo",
@@ -1360,7 +1346,190 @@
         "isAffix": false,
         "isAffix": false,
         "isKeepAlive": false
         "isKeepAlive": false
       }
       }
+    },{
+      "path": "/businessInfo",
+      "name": "businessInfo",
+      "component": "/businessInfo",
+      "meta":{
+        "icon": "ChatDotSquare",
+        "title": "设置收款账号",
+        "isLink": "",
+        "isHide": false,
+        "isFull": false,
+        "isAffix": false,
+        "isKeepAlive": false
+      },
+      "children": [
+        {
+          "path": "/businessInfo/weChartIndex",
+          "name": "/businessInfo/weChartIndex",
+          "component": "/businessInfo/weChartIndex",
+          "meta":{
+            "icon": "ChatDotSquare",
+            "title": "绑定微信账号",
+            "isLink": "",
+            "isHide": false,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+        {
+          "path": "/businessInfo/weChartExamine",
+          "name": "/businessInfo/weChartExamine",
+          "component": "/businessInfo/weChartExamine",
+          "meta":{
+            "icon": "ChatDotSquare",
+            "title": "查看微信审核状态",
+            "isLink": "",
+            "isHide": false,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+        {
+          "path": "/businessInfo/createApply",
+          "name": "/businessInfo/createApply",
+          "component": "/businessInfo/createApply",
+          "meta":{
+            "icon": "Document",
+            "title": "选择主体类型",
+            "isLink": "",
+            "isHide": true,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },{
+          "path": "/businessInfo/dataEntry",
+          "name": "/businessInfo/dataEntry",
+          "component": "/businessInfo/dataEntry",
+          "meta":{
+            "icon": "Document",
+            "title": "选择主体类型",
+            "isLink": "",
+            "isHide": true,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+        {
+          "path": "/businessInfo/subjectInfo",
+          "name": "/businessInfo/subjectInfo",
+          "component": "/businessInfo/subjectInfo",
+          "meta":{
+            "icon": "User",
+            "title": "主体信息",
+            "isLink": "",
+            "isHide": true,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+        {
+          "path": "/businessInfo/manageInfo",
+          "name": "/businessInfo/manageInfo",
+          "component": "/businessInfo/manageInfo",
+          "meta":{
+            "icon": "OfficeBuilding",
+            "title": "经营信息",
+            "isLink": "",
+            "isHide": true,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+        {
+          "path": "/businessInfo/industryQualifications",
+          "name": "/businessInfo/industryQualifications",
+          "component": "/businessInfo/industryQualifications",
+          "meta":{
+            "icon": "Document",
+            "title": "行业资质",
+            "isLink": "",
+            "isHide": true,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+        {
+          "path": "/businessInfo/accountInfo",
+          "name": "/businessInfo/accountInfo",
+          "component": "/businessInfo/accountInfo",
+          "meta":{
+            "icon": "Wallet",
+            "title": "结算账户",
+            "isLink": "",
+            "isHide": true,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+        {
+          "path": "/businessInfo/adminInfo",
+          "name": "/businessInfo/adminInfo",
+          "component": "/businessInfo/adminInfo",
+          "meta":{
+            "icon": "UserFilled",
+            "title": "超级管理员",
+            "isLink": "",
+            "isHide": true,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+         {
+          "path": "/businessInfo/zfbIndex",
+          "name": "/businessInfo/zfbIndex",
+          "component": "/businessInfo/zfbIndex",
+          "meta":{
+            "icon": "ChatDotSquare",
+            "title": "绑定支付宝账号",
+            "isLink": "",
+            "isHide": false,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+       {
+          "path": "/businessInfo/zfbIndexTwo",
+          "name": "/businessInfo/zfbIndexTwo",
+          "component": "/businessInfo/zfbIndexTwo",
+          "meta":{
+            "icon": "ChatDotSquare",
+            "title": "完善结算信息",
+            "isLink": "",
+            "isHide": true,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+        {
+          "path": "/businessInfo/zfbExamine",
+          "name": "/businessInfo/zfbExamine",
+          "component": "/businessInfo/zfbExamine",
+          "meta":{
+            "icon": "ChatDotSquare",
+            "title": "查看支付宝审核状态",
+            "isLink": "",
+            "isHide": false,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        }
+      ]
     }
     }
   ],
   ],
   "msg": "成功"
   "msg": "成功"
 }
 }
+

+ 3422 - 0
src/assets/json/city.json

@@ -0,0 +1,3422 @@
+{
+    "cityList": [
+        {
+            "letter": "A",
+            "list": [
+                {
+                    "name": "阿克苏市",
+                    "adCode": "652901",
+                    "cityCode": "0997"
+                },
+                {
+                    "name": "阿拉尔市",
+                    "adCode": "659002",
+                    "cityCode": "1997"
+                },
+                {
+                    "name": "阿拉山口市",
+                    "adCode": "652702",
+                    "cityCode": "0909"
+                },
+                {
+                    "name": "阿勒泰市",
+                    "adCode": "654301",
+                    "cityCode": "0906"
+                },
+                {
+                    "name": "阿图什市",
+                    "adCode": "653001",
+                    "cityCode": "0908"
+                },
+                {
+                    "name": "安达市",
+                    "adCode": "231281",
+                    "cityCode": "0455"
+                },
+                {
+                    "name": "安国市",
+                    "adCode": "130683",
+                    "cityCode": "0312"
+                },
+                {
+                    "name": "安康市",
+                    "adCode": "610900",
+                    "cityCode": "0915"
+                },
+                {
+                    "name": "安陆市",
+                    "adCode": "420982",
+                    "cityCode": "0712"
+                },
+                {
+                    "name": "安宁市",
+                    "adCode": "530181",
+                    "cityCode": "0871"
+                },
+                {
+                    "name": "安庆市",
+                    "adCode": "340800",
+                    "cityCode": "0556"
+                },
+                {
+                    "name": "安丘市",
+                    "adCode": "370784",
+                    "cityCode": "0536"
+                },
+                {
+                    "name": "安顺市",
+                    "adCode": "520400",
+                    "cityCode": "0853"
+                },
+                {
+                    "name": "安阳市",
+                    "adCode": "410500",
+                    "cityCode": "0372"
+                },
+                {
+                    "name": "鞍山市",
+                    "adCode": "210300",
+                    "cityCode": "0412"
+                }
+            ]
+        },
+        {
+            "letter": "B",
+            "list": [
+                {
+                    "name": "巴彦淖尔市",
+                    "adCode": "150800",
+                    "cityCode": "0478"
+                },
+                {
+                    "name": "巴中市",
+                    "adCode": "511900",
+                    "cityCode": "0827"
+                },
+                {
+                    "name": "霸州市",
+                    "adCode": "131081",
+                    "cityCode": "0316"
+                },
+                {
+                    "name": "白城市",
+                    "adCode": "220800",
+                    "cityCode": "0436"
+                },
+                {
+                    "name": "白山市",
+                    "adCode": "220600",
+                    "cityCode": "0439"
+                },
+                {
+                    "name": "白银市",
+                    "adCode": "620400",
+                    "cityCode": "0943"
+                },
+                {
+                    "name": "百色市",
+                    "adCode": "451000",
+                    "cityCode": "0776"
+                },
+                {
+                    "name": "蚌埠市",
+                    "adCode": "340300",
+                    "cityCode": "0552"
+                },
+                {
+                    "name": "包头市",
+                    "adCode": "150200",
+                    "cityCode": "0472"
+                },
+                {
+                    "name": "宝鸡市",
+                    "adCode": "610300",
+                    "cityCode": "0917"
+                },
+                {
+                    "name": "保定市",
+                    "adCode": "130600",
+                    "cityCode": "0312"
+                },
+                {
+                    "name": "保山市",
+                    "adCode": "530500",
+                    "cityCode": "0875"
+                },
+                {
+                    "name": "北安市",
+                    "adCode": "231181",
+                    "cityCode": "0456"
+                },
+                {
+                    "name": "北海市",
+                    "adCode": "450500",
+                    "cityCode": "0779"
+                },
+                {
+                    "name": "北京市",
+                    "adCode": "110000",
+                    "cityCode": "010",
+                    "type": "hot"
+                },
+                {
+                    "name": "北流市",
+                    "adCode": "450981",
+                    "cityCode": "0775"
+                },
+                {
+                    "name": "北票市",
+                    "adCode": "211381",
+                    "cityCode": "0421"
+                },
+                {
+                    "name": "北屯市",
+                    "adCode": "659005",
+                    "cityCode": "1906"
+                },
+                {
+                    "name": "北镇市",
+                    "adCode": "210782",
+                    "cityCode": "0416"
+                },
+                {
+                    "name": "本溪市",
+                    "adCode": "210500",
+                    "cityCode": "0414"
+                },
+                {
+                    "name": "毕节市",
+                    "adCode": "520500",
+                    "cityCode": "0857"
+                },
+                {
+                    "name": "滨州市",
+                    "adCode": "371600",
+                    "cityCode": "0543"
+                },
+                {
+                    "name": "泊头市",
+                    "adCode": "130981",
+                    "cityCode": "0317"
+                },
+                {
+                    "name": "亳州市",
+                    "adCode": "341600",
+                    "cityCode": "0558"
+                },
+                {
+                    "name": "博乐市",
+                    "adCode": "652701",
+                    "cityCode": "0909"
+                }
+            ]
+        },
+        {
+            "letter": "C",
+            "list": [
+                {
+                    "name": "沧州市",
+                    "adCode": "130900",
+                    "cityCode": "0317"
+                },
+                {
+                    "name": "岑溪市",
+                    "adCode": "450481",
+                    "cityCode": "0774"
+                },
+                {
+                    "name": "昌都市",
+                    "adCode": "540300",
+                    "cityCode": "0895"
+                },
+                {
+                    "name": "昌吉市",
+                    "adCode": "652301",
+                    "cityCode": "0994"
+                },
+                {
+                    "name": "昌邑市",
+                    "adCode": "370786",
+                    "cityCode": "0536"
+                },
+                {
+                    "name": "常德市",
+                    "adCode": "430700",
+                    "cityCode": "0736"
+                },
+                {
+                    "name": "常宁市",
+                    "adCode": "430482",
+                    "cityCode": "0734"
+                },
+                {
+                    "name": "常熟市",
+                    "adCode": "320581",
+                    "cityCode": "0512"
+                },
+                {
+                    "name": "常州市",
+                    "adCode": "320400",
+                    "cityCode": "0519"
+                },
+                {
+                    "name": "巢湖市",
+                    "adCode": "340181",
+                    "cityCode": "0551"
+                },
+                {
+                    "name": "朝阳市",
+                    "adCode": "211300",
+                    "cityCode": "0421"
+                },
+                {
+                    "name": "潮州市",
+                    "adCode": "445100",
+                    "cityCode": "0768"
+                },
+                {
+                    "name": "郴州市",
+                    "adCode": "431000",
+                    "cityCode": "0735"
+                },
+                {
+                    "name": "成都市",
+                    "adCode": "510100",
+                    "cityCode": "028",
+                    "type": "hot"
+                },
+                {
+                    "name": "承德市",
+                    "adCode": "130800",
+                    "cityCode": "0314"
+                },
+                {
+                    "name": "池州市",
+                    "adCode": "341700",
+                    "cityCode": "0566"
+                },
+                {
+                    "name": "赤壁市",
+                    "adCode": "421281",
+                    "cityCode": "0715"
+                },
+                {
+                    "name": "赤峰市",
+                    "adCode": "150400",
+                    "cityCode": "0476"
+                },
+                {
+                    "name": "赤水市",
+                    "adCode": "520381",
+                    "cityCode": "0852"
+                },
+                {
+                    "name": "崇州市",
+                    "adCode": "510184",
+                    "cityCode": "028"
+                },
+                {
+                    "name": "崇左市",
+                    "adCode": "451400",
+                    "cityCode": "1771"
+                },
+                {
+                    "name": "滁州市",
+                    "adCode": "341100",
+                    "cityCode": "0550"
+                },
+                {
+                    "name": "楚雄市",
+                    "adCode": "532301",
+                    "cityCode": "0878"
+                },
+                {
+                    "name": "慈溪市",
+                    "adCode": "330282",
+                    "cityCode": "0574"
+                },
+                {
+                    "name": "长春市",
+                    "adCode": "220100",
+                    "cityCode": "0431",
+                    "type": "hot"
+                },
+                {
+                    "name": "长葛市",
+                    "adCode": "411082",
+                    "cityCode": "0374"
+                },
+                {
+                    "name": "长乐市",
+                    "adCode": "350182",
+                    "cityCode": "0591"
+                },
+                {
+                    "name": "长沙市",
+                    "adCode": "430100",
+                    "cityCode": "0731",
+                    "type": "hot"
+                },
+                {
+                    "name": "长治市",
+                    "adCode": "140400",
+                    "cityCode": "0355"
+                },
+                {
+                    "name": "重庆市",
+                    "adCode": "500000",
+                    "cityCode": "023",
+                    "type": "hot"
+                }
+            ]
+        },
+        {
+            "letter": "D",
+            "list": [
+                {
+                    "name": "达州市",
+                    "adCode": "511700",
+                    "cityCode": "0818"
+                },
+                {
+                    "name": "大安市",
+                    "adCode": "220882",
+                    "cityCode": "0436"
+                },
+                {
+                    "name": "大理市",
+                    "adCode": "532901",
+                    "cityCode": "0872"
+                },
+                {
+                    "name": "大连市",
+                    "adCode": "210200",
+                    "cityCode": "0411",
+                    "type": "hot"
+                },
+                {
+                    "name": "大庆市",
+                    "adCode": "230600",
+                    "cityCode": "0459"
+                },
+                {
+                    "name": "大石桥市",
+                    "adCode": "210882",
+                    "cityCode": "0417"
+                },
+                {
+                    "name": "大同市",
+                    "adCode": "140200",
+                    "cityCode": "0352"
+                },
+                {
+                    "name": "大冶市",
+                    "adCode": "420281",
+                    "cityCode": "0714"
+                },
+                {
+                    "name": "丹东市",
+                    "adCode": "210600",
+                    "cityCode": "0415"
+                },
+                {
+                    "name": "丹江口市",
+                    "adCode": "420381",
+                    "cityCode": "0719"
+                },
+                {
+                    "name": "丹阳市",
+                    "adCode": "321181",
+                    "cityCode": "0511"
+                },
+                {
+                    "name": "儋州市",
+                    "adCode": "460400",
+                    "cityCode": "0805"
+                },
+                {
+                    "name": "当阳市",
+                    "adCode": "420582",
+                    "cityCode": "0717"
+                },
+                {
+                    "name": "德惠市",
+                    "adCode": "220183",
+                    "cityCode": "0431"
+                },
+                {
+                    "name": "德令哈市",
+                    "adCode": "632802",
+                    "cityCode": "0977"
+                },
+                {
+                    "name": "德兴市",
+                    "adCode": "361181",
+                    "cityCode": "0793"
+                },
+                {
+                    "name": "德阳市",
+                    "adCode": "510600",
+                    "cityCode": "0838"
+                },
+                {
+                    "name": "德州市",
+                    "adCode": "371400",
+                    "cityCode": "0534"
+                },
+                {
+                    "name": "灯塔市",
+                    "adCode": "211081",
+                    "cityCode": "0419"
+                },
+                {
+                    "name": "登封市",
+                    "adCode": "410185",
+                    "cityCode": "0371"
+                },
+                {
+                    "name": "邓州市",
+                    "adCode": "411381",
+                    "cityCode": "0377"
+                },
+                {
+                    "name": "定西市",
+                    "adCode": "621100",
+                    "cityCode": "0932"
+                },
+                {
+                    "name": "定州市",
+                    "adCode": "130682",
+                    "cityCode": "0312"
+                },
+                {
+                    "name": "东方市",
+                    "adCode": "469007",
+                    "cityCode": "0807"
+                },
+                {
+                    "name": "东港市",
+                    "adCode": "210681",
+                    "cityCode": "0415"
+                },
+                {
+                    "name": "东莞市",
+                    "adCode": "441900",
+                    "cityCode": "0769"
+                },
+                {
+                    "name": "东宁市",
+                    "adCode": "231086",
+                    "cityCode": "0453"
+                },
+                {
+                    "name": "东台市",
+                    "adCode": "320981",
+                    "cityCode": "0515"
+                },
+                {
+                    "name": "东兴市",
+                    "adCode": "450681",
+                    "cityCode": "0770"
+                },
+                {
+                    "name": "东阳市",
+                    "adCode": "330783",
+                    "cityCode": "0579"
+                },
+                {
+                    "name": "东营市",
+                    "adCode": "370500",
+                    "cityCode": "0546"
+                },
+                {
+                    "name": "都江堰市",
+                    "adCode": "510181",
+                    "cityCode": "028"
+                },
+                {
+                    "name": "都匀市",
+                    "adCode": "522701",
+                    "cityCode": "0854"
+                },
+                {
+                    "name": "敦化市",
+                    "adCode": "222403",
+                    "cityCode": "1433"
+                },
+                {
+                    "name": "敦煌市",
+                    "adCode": "620982",
+                    "cityCode": "0937"
+                }
+            ]
+        },
+        {
+            "letter": "E",
+            "list": [
+                {
+                    "name": "峨眉山市",
+                    "adCode": "511181",
+                    "cityCode": "0833"
+                },
+                {
+                    "name": "额尔古纳市",
+                    "adCode": "150784",
+                    "cityCode": "0470"
+                },
+                {
+                    "name": "鄂尔多斯市",
+                    "adCode": "150600",
+                    "cityCode": "0477"
+                },
+                {
+                    "name": "鄂州市",
+                    "adCode": "420700",
+                    "cityCode": "0711"
+                },
+                {
+                    "name": "恩平市",
+                    "adCode": "440785",
+                    "cityCode": "0750"
+                },
+                {
+                    "name": "恩施市",
+                    "adCode": "422801",
+                    "cityCode": "0718"
+                },
+                {
+                    "name": "二连浩特市",
+                    "adCode": "152501",
+                    "cityCode": "0479"
+                }
+            ]
+        },
+        {
+            "letter": "F",
+            "list": [
+                {
+                    "name": "防城港市",
+                    "adCode": "450600",
+                    "cityCode": "0770"
+                },
+                {
+                    "name": "肥城市",
+                    "adCode": "370983",
+                    "cityCode": "0538"
+                },
+                {
+                    "name": "汾阳市",
+                    "adCode": "141182",
+                    "cityCode": "0358"
+                },
+                {
+                    "name": "丰城市",
+                    "adCode": "360981",
+                    "cityCode": "0795"
+                },
+                {
+                    "name": "丰镇市",
+                    "adCode": "150981",
+                    "cityCode": "0474"
+                },
+                {
+                    "name": "凤城市",
+                    "adCode": "210682",
+                    "cityCode": "0415"
+                },
+                {
+                    "name": "佛山市",
+                    "adCode": "440600",
+                    "cityCode": "0757",
+                    "type": "hot"
+                },
+                {
+                    "name": "扶余市",
+                    "adCode": "220781",
+                    "cityCode": "0438"
+                },
+                {
+                    "name": "福安市",
+                    "adCode": "350981",
+                    "cityCode": "0593"
+                },
+                {
+                    "name": "福鼎市",
+                    "adCode": "350982",
+                    "cityCode": "0593"
+                },
+                {
+                    "name": "福清市",
+                    "adCode": "350181",
+                    "cityCode": "0591"
+                },
+                {
+                    "name": "福泉市",
+                    "adCode": "522702",
+                    "cityCode": "0854"
+                },
+                {
+                    "name": "福州市",
+                    "adCode": "350100",
+                    "cityCode": "0591"
+                },
+                {
+                    "name": "抚顺市",
+                    "adCode": "210400",
+                    "cityCode": "0413"
+                },
+                {
+                    "name": "抚远市",
+                    "adCode": "230883",
+                    "cityCode": "0454"
+                },
+                {
+                    "name": "抚州市",
+                    "adCode": "361000",
+                    "cityCode": "0794"
+                },
+                {
+                    "name": "阜康市",
+                    "adCode": "652302",
+                    "cityCode": "0994"
+                },
+                {
+                    "name": "阜新市",
+                    "adCode": "210900",
+                    "cityCode": "0418"
+                },
+                {
+                    "name": "阜阳市",
+                    "adCode": "341200",
+                    "cityCode": "1558"
+                },
+                {
+                    "name": "富锦市",
+                    "adCode": "230882",
+                    "cityCode": "0454"
+                }
+            ]
+        },
+        {
+            "letter": "G",
+            "list": [
+                {
+                    "name": "盖州市",
+                    "adCode": "210881",
+                    "cityCode": "0417"
+                },
+                {
+                    "name": "赣州市",
+                    "adCode": "360700",
+                    "cityCode": "0797"
+                },
+                {
+                    "name": "高安市",
+                    "adCode": "360983",
+                    "cityCode": "0795"
+                },
+                {
+                    "name": "高碑店市",
+                    "adCode": "130684",
+                    "cityCode": "0312"
+                },
+                {
+                    "name": "高密市",
+                    "adCode": "370785",
+                    "cityCode": "0536"
+                },
+                {
+                    "name": "高平市",
+                    "adCode": "140581",
+                    "cityCode": "0356"
+                },
+                {
+                    "name": "高邮市",
+                    "adCode": "321084",
+                    "cityCode": "0514"
+                },
+                {
+                    "name": "高州市",
+                    "adCode": "440981",
+                    "cityCode": "0668"
+                },
+                {
+                    "name": "格尔木市",
+                    "adCode": "632801",
+                    "cityCode": "0977"
+                },
+                {
+                    "name": "个旧市",
+                    "adCode": "532501",
+                    "cityCode": "0873"
+                },
+                {
+                    "name": "根河市",
+                    "adCode": "150785",
+                    "cityCode": "0470"
+                },
+                {
+                    "name": "公主岭市",
+                    "adCode": "220381",
+                    "cityCode": "0434"
+                },
+                {
+                    "name": "巩义市",
+                    "adCode": "410181",
+                    "cityCode": "0371"
+                },
+                {
+                    "name": "共青城市",
+                    "adCode": "360482",
+                    "cityCode": "0792"
+                },
+                {
+                    "name": "古交市",
+                    "adCode": "140181",
+                    "cityCode": "0351"
+                },
+                {
+                    "name": "固原市",
+                    "adCode": "640400",
+                    "cityCode": "0954"
+                },
+                {
+                    "name": "广安市",
+                    "adCode": "511600",
+                    "cityCode": "0826"
+                },
+                {
+                    "name": "广汉市",
+                    "adCode": "510681",
+                    "cityCode": "0838"
+                },
+                {
+                    "name": "广水市",
+                    "adCode": "421381",
+                    "cityCode": "0722"
+                },
+                {
+                    "name": "广元市",
+                    "adCode": "510800",
+                    "cityCode": "0839"
+                },
+                {
+                    "name": "广州市",
+                    "adCode": "440100",
+                    "cityCode": "020",
+                    "type": "hot"
+                },
+                {
+                    "name": "贵港市",
+                    "adCode": "450800",
+                    "cityCode": "1755"
+                },
+                {
+                    "name": "贵溪市",
+                    "adCode": "360681",
+                    "cityCode": "0701"
+                },
+                {
+                    "name": "贵阳市",
+                    "adCode": "520100",
+                    "cityCode": "0851",
+                    "type": "hot"
+                },
+                {
+                    "name": "桂林市",
+                    "adCode": "450300",
+                    "cityCode": "0773"
+                },
+                {
+                    "name": "桂平市",
+                    "adCode": "450881",
+                    "cityCode": "1755"
+                }
+            ]
+        },
+        {
+            "letter": "H",
+            "list": [
+                {
+                    "name": "哈尔滨市",
+                    "adCode": "230100",
+                    "cityCode": "0451"
+                },
+                {
+                    "name": "哈密市",
+                    "adCode": "650500",
+                    "cityCode": "0902"
+                },
+                {
+                    "name": "海城市",
+                    "adCode": "210381",
+                    "cityCode": "0412"
+                },
+                {
+                    "name": "海东市",
+                    "adCode": "630200",
+                    "cityCode": "0972"
+                },
+                {
+                    "name": "海口市",
+                    "adCode": "460100",
+                    "cityCode": "0898",
+                    "type": "hot"
+                },
+                {
+                    "name": "海林市",
+                    "adCode": "231083",
+                    "cityCode": "0453"
+                },
+                {
+                    "name": "海伦市",
+                    "adCode": "231283",
+                    "cityCode": "0455"
+                },
+                {
+                    "name": "海门市",
+                    "adCode": "320684",
+                    "cityCode": "0513"
+                },
+                {
+                    "name": "海宁市",
+                    "adCode": "330481",
+                    "cityCode": "0573"
+                },
+                {
+                    "name": "海阳市",
+                    "adCode": "370687",
+                    "cityCode": "0535"
+                },
+                {
+                    "name": "邯郸市",
+                    "adCode": "130400",
+                    "cityCode": "0310"
+                },
+                {
+                    "name": "韩城市",
+                    "adCode": "610581",
+                    "cityCode": "0913"
+                },
+                {
+                    "name": "汉川市",
+                    "adCode": "420984",
+                    "cityCode": "0712"
+                },
+                {
+                    "name": "汉中市",
+                    "adCode": "610700",
+                    "cityCode": "0916"
+                },
+                {
+                    "name": "杭州市",
+                    "adCode": "330100",
+                    "cityCode": "0571",
+                    "type": "hot"
+                },
+                {
+                    "name": "合肥市",
+                    "adCode": "340100",
+                    "cityCode": "0551",
+                    "type": "hot"
+                },
+                {
+                    "name": "合山市",
+                    "adCode": "451381",
+                    "cityCode": "1772"
+                },
+                {
+                    "name": "合作市",
+                    "adCode": "623001",
+                    "cityCode": "0941"
+                },
+                {
+                    "name": "和龙市",
+                    "adCode": "222406",
+                    "cityCode": "1433"
+                },
+                {
+                    "name": "和田市",
+                    "adCode": "653201",
+                    "cityCode": "0903"
+                },
+                {
+                    "name": "河池市",
+                    "adCode": "451200",
+                    "cityCode": "0778"
+                },
+                {
+                    "name": "河间市",
+                    "adCode": "130984",
+                    "cityCode": "0317"
+                },
+                {
+                    "name": "河津市",
+                    "adCode": "140882",
+                    "cityCode": "0359"
+                },
+                {
+                    "name": "河源市",
+                    "adCode": "441600",
+                    "cityCode": "0762"
+                },
+                {
+                    "name": "菏泽市",
+                    "adCode": "371700",
+                    "cityCode": "0530"
+                },
+                {
+                    "name": "贺州市",
+                    "adCode": "451100",
+                    "cityCode": "1774"
+                },
+                {
+                    "name": "鹤壁市",
+                    "adCode": "410600",
+                    "cityCode": "0392"
+                },
+                {
+                    "name": "鹤岗市",
+                    "adCode": "230400",
+                    "cityCode": "0468"
+                },
+                {
+                    "name": "鹤山市",
+                    "adCode": "440784",
+                    "cityCode": "0750"
+                },
+                {
+                    "name": "黑河市",
+                    "adCode": "231100",
+                    "cityCode": "0456"
+                },
+                {
+                    "name": "衡水市",
+                    "adCode": "131100",
+                    "cityCode": "0318"
+                },
+                {
+                    "name": "衡阳市",
+                    "adCode": "430400",
+                    "cityCode": "0734"
+                },
+                {
+                    "name": "洪湖市",
+                    "adCode": "421083",
+                    "cityCode": "0716"
+                },
+                {
+                    "name": "洪江市",
+                    "adCode": "431281",
+                    "cityCode": "0745"
+                },
+                {
+                    "name": "侯马市",
+                    "adCode": "141081",
+                    "cityCode": "0357"
+                },
+                {
+                    "name": "呼和浩特市",
+                    "adCode": "150100",
+                    "cityCode": "0471"
+                },
+                {
+                    "name": "呼伦贝尔市",
+                    "adCode": "150700",
+                    "cityCode": "0470"
+                },
+                {
+                    "name": "葫芦岛市",
+                    "adCode": "211400",
+                    "cityCode": "0429"
+                },
+                {
+                    "name": "湖州市",
+                    "adCode": "330500",
+                    "cityCode": "0572"
+                },
+                {
+                    "name": "虎林市",
+                    "adCode": "230381",
+                    "cityCode": "0467"
+                },
+                {
+                    "name": "华阴市",
+                    "adCode": "610582",
+                    "cityCode": "0913"
+                },
+                {
+                    "name": "华蓥市",
+                    "adCode": "511681",
+                    "cityCode": "0826"
+                },
+                {
+                    "name": "化州市",
+                    "adCode": "440982",
+                    "cityCode": "0668"
+                },
+                {
+                    "name": "桦甸市",
+                    "adCode": "220282",
+                    "cityCode": "0432"
+                },
+                {
+                    "name": "怀化市",
+                    "adCode": "431200",
+                    "cityCode": "0745"
+                },
+                {
+                    "name": "淮安市",
+                    "adCode": "320800",
+                    "cityCode": "0517"
+                },
+                {
+                    "name": "淮北市",
+                    "adCode": "340600",
+                    "cityCode": "0561"
+                },
+                {
+                    "name": "淮南市",
+                    "adCode": "340400",
+                    "cityCode": "0554"
+                },
+                {
+                    "name": "黄冈市",
+                    "adCode": "421100",
+                    "cityCode": "0713"
+                },
+                {
+                    "name": "黄骅市",
+                    "adCode": "130983",
+                    "cityCode": "0317"
+                },
+                {
+                    "name": "黄山市",
+                    "adCode": "341000",
+                    "cityCode": "0559"
+                },
+                {
+                    "name": "黄石市",
+                    "adCode": "420200",
+                    "cityCode": "0714"
+                },
+                {
+                    "name": "珲春市",
+                    "adCode": "222404",
+                    "cityCode": "1433"
+                },
+                {
+                    "name": "辉县市",
+                    "adCode": "410782",
+                    "cityCode": "0373"
+                },
+                {
+                    "name": "惠州市",
+                    "adCode": "441300",
+                    "cityCode": "0752"
+                },
+                {
+                    "name": "霍尔果斯市",
+                    "adCode": "654004",
+                    "cityCode": "0999"
+                },
+                {
+                    "name": "霍林郭勒市",
+                    "adCode": "150581",
+                    "cityCode": "0475"
+                },
+                {
+                    "name": "霍州市",
+                    "adCode": "141082",
+                    "cityCode": "0357"
+                }
+            ]
+        },
+        {
+            "letter": "J",
+            "list": [
+                {
+                    "name": "鸡西市",
+                    "adCode": "230300",
+                    "cityCode": "0467"
+                },
+                {
+                    "name": "吉安市",
+                    "adCode": "360800",
+                    "cityCode": "0796"
+                },
+                {
+                    "name": "吉林市",
+                    "adCode": "220200",
+                    "cityCode": "0432"
+                },
+                {
+                    "name": "吉首市",
+                    "adCode": "433101",
+                    "cityCode": "0743"
+                },
+                {
+                    "name": "即墨市",
+                    "adCode": "370282",
+                    "cityCode": "0532"
+                },
+                {
+                    "name": "集安市",
+                    "adCode": "220582",
+                    "cityCode": "0435"
+                },
+                {
+                    "name": "济南市",
+                    "adCode": "370100",
+                    "cityCode": "0531"
+                },
+                {
+                    "name": "济宁市",
+                    "adCode": "370800",
+                    "cityCode": "0537"
+                },
+                {
+                    "name": "济源市",
+                    "adCode": "419001",
+                    "cityCode": "1391"
+                },
+                {
+                    "name": "佳木斯市",
+                    "adCode": "230800",
+                    "cityCode": "0454"
+                },
+                {
+                    "name": "嘉兴市",
+                    "adCode": "330400",
+                    "cityCode": "0573"
+                },
+                {
+                    "name": "嘉峪关市",
+                    "adCode": "620200",
+                    "cityCode": "1937"
+                },
+                {
+                    "name": "简阳市",
+                    "adCode": "510180",
+                    "cityCode": "028"
+                },
+                {
+                    "name": "建德市",
+                    "adCode": "330182",
+                    "cityCode": "0571"
+                },
+                {
+                    "name": "建瓯市",
+                    "adCode": "350783",
+                    "cityCode": "0599"
+                },
+                {
+                    "name": "江门市",
+                    "adCode": "440700",
+                    "cityCode": "0750"
+                },
+                {
+                    "name": "江山市",
+                    "adCode": "330881",
+                    "cityCode": "0570"
+                },
+                {
+                    "name": "江阴市",
+                    "adCode": "320281",
+                    "cityCode": "0510"
+                },
+                {
+                    "name": "江油市",
+                    "adCode": "510781",
+                    "cityCode": "0816"
+                },
+                {
+                    "name": "胶州市",
+                    "adCode": "370281",
+                    "cityCode": "0532"
+                },
+                {
+                    "name": "蛟河市",
+                    "adCode": "220281",
+                    "cityCode": "0432"
+                },
+                {
+                    "name": "焦作市",
+                    "adCode": "410800",
+                    "cityCode": "0391"
+                },
+                {
+                    "name": "揭阳市",
+                    "adCode": "445200",
+                    "cityCode": "0663"
+                },
+                {
+                    "name": "介休市",
+                    "adCode": "140781",
+                    "cityCode": "0354"
+                },
+                {
+                    "name": "界首市",
+                    "adCode": "341282",
+                    "cityCode": "1558"
+                },
+                {
+                    "name": "金昌市",
+                    "adCode": "620300",
+                    "cityCode": "0935"
+                },
+                {
+                    "name": "金华市",
+                    "adCode": "330700",
+                    "cityCode": "0579"
+                },
+                {
+                    "name": "津市市",
+                    "adCode": "430781",
+                    "cityCode": "0736"
+                },
+                {
+                    "name": "锦州市",
+                    "adCode": "210700",
+                    "cityCode": "0416"
+                },
+                {
+                    "name": "晋城市",
+                    "adCode": "140500",
+                    "cityCode": "0356"
+                },
+                {
+                    "name": "晋江市",
+                    "adCode": "350582",
+                    "cityCode": "0595"
+                },
+                {
+                    "name": "晋中市",
+                    "adCode": "140700",
+                    "cityCode": "0354"
+                },
+                {
+                    "name": "晋州市",
+                    "adCode": "130183",
+                    "cityCode": "0311"
+                },
+                {
+                    "name": "荆门市",
+                    "adCode": "420800",
+                    "cityCode": "0724"
+                },
+                {
+                    "name": "荆州市",
+                    "adCode": "421000",
+                    "cityCode": "0716"
+                },
+                {
+                    "name": "井冈山市",
+                    "adCode": "360881",
+                    "cityCode": "0796"
+                },
+                {
+                    "name": "景德镇市",
+                    "adCode": "360200",
+                    "cityCode": "0798"
+                },
+                {
+                    "name": "景洪市",
+                    "adCode": "532801",
+                    "cityCode": "0691"
+                },
+                {
+                    "name": "靖江市",
+                    "adCode": "321282",
+                    "cityCode": "0523"
+                },
+                {
+                    "name": "靖西市",
+                    "adCode": "451081",
+                    "cityCode": "0776"
+                },
+                {
+                    "name": "九江市",
+                    "adCode": "360400",
+                    "cityCode": "0792"
+                },
+                {
+                    "name": "酒泉市",
+                    "adCode": "620900",
+                    "cityCode": "0937"
+                },
+                {
+                    "name": "句容市",
+                    "adCode": "321183",
+                    "cityCode": "0511"
+                }
+            ]
+        },
+        {
+            "letter": "K",
+            "list": [
+                {
+                    "name": "喀什市",
+                    "adCode": "653101",
+                    "cityCode": "0998"
+                },
+                {
+                    "name": "开封市",
+                    "adCode": "410200",
+                    "cityCode": "0378"
+                },
+                {
+                    "name": "开平市",
+                    "adCode": "440783",
+                    "cityCode": "0750"
+                },
+                {
+                    "name": "开原市",
+                    "adCode": "211282",
+                    "cityCode": "0410"
+                },
+                {
+                    "name": "开远市",
+                    "adCode": "532502",
+                    "cityCode": "0873"
+                },
+                {
+                    "name": "凯里市",
+                    "adCode": "522601",
+                    "cityCode": "0855"
+                },
+                {
+                    "name": "康定市",
+                    "adCode": "513301",
+                    "cityCode": "0836"
+                },
+                {
+                    "name": "可克达拉市",
+                    "adCode": "659008",
+                    "cityCode": "1999"
+                },
+                {
+                    "name": "克拉玛依市",
+                    "adCode": "650200",
+                    "cityCode": "0990"
+                },
+                {
+                    "name": "库尔勒市",
+                    "adCode": "652801",
+                    "cityCode": "0996"
+                },
+                {
+                    "name": "奎屯市",
+                    "adCode": "654003",
+                    "cityCode": "0999"
+                },
+                {
+                    "name": "昆明市",
+                    "adCode": "530100",
+                    "cityCode": "0871",
+                    "type": "hot"
+                },
+                {
+                    "name": "昆山市",
+                    "adCode": "320583",
+                    "cityCode": "0512"
+                },
+                {
+                    "name": "昆玉市",
+                    "adCode": "659009",
+                    "cityCode": "1903"
+                }
+            ]
+        },
+        {
+            "letter": "L",
+            "list": [
+                {
+                    "name": "拉萨市",
+                    "adCode": "540100",
+                    "cityCode": "0891"
+                },
+                {
+                    "name": "来宾市",
+                    "adCode": "451300",
+                    "cityCode": "1772"
+                },
+                {
+                    "name": "莱芜市",
+                    "adCode": "371200",
+                    "cityCode": "0634"
+                },
+                {
+                    "name": "莱西市",
+                    "adCode": "370285",
+                    "cityCode": "0532"
+                },
+                {
+                    "name": "莱阳市",
+                    "adCode": "370682",
+                    "cityCode": "0535"
+                },
+                {
+                    "name": "莱州市",
+                    "adCode": "370683",
+                    "cityCode": "0535"
+                },
+                {
+                    "name": "兰溪市",
+                    "adCode": "330781",
+                    "cityCode": "0579"
+                },
+                {
+                    "name": "兰州市",
+                    "adCode": "620100",
+                    "cityCode": "0931"
+                },
+                {
+                    "name": "阆中市",
+                    "adCode": "511381",
+                    "cityCode": "0817"
+                },
+                {
+                    "name": "廊坊市",
+                    "adCode": "131000",
+                    "cityCode": "0316"
+                },
+                {
+                    "name": "老河口市",
+                    "adCode": "420682",
+                    "cityCode": "0710"
+                },
+                {
+                    "name": "乐昌市",
+                    "adCode": "440281",
+                    "cityCode": "0751"
+                },
+                {
+                    "name": "乐陵市",
+                    "adCode": "371481",
+                    "cityCode": "0534"
+                },
+                {
+                    "name": "乐平市",
+                    "adCode": "360281",
+                    "cityCode": "0798"
+                },
+                {
+                    "name": "乐清市",
+                    "adCode": "330382",
+                    "cityCode": "0577"
+                },
+                {
+                    "name": "乐山市",
+                    "adCode": "511100",
+                    "cityCode": "0833"
+                },
+                {
+                    "name": "雷州市",
+                    "adCode": "440882",
+                    "cityCode": "0759"
+                },
+                {
+                    "name": "耒阳市",
+                    "adCode": "430481",
+                    "cityCode": "0734"
+                },
+                {
+                    "name": "冷水江市",
+                    "adCode": "431381",
+                    "cityCode": "0738"
+                },
+                {
+                    "name": "醴陵市",
+                    "adCode": "430281",
+                    "cityCode": "0733"
+                },
+                {
+                    "name": "丽江市",
+                    "adCode": "530700",
+                    "cityCode": "0888"
+                },
+                {
+                    "name": "丽水市",
+                    "adCode": "331100",
+                    "cityCode": "0578"
+                },
+                {
+                    "name": "利川市",
+                    "adCode": "422802",
+                    "cityCode": "0718"
+                },
+                {
+                    "name": "溧阳市",
+                    "adCode": "320481",
+                    "cityCode": "0519"
+                },
+                {
+                    "name": "连云港市",
+                    "adCode": "320700",
+                    "cityCode": "0518"
+                },
+                {
+                    "name": "连州市",
+                    "adCode": "441882",
+                    "cityCode": "0763"
+                },
+                {
+                    "name": "涟源市",
+                    "adCode": "431382",
+                    "cityCode": "0738"
+                },
+                {
+                    "name": "廉江市",
+                    "adCode": "440881",
+                    "cityCode": "0759"
+                },
+                {
+                    "name": "辽阳市",
+                    "adCode": "211000",
+                    "cityCode": "0419"
+                },
+                {
+                    "name": "辽源市",
+                    "adCode": "220400",
+                    "cityCode": "0437"
+                },
+                {
+                    "name": "聊城市",
+                    "adCode": "371500",
+                    "cityCode": "0635"
+                },
+                {
+                    "name": "林芝市",
+                    "adCode": "540400",
+                    "cityCode": "0894"
+                },
+                {
+                    "name": "林州市",
+                    "adCode": "410581",
+                    "cityCode": "0372"
+                },
+                {
+                    "name": "临安市",
+                    "adCode": "330185",
+                    "cityCode": "0571"
+                },
+                {
+                    "name": "临沧市",
+                    "adCode": "530900",
+                    "cityCode": "0883"
+                },
+                {
+                    "name": "临汾市",
+                    "adCode": "141000",
+                    "cityCode": "0357"
+                },
+                {
+                    "name": "临海市",
+                    "adCode": "331082",
+                    "cityCode": "0576"
+                },
+                {
+                    "name": "临江市",
+                    "adCode": "220681",
+                    "cityCode": "0439"
+                },
+                {
+                    "name": "临清市",
+                    "adCode": "371581",
+                    "cityCode": "0635"
+                },
+                {
+                    "name": "临夏市",
+                    "adCode": "622901",
+                    "cityCode": "0930"
+                },
+                {
+                    "name": "临湘市",
+                    "adCode": "430682",
+                    "cityCode": "0730"
+                },
+                {
+                    "name": "临沂市",
+                    "adCode": "371300",
+                    "cityCode": "0539"
+                },
+                {
+                    "name": "灵宝市",
+                    "adCode": "411282",
+                    "cityCode": "0398"
+                },
+                {
+                    "name": "灵武市",
+                    "adCode": "640181",
+                    "cityCode": "0951"
+                },
+                {
+                    "name": "凌海市",
+                    "adCode": "210781",
+                    "cityCode": "0416"
+                },
+                {
+                    "name": "凌源市",
+                    "adCode": "211382",
+                    "cityCode": "0421"
+                },
+                {
+                    "name": "浏阳市",
+                    "adCode": "430181",
+                    "cityCode": "0731"
+                },
+                {
+                    "name": "柳州市",
+                    "adCode": "450200",
+                    "cityCode": "0772"
+                },
+                {
+                    "name": "六安市",
+                    "adCode": "341500",
+                    "cityCode": "0564"
+                },
+                {
+                    "name": "六盘水市",
+                    "adCode": "520200",
+                    "cityCode": "0858"
+                },
+                {
+                    "name": "龙海市",
+                    "adCode": "350681",
+                    "cityCode": "0596"
+                },
+                {
+                    "name": "龙井市",
+                    "adCode": "222405",
+                    "cityCode": "1433"
+                },
+                {
+                    "name": "龙口市",
+                    "adCode": "370681",
+                    "cityCode": "0535"
+                },
+                {
+                    "name": "龙泉市",
+                    "adCode": "331181",
+                    "cityCode": "0578"
+                },
+                {
+                    "name": "龙岩市",
+                    "adCode": "350800",
+                    "cityCode": "0597"
+                },
+                {
+                    "name": "陇南市",
+                    "adCode": "621200",
+                    "cityCode": "2935"
+                },
+                {
+                    "name": "娄底市",
+                    "adCode": "431300",
+                    "cityCode": "0738"
+                },
+                {
+                    "name": "庐山市",
+                    "adCode": "360427",
+                    "cityCode": "0792"
+                },
+                {
+                    "name": "泸水市",
+                    "adCode": "533301",
+                    "cityCode": "0886"
+                },
+                {
+                    "name": "泸州市",
+                    "adCode": "510500",
+                    "cityCode": "0830"
+                },
+                {
+                    "name": "陆丰市",
+                    "adCode": "441581",
+                    "cityCode": "0660"
+                },
+                {
+                    "name": "潞城市",
+                    "adCode": "140481",
+                    "cityCode": "0355"
+                },
+                {
+                    "name": "罗定市",
+                    "adCode": "445381",
+                    "cityCode": "0766"
+                },
+                {
+                    "name": "洛阳市",
+                    "adCode": "410300",
+                    "cityCode": "0379"
+                },
+                {
+                    "name": "漯河市",
+                    "adCode": "411100",
+                    "cityCode": "0395"
+                },
+                {
+                    "name": "吕梁市",
+                    "adCode": "141100",
+                    "cityCode": "0358"
+                }
+            ]
+        },
+        {
+            "letter": "M",
+            "list": [
+                {
+                    "name": "麻城市",
+                    "adCode": "421181",
+                    "cityCode": "0713"
+                },
+                {
+                    "name": "马鞍山市",
+                    "adCode": "340500",
+                    "cityCode": "0555"
+                },
+                {
+                    "name": "马尔康市",
+                    "adCode": "513201",
+                    "cityCode": "0837"
+                },
+                {
+                    "name": "满洲里市",
+                    "adCode": "150781",
+                    "cityCode": "0470"
+                },
+                {
+                    "name": "芒市",
+                    "adCode": "533103",
+                    "cityCode": "0692"
+                },
+                {
+                    "name": "茂名市",
+                    "adCode": "440900",
+                    "cityCode": "0668"
+                },
+                {
+                    "name": "眉山市",
+                    "adCode": "511400",
+                    "cityCode": "1833"
+                },
+                {
+                    "name": "梅河口市",
+                    "adCode": "220581",
+                    "cityCode": "0435"
+                },
+                {
+                    "name": "梅州市",
+                    "adCode": "441400",
+                    "cityCode": "0753"
+                },
+                {
+                    "name": "蒙自市",
+                    "adCode": "532503",
+                    "cityCode": "0873"
+                },
+                {
+                    "name": "孟州市",
+                    "adCode": "410883",
+                    "cityCode": "0391"
+                },
+                {
+                    "name": "弥勒市",
+                    "adCode": "532504",
+                    "cityCode": "0873"
+                },
+                {
+                    "name": "汨罗市",
+                    "adCode": "430681",
+                    "cityCode": "0730"
+                },
+                {
+                    "name": "密山市",
+                    "adCode": "230382",
+                    "cityCode": "0467"
+                },
+                {
+                    "name": "绵阳市",
+                    "adCode": "510700",
+                    "cityCode": "0816"
+                },
+                {
+                    "name": "绵竹市",
+                    "adCode": "510683",
+                    "cityCode": "0838"
+                },
+                {
+                    "name": "明光市",
+                    "adCode": "341182",
+                    "cityCode": "0550"
+                },
+                {
+                    "name": "牡丹江市",
+                    "adCode": "231000",
+                    "cityCode": "0453"
+                },
+                {
+                    "name": "穆棱市",
+                    "adCode": "231085",
+                    "cityCode": "0453"
+                }
+            ]
+        },
+        {
+            "letter": "N",
+            "list": [
+                {
+                    "name": "南安市",
+                    "adCode": "350583",
+                    "cityCode": "0595"
+                },
+                {
+                    "name": "南昌市",
+                    "adCode": "360100",
+                    "cityCode": "0791"
+                },
+                {
+                    "name": "南充市",
+                    "adCode": "511300",
+                    "cityCode": "0817"
+                },
+                {
+                    "name": "南宫市",
+                    "adCode": "130581",
+                    "cityCode": "0319"
+                },
+                {
+                    "name": "南京市",
+                    "adCode": "320100",
+                    "cityCode": "025",
+                    "type": "hot"
+                },
+                {
+                    "name": "南宁市",
+                    "adCode": "450100",
+                    "cityCode": "0771"
+                },
+                {
+                    "name": "南平市",
+                    "adCode": "350700",
+                    "cityCode": "0599"
+                },
+                {
+                    "name": "南通市",
+                    "adCode": "320600",
+                    "cityCode": "0513"
+                },
+                {
+                    "name": "南雄市",
+                    "adCode": "440282",
+                    "cityCode": "0751"
+                },
+                {
+                    "name": "南阳市",
+                    "adCode": "411300",
+                    "cityCode": "0377"
+                },
+                {
+                    "name": "讷河市",
+                    "adCode": "230281",
+                    "cityCode": "0452"
+                },
+                {
+                    "name": "内江市",
+                    "adCode": "511000",
+                    "cityCode": "1832"
+                },
+                {
+                    "name": "宁安市",
+                    "adCode": "231084",
+                    "cityCode": "0453"
+                },
+                {
+                    "name": "宁波市",
+                    "adCode": "330200",
+                    "cityCode": "0574"
+                },
+                {
+                    "name": "宁德市",
+                    "adCode": "350900",
+                    "cityCode": "0593"
+                },
+                {
+                    "name": "宁国市",
+                    "adCode": "341881",
+                    "cityCode": "0563"
+                }
+            ]
+        },
+        {
+            "letter": "P",
+            "list": [
+                {
+                    "name": "攀枝花市",
+                    "adCode": "510400",
+                    "cityCode": "0812"
+                },
+                {
+                    "name": "盘锦市",
+                    "adCode": "211100",
+                    "cityCode": "0427"
+                },
+                {
+                    "name": "磐石市",
+                    "adCode": "220284",
+                    "cityCode": "0432"
+                },
+                {
+                    "name": "彭州市",
+                    "adCode": "510182",
+                    "cityCode": "028"
+                },
+                {
+                    "name": "蓬莱市",
+                    "adCode": "370684",
+                    "cityCode": "0535"
+                },
+                {
+                    "name": "邳州市",
+                    "adCode": "320382",
+                    "cityCode": "0516"
+                },
+                {
+                    "name": "平顶山市",
+                    "adCode": "410400",
+                    "cityCode": "0375"
+                },
+                {
+                    "name": "平度市",
+                    "adCode": "370283",
+                    "cityCode": "0532"
+                },
+                {
+                    "name": "平湖市",
+                    "adCode": "330482",
+                    "cityCode": "0573"
+                },
+                {
+                    "name": "平凉市",
+                    "adCode": "620800",
+                    "cityCode": "0933"
+                },
+                {
+                    "name": "凭祥市",
+                    "adCode": "451481",
+                    "cityCode": "1771"
+                },
+                {
+                    "name": "萍乡市",
+                    "adCode": "360300",
+                    "cityCode": "0799"
+                },
+                {
+                    "name": "莆田市",
+                    "adCode": "350300",
+                    "cityCode": "0594"
+                },
+                {
+                    "name": "濮阳市",
+                    "adCode": "410900",
+                    "cityCode": "0393"
+                },
+                {
+                    "name": "普洱市",
+                    "adCode": "530800",
+                    "cityCode": "0879"
+                },
+                {
+                    "name": "普宁市",
+                    "adCode": "445281",
+                    "cityCode": "0663"
+                }
+            ]
+        },
+        {
+            "letter": "Q",
+            "list": [
+                {
+                    "name": "七台河市",
+                    "adCode": "230900",
+                    "cityCode": "0464"
+                },
+                {
+                    "name": "栖霞市",
+                    "adCode": "370686",
+                    "cityCode": "0535"
+                },
+                {
+                    "name": "齐齐哈尔市",
+                    "adCode": "230200",
+                    "cityCode": "0452"
+                },
+                {
+                    "name": "启东市",
+                    "adCode": "320681",
+                    "cityCode": "0513"
+                },
+                {
+                    "name": "迁安市",
+                    "adCode": "130283",
+                    "cityCode": "0315"
+                },
+                {
+                    "name": "潜江市",
+                    "adCode": "429005",
+                    "cityCode": "2728"
+                },
+                {
+                    "name": "钦州市",
+                    "adCode": "450700",
+                    "cityCode": "0777"
+                },
+                {
+                    "name": "秦皇岛市",
+                    "adCode": "130300",
+                    "cityCode": "0335"
+                },
+                {
+                    "name": "沁阳市",
+                    "adCode": "410882",
+                    "cityCode": "0391"
+                },
+                {
+                    "name": "青岛市",
+                    "adCode": "370200",
+                    "cityCode": "0532",
+                    "type": "hot"
+                },
+                {
+                    "name": "青铜峡市",
+                    "adCode": "640381",
+                    "cityCode": "0953"
+                },
+                {
+                    "name": "青州市",
+                    "adCode": "370781",
+                    "cityCode": "0536"
+                },
+                {
+                    "name": "清远市",
+                    "adCode": "441800",
+                    "cityCode": "0763"
+                },
+                {
+                    "name": "清镇市",
+                    "adCode": "520181",
+                    "cityCode": "0851"
+                },
+                {
+                    "name": "庆阳市",
+                    "adCode": "621000",
+                    "cityCode": "0934"
+                },
+                {
+                    "name": "邛崃市",
+                    "adCode": "510183",
+                    "cityCode": "028"
+                },
+                {
+                    "name": "琼海市",
+                    "adCode": "469002",
+                    "cityCode": "1894"
+                },
+                {
+                    "name": "衢州市",
+                    "adCode": "330800",
+                    "cityCode": "0570"
+                },
+                {
+                    "name": "曲阜市",
+                    "adCode": "370881",
+                    "cityCode": "0537"
+                },
+                {
+                    "name": "曲靖市",
+                    "adCode": "530300",
+                    "cityCode": "0874"
+                },
+                {
+                    "name": "泉州市",
+                    "adCode": "350500",
+                    "cityCode": "0595"
+                }
+            ]
+        },
+        {
+            "letter": "R",
+            "list": [
+                {
+                    "name": "仁怀市",
+                    "adCode": "520382",
+                    "cityCode": "0852"
+                },
+                {
+                    "name": "任丘市",
+                    "adCode": "130982",
+                    "cityCode": "0317"
+                },
+                {
+                    "name": "日喀则市",
+                    "adCode": "540200",
+                    "cityCode": "0892"
+                },
+                {
+                    "name": "日照市",
+                    "adCode": "371100",
+                    "cityCode": "0633"
+                },
+                {
+                    "name": "荣成市",
+                    "adCode": "371082",
+                    "cityCode": "0631"
+                },
+                {
+                    "name": "如皋市",
+                    "adCode": "320682",
+                    "cityCode": "0513"
+                },
+                {
+                    "name": "汝州市",
+                    "adCode": "410482",
+                    "cityCode": "0375"
+                },
+                {
+                    "name": "乳山市",
+                    "adCode": "371083",
+                    "cityCode": "0631"
+                },
+                {
+                    "name": "瑞安市",
+                    "adCode": "330381",
+                    "cityCode": "0577"
+                },
+                {
+                    "name": "瑞昌市",
+                    "adCode": "360481",
+                    "cityCode": "0792"
+                },
+                {
+                    "name": "瑞金市",
+                    "adCode": "360781",
+                    "cityCode": "0797"
+                },
+                {
+                    "name": "瑞丽市",
+                    "adCode": "533102",
+                    "cityCode": "0692"
+                }
+            ]
+        },
+        {
+            "letter": "S",
+            "list": [
+                {
+                    "name": "三河市",
+                    "adCode": "131082",
+                    "cityCode": "0316"
+                },
+                {
+                    "name": "三门峡市",
+                    "adCode": "411200",
+                    "cityCode": "0398"
+                },
+                {
+                    "name": "三明市",
+                    "adCode": "350400",
+                    "cityCode": "0598"
+                },
+                {
+                    "name": "三沙市",
+                    "adCode": "460300",
+                    "cityCode": "2898"
+                },
+                {
+                    "name": "三亚市",
+                    "adCode": "460200",
+                    "cityCode": "0899"
+                },
+                {
+                    "name": "沙河市",
+                    "adCode": "130582",
+                    "cityCode": "0319"
+                },
+                {
+                    "name": "厦门市",
+                    "adCode": "350200",
+                    "cityCode": "0592",
+                    "type": "hot"
+                },
+                {
+                    "name": "山南市",
+                    "adCode": "540500",
+                    "cityCode": "0893"
+                },
+                {
+                    "name": "汕头市",
+                    "adCode": "440500",
+                    "cityCode": "0754"
+                },
+                {
+                    "name": "汕尾市",
+                    "adCode": "441500",
+                    "cityCode": "0660"
+                },
+                {
+                    "name": "商洛市",
+                    "adCode": "611000",
+                    "cityCode": "0914"
+                },
+                {
+                    "name": "商丘市",
+                    "adCode": "411400",
+                    "cityCode": "0370"
+                },
+                {
+                    "name": "上海市",
+                    "adCode": "310000",
+                    "cityCode": "021",
+                    "type": "hot"
+                },
+                {
+                    "name": "上饶市",
+                    "adCode": "361100",
+                    "cityCode": "0793"
+                },
+                {
+                    "name": "尚志市",
+                    "adCode": "230183",
+                    "cityCode": "0451"
+                },
+                {
+                    "name": "韶关市",
+                    "adCode": "440200",
+                    "cityCode": "0751"
+                },
+                {
+                    "name": "韶山市",
+                    "adCode": "430382",
+                    "cityCode": "0732"
+                },
+                {
+                    "name": "邵武市",
+                    "adCode": "350781",
+                    "cityCode": "0599"
+                },
+                {
+                    "name": "邵阳市",
+                    "adCode": "430500",
+                    "cityCode": "0739"
+                },
+                {
+                    "name": "绍兴市",
+                    "adCode": "330600",
+                    "cityCode": "0575"
+                },
+                {
+                    "name": "深圳市",
+                    "adCode": "440300",
+                    "cityCode": "0755",
+                    "type": "hot"
+                },
+                {
+                    "name": "深州市",
+                    "adCode": "131182",
+                    "cityCode": "0318"
+                },
+                {
+                    "name": "什邡市",
+                    "adCode": "510682",
+                    "cityCode": "0838"
+                },
+                {
+                    "name": "沈阳市",
+                    "adCode": "210100",
+                    "cityCode": "024"
+                },
+                {
+                    "name": "嵊州市",
+                    "adCode": "330683",
+                    "cityCode": "0575"
+                },
+                {
+                    "name": "十堰市",
+                    "adCode": "420300",
+                    "cityCode": "0719"
+                },
+                {
+                    "name": "石河子市",
+                    "adCode": "659001",
+                    "cityCode": "0993"
+                },
+                {
+                    "name": "石家庄市",
+                    "adCode": "130100",
+                    "cityCode": "0311"
+                },
+                {
+                    "name": "石狮市",
+                    "adCode": "350581",
+                    "cityCode": "0595"
+                },
+                {
+                    "name": "石首市",
+                    "adCode": "421081",
+                    "cityCode": "0716"
+                },
+                {
+                    "name": "石嘴山市",
+                    "adCode": "640200",
+                    "cityCode": "0952"
+                },
+                {
+                    "name": "寿光市",
+                    "adCode": "370783",
+                    "cityCode": "0536"
+                },
+                {
+                    "name": "舒兰市",
+                    "adCode": "220283",
+                    "cityCode": "0432"
+                },
+                {
+                    "name": "双河市",
+                    "adCode": "659007",
+                    "cityCode": "1909"
+                },
+                {
+                    "name": "双辽市",
+                    "adCode": "220382",
+                    "cityCode": "0434"
+                },
+                {
+                    "name": "双鸭山市",
+                    "adCode": "230500",
+                    "cityCode": "0469"
+                },
+                {
+                    "name": "朔州市",
+                    "adCode": "140600",
+                    "cityCode": "0349"
+                },
+                {
+                    "name": "四会市",
+                    "adCode": "441284",
+                    "cityCode": "0758"
+                },
+                {
+                    "name": "四平市",
+                    "adCode": "220300",
+                    "cityCode": "0434"
+                },
+                {
+                    "name": "松原市",
+                    "adCode": "220700",
+                    "cityCode": "0438"
+                },
+                {
+                    "name": "松滋市",
+                    "adCode": "421087",
+                    "cityCode": "0716"
+                },
+                {
+                    "name": "苏州市",
+                    "adCode": "320500",
+                    "cityCode": "0512"
+                },
+                {
+                    "name": "绥芬河市",
+                    "adCode": "231081",
+                    "cityCode": "0453"
+                },
+                {
+                    "name": "绥化市",
+                    "adCode": "231200",
+                    "cityCode": "0455"
+                },
+                {
+                    "name": "随州市",
+                    "adCode": "421300",
+                    "cityCode": "0722"
+                },
+                {
+                    "name": "遂宁市",
+                    "adCode": "510900",
+                    "cityCode": "0825"
+                }
+            ]
+        },
+        {
+            "letter": "T",
+            "list": [
+                {
+                    "name": "塔城市",
+                    "adCode": "654201",
+                    "cityCode": "0901"
+                },
+                {
+                    "name": "台山市",
+                    "adCode": "440781",
+                    "cityCode": "0750"
+                },
+                {
+                    "name": "台州市",
+                    "adCode": "331000",
+                    "cityCode": "0576"
+                },
+                {
+                    "name": "太仓市",
+                    "adCode": "320585",
+                    "cityCode": "0512"
+                },
+                {
+                    "name": "太原市",
+                    "adCode": "140100",
+                    "cityCode": "0351"
+                },
+                {
+                    "name": "泰安市",
+                    "adCode": "370900",
+                    "cityCode": "0538"
+                },
+                {
+                    "name": "泰兴市",
+                    "adCode": "321283",
+                    "cityCode": "0523"
+                },
+                {
+                    "name": "泰州市",
+                    "adCode": "321200",
+                    "cityCode": "0523"
+                },
+                {
+                    "name": "唐山市",
+                    "adCode": "130200",
+                    "cityCode": "0315"
+                },
+                {
+                    "name": "洮南市",
+                    "adCode": "220881",
+                    "cityCode": "0436"
+                },
+                {
+                    "name": "腾冲市",
+                    "adCode": "530581",
+                    "cityCode": "0875"
+                },
+                {
+                    "name": "滕州市",
+                    "adCode": "370481",
+                    "cityCode": "0632"
+                },
+                {
+                    "name": "天津市",
+                    "adCode": "120000",
+                    "cityCode": "022",
+                    "type": "hot"
+                },
+                {
+                    "name": "天门市",
+                    "adCode": "429006",
+                    "cityCode": "1728"
+                },
+                {
+                    "name": "天水市",
+                    "adCode": "620500",
+                    "cityCode": "0938"
+                },
+                {
+                    "name": "天长市",
+                    "adCode": "341181",
+                    "cityCode": "0550"
+                },
+                {
+                    "name": "调兵山市",
+                    "adCode": "211281",
+                    "cityCode": "0410"
+                },
+                {
+                    "name": "铁力市",
+                    "adCode": "230781",
+                    "cityCode": "0458"
+                },
+                {
+                    "name": "铁岭市",
+                    "adCode": "211200",
+                    "cityCode": "0410"
+                },
+                {
+                    "name": "铁门关市",
+                    "adCode": "659006",
+                    "cityCode": "1996"
+                },
+                {
+                    "name": "通化市",
+                    "adCode": "220500",
+                    "cityCode": "0435"
+                },
+                {
+                    "name": "通辽市",
+                    "adCode": "150500",
+                    "cityCode": "0475"
+                },
+                {
+                    "name": "同江市",
+                    "adCode": "230881",
+                    "cityCode": "0454"
+                },
+                {
+                    "name": "桐城市",
+                    "adCode": "340881",
+                    "cityCode": "0556"
+                },
+                {
+                    "name": "桐乡市",
+                    "adCode": "330483",
+                    "cityCode": "0573"
+                },
+                {
+                    "name": "铜川市",
+                    "adCode": "610200",
+                    "cityCode": "0919"
+                },
+                {
+                    "name": "铜陵市",
+                    "adCode": "340700",
+                    "cityCode": "0562"
+                },
+                {
+                    "name": "铜仁市",
+                    "adCode": "520600",
+                    "cityCode": "0856"
+                },
+                {
+                    "name": "图们市",
+                    "adCode": "222402",
+                    "cityCode": "1433"
+                },
+                {
+                    "name": "图木舒克市",
+                    "adCode": "659003",
+                    "cityCode": "1998"
+                },
+                {
+                    "name": "吐鲁番市",
+                    "adCode": "650400",
+                    "cityCode": "0995"
+                }
+            ]
+        },
+        {
+            "letter": "W",
+            "list": [
+                {
+                    "name": "瓦房店市",
+                    "adCode": "210281",
+                    "cityCode": "0411"
+                },
+                {
+                    "name": "万宁市",
+                    "adCode": "469006",
+                    "cityCode": "1898"
+                },
+                {
+                    "name": "万源市",
+                    "adCode": "511781",
+                    "cityCode": "0818"
+                },
+                {
+                    "name": "威海市",
+                    "adCode": "371000",
+                    "cityCode": "0631"
+                },
+                {
+                    "name": "潍坊市",
+                    "adCode": "370700",
+                    "cityCode": "0536"
+                },
+                {
+                    "name": "卫辉市",
+                    "adCode": "410781",
+                    "cityCode": "0373"
+                },
+                {
+                    "name": "渭南市",
+                    "adCode": "610500",
+                    "cityCode": "0913"
+                },
+                {
+                    "name": "温岭市",
+                    "adCode": "331081",
+                    "cityCode": "0576"
+                },
+                {
+                    "name": "温州市",
+                    "adCode": "330300",
+                    "cityCode": "0577"
+                },
+                {
+                    "name": "文昌市",
+                    "adCode": "469005",
+                    "cityCode": "1893"
+                },
+                {
+                    "name": "文山市",
+                    "adCode": "532601",
+                    "cityCode": "0876"
+                },
+                {
+                    "name": "乌海市",
+                    "adCode": "150300",
+                    "cityCode": "0473"
+                },
+                {
+                    "name": "乌兰察布市",
+                    "adCode": "150900",
+                    "cityCode": "0474"
+                },
+                {
+                    "name": "乌兰浩特市",
+                    "adCode": "152201",
+                    "cityCode": "0482"
+                },
+                {
+                    "name": "乌鲁木齐市",
+                    "adCode": "650100",
+                    "cityCode": "0991",
+                    "type": "hot"
+                },
+                {
+                    "name": "乌苏市",
+                    "adCode": "654202",
+                    "cityCode": "0901"
+                },
+                {
+                    "name": "无锡市",
+                    "adCode": "320200",
+                    "cityCode": "0510"
+                },
+                {
+                    "name": "芜湖市",
+                    "adCode": "340200",
+                    "cityCode": "0553"
+                },
+                {
+                    "name": "吴川市",
+                    "adCode": "440883",
+                    "cityCode": "0759"
+                },
+                {
+                    "name": "吴忠市",
+                    "adCode": "640300",
+                    "cityCode": "0953"
+                },
+                {
+                    "name": "梧州市",
+                    "adCode": "450400",
+                    "cityCode": "0774"
+                },
+                {
+                    "name": "五常市",
+                    "adCode": "230184",
+                    "cityCode": "0451"
+                },
+                {
+                    "name": "五大连池市",
+                    "adCode": "231182",
+                    "cityCode": "0456"
+                },
+                {
+                    "name": "五家渠市",
+                    "adCode": "659004",
+                    "cityCode": "1994"
+                },
+                {
+                    "name": "五指山市",
+                    "adCode": "469001",
+                    "cityCode": "1897"
+                },
+                {
+                    "name": "武安市",
+                    "adCode": "130481",
+                    "cityCode": "0310"
+                },
+                {
+                    "name": "武冈市",
+                    "adCode": "430581",
+                    "cityCode": "0739"
+                },
+                {
+                    "name": "武汉市",
+                    "adCode": "420100",
+                    "cityCode": "027",
+                    "type": "hot"
+                },
+                {
+                    "name": "武威市",
+                    "adCode": "620600",
+                    "cityCode": "1935"
+                },
+                {
+                    "name": "武穴市",
+                    "adCode": "421182",
+                    "cityCode": "0713"
+                },
+                {
+                    "name": "武夷山市",
+                    "adCode": "350782",
+                    "cityCode": "0599"
+                },
+                {
+                    "name": "舞钢市",
+                    "adCode": "410481",
+                    "cityCode": "0375"
+                }
+            ]
+        },
+        {
+            "letter": "X",
+            "list": [
+                {
+                    "name": "西安市",
+                    "adCode": "610100",
+                    "cityCode": "029",
+                    "type": "hot"
+                },
+                {
+                    "name": "西昌市",
+                    "adCode": "513401",
+                    "cityCode": "0834"
+                },
+                {
+                    "name": "西宁市",
+                    "adCode": "630100",
+                    "cityCode": "0971"
+                },
+                {
+                    "name": "锡林浩特市",
+                    "adCode": "152502",
+                    "cityCode": "0479"
+                },
+                {
+                    "name": "仙桃市",
+                    "adCode": "429004",
+                    "cityCode": "0728"
+                },
+                {
+                    "name": "咸宁市",
+                    "adCode": "421200",
+                    "cityCode": "0715"
+                },
+                {
+                    "name": "咸阳市",
+                    "adCode": "610400",
+                    "cityCode": "0910"
+                },
+                {
+                    "name": "香格里拉市",
+                    "adCode": "533401",
+                    "cityCode": "0887"
+                },
+                {
+                    "name": "湘潭市",
+                    "adCode": "430300",
+                    "cityCode": "0732"
+                },
+                {
+                    "name": "湘乡市",
+                    "adCode": "430381",
+                    "cityCode": "0732"
+                },
+                {
+                    "name": "襄阳市",
+                    "adCode": "420600",
+                    "cityCode": "0710"
+                },
+                {
+                    "name": "项城市",
+                    "adCode": "411681",
+                    "cityCode": "0394"
+                },
+                {
+                    "name": "孝感市",
+                    "adCode": "420900",
+                    "cityCode": "0712"
+                },
+                {
+                    "name": "孝义市",
+                    "adCode": "141181",
+                    "cityCode": "0358"
+                },
+                {
+                    "name": "辛集市",
+                    "adCode": "130181",
+                    "cityCode": "0311"
+                },
+                {
+                    "name": "忻州市",
+                    "adCode": "140900",
+                    "cityCode": "0350"
+                },
+                {
+                    "name": "新乐市",
+                    "adCode": "130184",
+                    "cityCode": "0311"
+                },
+                {
+                    "name": "新密市",
+                    "adCode": "410183",
+                    "cityCode": "0371"
+                },
+                {
+                    "name": "新民市",
+                    "adCode": "210181",
+                    "cityCode": "024"
+                },
+                {
+                    "name": "新泰市",
+                    "adCode": "370982",
+                    "cityCode": "0538"
+                },
+                {
+                    "name": "新乡市",
+                    "adCode": "410700",
+                    "cityCode": "0373"
+                },
+                {
+                    "name": "新沂市",
+                    "adCode": "320381",
+                    "cityCode": "0516"
+                },
+                {
+                    "name": "新余市",
+                    "adCode": "360500",
+                    "cityCode": "0790"
+                },
+                {
+                    "name": "新郑市",
+                    "adCode": "410184",
+                    "cityCode": "0371"
+                },
+                {
+                    "name": "信阳市",
+                    "adCode": "411500",
+                    "cityCode": "0376"
+                },
+                {
+                    "name": "信宜市",
+                    "adCode": "440983",
+                    "cityCode": "0668"
+                },
+                {
+                    "name": "邢台市",
+                    "adCode": "130500",
+                    "cityCode": "0319"
+                },
+                {
+                    "name": "兴城市",
+                    "adCode": "211481",
+                    "cityCode": "0429"
+                },
+                {
+                    "name": "兴化市",
+                    "adCode": "321281",
+                    "cityCode": "0523"
+                },
+                {
+                    "name": "兴宁市",
+                    "adCode": "441481",
+                    "cityCode": "0753"
+                },
+                {
+                    "name": "兴平市",
+                    "adCode": "610481",
+                    "cityCode": "0910"
+                },
+                {
+                    "name": "兴义市",
+                    "adCode": "522301",
+                    "cityCode": "0859"
+                },
+                {
+                    "name": "宿迁市",
+                    "adCode": "321300",
+                    "cityCode": "0527"
+                },
+                {
+                    "name": "宿州市",
+                    "adCode": "341300",
+                    "cityCode": "0557"
+                },
+                {
+                    "name": "徐州市",
+                    "adCode": "320300",
+                    "cityCode": "0516"
+                },
+                {
+                    "name": "许昌市",
+                    "adCode": "411000",
+                    "cityCode": "0374"
+                },
+                {
+                    "name": "宣城市",
+                    "adCode": "341800",
+                    "cityCode": "0563"
+                },
+                {
+                    "name": "宣威市",
+                    "adCode": "530381",
+                    "cityCode": "0874"
+                }
+            ]
+        },
+        {
+            "letter": "Y",
+            "list": [
+                {
+                    "name": "牙克石市",
+                    "adCode": "150782",
+                    "cityCode": "0470"
+                },
+                {
+                    "name": "雅安市",
+                    "adCode": "511800",
+                    "cityCode": "0835"
+                },
+                {
+                    "name": "烟台市",
+                    "adCode": "370600",
+                    "cityCode": "0535"
+                },
+                {
+                    "name": "延安市",
+                    "adCode": "610600",
+                    "cityCode": "0911"
+                },
+                {
+                    "name": "延吉市",
+                    "adCode": "222401",
+                    "cityCode": "1433"
+                },
+                {
+                    "name": "盐城市",
+                    "adCode": "320900",
+                    "cityCode": "0515"
+                },
+                {
+                    "name": "偃师市",
+                    "adCode": "410381",
+                    "cityCode": "0379"
+                },
+                {
+                    "name": "扬中市",
+                    "adCode": "321182",
+                    "cityCode": "0511"
+                },
+                {
+                    "name": "扬州市",
+                    "adCode": "321000",
+                    "cityCode": "0514"
+                },
+                {
+                    "name": "阳春市",
+                    "adCode": "441781",
+                    "cityCode": "0662"
+                },
+                {
+                    "name": "阳江市",
+                    "adCode": "441700",
+                    "cityCode": "0662"
+                },
+                {
+                    "name": "阳泉市",
+                    "adCode": "140300",
+                    "cityCode": "0353"
+                },
+                {
+                    "name": "伊春市",
+                    "adCode": "230700",
+                    "cityCode": "0458"
+                },
+                {
+                    "name": "伊宁市",
+                    "adCode": "654002",
+                    "cityCode": "0999"
+                },
+                {
+                    "name": "仪征市",
+                    "adCode": "321081",
+                    "cityCode": "0514"
+                },
+                {
+                    "name": "宜宾市",
+                    "adCode": "511500",
+                    "cityCode": "0831"
+                },
+                {
+                    "name": "宜昌市",
+                    "adCode": "420500",
+                    "cityCode": "0717"
+                },
+                {
+                    "name": "宜城市",
+                    "adCode": "420684",
+                    "cityCode": "0710"
+                },
+                {
+                    "name": "宜春市",
+                    "adCode": "360900",
+                    "cityCode": "0795"
+                },
+                {
+                    "name": "宜都市",
+                    "adCode": "420581",
+                    "cityCode": "0717"
+                },
+                {
+                    "name": "宜兴市",
+                    "adCode": "320282",
+                    "cityCode": "0510"
+                },
+                {
+                    "name": "宜州市",
+                    "adCode": "451281",
+                    "cityCode": "0778"
+                },
+                {
+                    "name": "义马市",
+                    "adCode": "411281",
+                    "cityCode": "0398"
+                },
+                {
+                    "name": "义乌市",
+                    "adCode": "330782",
+                    "cityCode": "0579"
+                },
+                {
+                    "name": "益阳市",
+                    "adCode": "430900",
+                    "cityCode": "0737"
+                },
+                {
+                    "name": "银川市",
+                    "adCode": "640100",
+                    "cityCode": "0951"
+                },
+                {
+                    "name": "英德市",
+                    "adCode": "441881",
+                    "cityCode": "0763"
+                },
+                {
+                    "name": "鹰潭市",
+                    "adCode": "360600",
+                    "cityCode": "0701"
+                },
+                {
+                    "name": "荥阳市",
+                    "adCode": "410182",
+                    "cityCode": "0371"
+                },
+                {
+                    "name": "营口市",
+                    "adCode": "210800",
+                    "cityCode": "0417"
+                },
+                {
+                    "name": "应城市",
+                    "adCode": "420981",
+                    "cityCode": "0712"
+                },
+                {
+                    "name": "永安市",
+                    "adCode": "350481",
+                    "cityCode": "0598"
+                },
+                {
+                    "name": "永城市",
+                    "adCode": "411481",
+                    "cityCode": "0370"
+                },
+                {
+                    "name": "永济市",
+                    "adCode": "140881",
+                    "cityCode": "0359"
+                },
+                {
+                    "name": "永康市",
+                    "adCode": "330784",
+                    "cityCode": "0579"
+                },
+                {
+                    "name": "永州市",
+                    "adCode": "431100",
+                    "cityCode": "0746"
+                },
+                {
+                    "name": "余姚市",
+                    "adCode": "330281",
+                    "cityCode": "0574"
+                },
+                {
+                    "name": "榆林市",
+                    "adCode": "610800",
+                    "cityCode": "0912"
+                },
+                {
+                    "name": "榆树市",
+                    "adCode": "220182",
+                    "cityCode": "0431"
+                },
+                {
+                    "name": "禹城市",
+                    "adCode": "371482",
+                    "cityCode": "0534"
+                },
+                {
+                    "name": "禹州市",
+                    "adCode": "411081",
+                    "cityCode": "0374"
+                },
+                {
+                    "name": "玉林市",
+                    "adCode": "450900",
+                    "cityCode": "0775"
+                },
+                {
+                    "name": "玉门市",
+                    "adCode": "620981",
+                    "cityCode": "0937"
+                },
+                {
+                    "name": "玉树市",
+                    "adCode": "632701",
+                    "cityCode": "0976"
+                },
+                {
+                    "name": "玉溪市",
+                    "adCode": "530400",
+                    "cityCode": "0877"
+                },
+                {
+                    "name": "沅江市",
+                    "adCode": "430981",
+                    "cityCode": "0737"
+                },
+                {
+                    "name": "原平市",
+                    "adCode": "140981",
+                    "cityCode": "0350"
+                },
+                {
+                    "name": "岳阳市",
+                    "adCode": "430600",
+                    "cityCode": "0730"
+                },
+                {
+                    "name": "云浮市",
+                    "adCode": "445300",
+                    "cityCode": "0766"
+                },
+                {
+                    "name": "运城市",
+                    "adCode": "140800",
+                    "cityCode": "0359"
+                }
+            ]
+        },
+        {
+            "letter": "Z",
+            "list": [
+                {
+                    "name": "枣阳市",
+                    "adCode": "420683",
+                    "cityCode": "0710"
+                },
+                {
+                    "name": "枣庄市",
+                    "adCode": "370400",
+                    "cityCode": "0632"
+                },
+                {
+                    "name": "扎兰屯市",
+                    "adCode": "150783",
+                    "cityCode": "0470"
+                },
+                {
+                    "name": "湛江市",
+                    "adCode": "440800",
+                    "cityCode": "0759"
+                },
+                {
+                    "name": "张家港市",
+                    "adCode": "320582",
+                    "cityCode": "0512"
+                },
+                {
+                    "name": "张家界市",
+                    "adCode": "430800",
+                    "cityCode": "0744"
+                },
+                {
+                    "name": "张家口市",
+                    "adCode": "130700",
+                    "cityCode": "0313"
+                },
+                {
+                    "name": "张掖市",
+                    "adCode": "620700",
+                    "cityCode": "0936"
+                },
+                {
+                    "name": "漳平市",
+                    "adCode": "350881",
+                    "cityCode": "0597"
+                },
+                {
+                    "name": "漳州市",
+                    "adCode": "350600",
+                    "cityCode": "0596"
+                },
+                {
+                    "name": "樟树市",
+                    "adCode": "360982",
+                    "cityCode": "0795"
+                },
+                {
+                    "name": "招远市",
+                    "adCode": "370685",
+                    "cityCode": "0535"
+                },
+                {
+                    "name": "昭通市",
+                    "adCode": "530600",
+                    "cityCode": "0870"
+                },
+                {
+                    "name": "肇东市",
+                    "adCode": "231282",
+                    "cityCode": "0455"
+                },
+                {
+                    "name": "肇庆市",
+                    "adCode": "441200",
+                    "cityCode": "0758"
+                },
+                {
+                    "name": "镇江市",
+                    "adCode": "321100",
+                    "cityCode": "0511"
+                },
+                {
+                    "name": "郑州市",
+                    "adCode": "410100",
+                    "cityCode": "0371",
+                    "type": "hot"
+                },
+                {
+                    "name": "枝江市",
+                    "adCode": "420583",
+                    "cityCode": "0717"
+                },
+                {
+                    "name": "中山市",
+                    "adCode": "442000",
+                    "cityCode": "0760"
+                },
+                {
+                    "name": "中卫市",
+                    "adCode": "640500",
+                    "cityCode": "1953"
+                },
+                {
+                    "name": "钟祥市",
+                    "adCode": "420881",
+                    "cityCode": "0724"
+                },
+                {
+                    "name": "舟山市",
+                    "adCode": "330900",
+                    "cityCode": "0580"
+                },
+                {
+                    "name": "周口市",
+                    "adCode": "411600",
+                    "cityCode": "0394"
+                },
+                {
+                    "name": "珠海市",
+                    "adCode": "440400",
+                    "cityCode": "0756"
+                },
+                {
+                    "name": "株洲市",
+                    "adCode": "430200",
+                    "cityCode": "0733"
+                },
+                {
+                    "name": "诸城市",
+                    "adCode": "370782",
+                    "cityCode": "0536"
+                },
+                {
+                    "name": "诸暨市",
+                    "adCode": "330681",
+                    "cityCode": "0575"
+                },
+                {
+                    "name": "驻马店市",
+                    "adCode": "411700",
+                    "cityCode": "0396"
+                },
+                {
+                    "name": "庄河市",
+                    "adCode": "210283",
+                    "cityCode": "0411"
+                },
+                {
+                    "name": "涿州市",
+                    "adCode": "130681",
+                    "cityCode": "0312"
+                },
+                {
+                    "name": "资兴市",
+                    "adCode": "431081",
+                    "cityCode": "0735"
+                },
+                {
+                    "name": "资阳市",
+                    "adCode": "512000",
+                    "cityCode": "0832"
+                },
+                {
+                    "name": "淄博市",
+                    "adCode": "370300",
+                    "cityCode": "0533"
+                },
+                {
+                    "name": "自贡市",
+                    "adCode": "510300",
+                    "cityCode": "0813"
+                },
+                {
+                    "name": "邹城市",
+                    "adCode": "370883",
+                    "cityCode": "0537"
+                },
+                {
+                    "name": "遵化市",
+                    "adCode": "130281",
+                    "cityCode": "0315"
+                },
+                {
+                    "name": "遵义市",
+                    "adCode": "520300",
+                    "cityCode": "0852"
+                }
+            ]
+        }
+    ]
+}

+ 15 - 9
src/components/Upload/Imgs.vue

@@ -69,7 +69,7 @@ interface UploadFileProps {
   disabled?: boolean; // 是否禁用上传组件 ==> 非必传(默认为 false)
   disabled?: boolean; // 是否禁用上传组件 ==> 非必传(默认为 false)
   limit?: number; // 最大图片上传数 ==> 非必传(默认为 5张)
   limit?: number; // 最大图片上传数 ==> 非必传(默认为 5张)
   fileSize?: number; // 图片大小限制 ==> 非必传(默认为 5M)
   fileSize?: number; // 图片大小限制 ==> 非必传(默认为 5M)
-  fileType?: File.ImageMimeType[]; // 图片类型限制 ==> 非必传(默认为 ["image/jpeg", "image/png", "image/gif"])
+  fileType?: string[]; // 接受的 MIME(图片 + 可选视频)==> 非必传
   height?: string; // 组件高度 ==> 非必传(默认为 150px)
   height?: string; // 组件高度 ==> 非必传(默认为 150px)
   width?: string; // 组件宽度 ==> 非必传(默认为 150px)
   width?: string; // 组件宽度 ==> 非必传(默认为 150px)
   borderRadius?: string; // 组件边框圆角 ==> 非必传(默认为 8px)
   borderRadius?: string; // 组件边框圆角 ==> 非必传(默认为 8px)
@@ -85,7 +85,7 @@ const props = withDefaults(defineProps<UploadFileProps>(), {
   disabled: false,
   disabled: false,
   limit: 5,
   limit: 5,
   fileSize: 5,
   fileSize: 5,
-  fileType: () => ["image/jpeg", "image/png", "image/gif"],
+  fileType: () => ["image/jpeg", "image/png", "image/gif", "video/mp4", "video/webm", "video/quicktime", "video/ogg"],
   height: "150px",
   height: "150px",
   width: "150px",
   width: "150px",
   borderRadius: "8px",
   borderRadius: "8px",
@@ -160,22 +160,28 @@ const isVideoFile = (file: UploadFile) => {
  * */
  * */
 const beforeUpload: UploadProps["beforeUpload"] = rawFile => {
 const beforeUpload: UploadProps["beforeUpload"] = rawFile => {
   const imgSize = rawFile.size / 1024 / 1024 < props.fileSize;
   const imgSize = rawFile.size / 1024 / 1024 < props.fileSize;
-  const imgType = props.fileType.includes(rawFile.type as File.ImageMimeType);
-  if (!imgType)
+  const acceptVideo = props.fileType.some(t => String(t).startsWith("video/"));
+  const byNameVideo = /\.(mp4|m4v|webm|ogg|mov)(\?.*)?$/i.test(rawFile.name || "");
+  const mimeVideo = typeof rawFile.type === "string" && rawFile.type.startsWith("video/");
+  const looseVideoMime =
+    acceptVideo && byNameVideo && (!rawFile.type || rawFile.type === "application/octet-stream" || mimeVideo);
+  const typeListed = props.fileType.includes(rawFile.type);
+  const okType = typeListed || looseVideoMime;
+  if (!okType)
     ElNotification({
     ElNotification({
       title: "温馨提示",
       title: "温馨提示",
-      message: "上传图片不符合所需的格式!",
+      message: "上传文件不符合所需的格式!",
       type: "warning"
       type: "warning"
     });
     });
   if (!imgSize)
   if (!imgSize)
     setTimeout(() => {
     setTimeout(() => {
       ElNotification({
       ElNotification({
         title: "温馨提示",
         title: "温馨提示",
-        message: `上传图片大小不能超过 ${props.fileSize}M!`,
+        message: `上传文件大小不能超过 ${props.fileSize}M!`,
         type: "warning"
         type: "warning"
       });
       });
     }, 0);
     }, 0);
-  return imgType && imgSize;
+  return okType && imgSize;
 };
 };
 
 
 /**
 /**
@@ -333,7 +339,7 @@ const handleImageLoad = (event: Event) => {
 const uploadError = () => {
 const uploadError = () => {
   ElNotification({
   ElNotification({
     title: "温馨提示",
     title: "温馨提示",
-    message: "图片上传失败,请您重新上传!",
+    message: "上传失败,请您重新上传!",
     type: "error"
     type: "error"
   });
   });
 };
 };
@@ -344,7 +350,7 @@ const uploadError = () => {
 const handleExceed = () => {
 const handleExceed = () => {
   ElNotification({
   ElNotification({
     title: "温馨提示",
     title: "温馨提示",
-    message: `当前最多只能上传 ${props.limit} 张图片,请移除后上传!`,
+    message: `当前最多只能上传 ${props.limit} 个文件,请移除后上传!`,
     type: "warning"
     type: "warning"
   });
   });
 };
 };

+ 6 - 20
src/stores/modules/auth.ts

@@ -75,8 +75,8 @@ export const useAuthStore = defineStore({
                 menu.meta.isHide = businessSection !== 2;
                 menu.meta.isHide = businessSection !== 2;
                 break;
                 break;
               case "设施与服务":
               case "设施与服务":
-                // 只在洗浴汗蒸(4) 和 运动健身(7) 时显示设施与服务
-                menu.meta.isHide = ![4, 7].includes(businessSection);
+                // 特色美食(1) 不显示设施与服务
+                menu.meta.isHide = businessSection !== 1;
                 break;
                 break;
               case "门店基础信息":
               case "门店基础信息":
               case "门店头图":
               case "门店头图":
@@ -136,24 +136,10 @@ export const useAuthStore = defineStore({
             }
             }
           }
           }
 
 
-          // 处理子菜单
-          // if (menu.children && menu.children.length > 0) {
-          //   // 检查子菜单中是否有需要显示的菜单项
-          //   let hasVisibleChild = false;
-          //   menu.children.forEach((child: any) => {
-          //     if (!child.meta?.isHide) {
-          //       hasVisibleChild = true;
-          //     }
-          //   });
-
-          //   // 如果父菜单基础信息、头图、相册本身被隐藏,但有可见子菜单,则显示父菜单
-          //   if (menu.meta?.isHide && hasVisibleChild) {
-          //     menu.meta.isHide = false;
-          //   }
-
-          //   // 递归处理子菜单
-          //   processMenus(menu.children);
-          // }
+          // 递归处理子菜单:switch 按 meta.title 匹配,子级(如「设施与服务」在「基础设施服务」下)否则永远走不到
+          if (menu.children?.length) {
+            processMenus(menu.children);
+          }
         });
         });
       };
       };
 
 

+ 8 - 0
src/typings/global.d.ts

@@ -62,6 +62,14 @@ declare interface ViteEnv {
   VITE_CRYPTO_KEY: string;
   VITE_CRYPTO_KEY: string;
   VITE_CRYPTO_IV: string;
   VITE_CRYPTO_IV: string;
   VITE_WS_BASE?: string;
   VITE_WS_BASE?: string;
+  /** Tus 上传服务根(可选,不配则开发走 /ai-upload 代理、生产走 upload.ailien.shop) */
+  VITE_AI_UPLOAD_BASE?: string;
+  /** AI 审核服务根(可选,不配则开发走 /ai-moderate 代理) */
+  VITE_AI_MODERATE_BASE?: string;
+  /** 上传完成后对外访问 URL 前缀,默认 http://upload.ailien.shop:8088/files */
+  VITE_AI_FILES_PUBLIC_BASE?: string;
+  /** 设为 false 时图片仍走原 OSS / uploadMore,不经过 Tus + AI 审核 */
+  VITE_UPLOAD_IMAGE_AI_MODERATE?: string;
 }
 }
 
 
 interface ImportMetaEnv extends ViteEnv {
 interface ImportMetaEnv extends ViteEnv {

+ 29 - 0
src/utils/commonCommentList.ts

@@ -0,0 +1,29 @@
+/** 将 commonComment/getListBySourceType 等接口的单条评论转为列表展示用结构(兼容旧 storeComment 模板字段) */
+export function normalizeCommonCommentListItem(row: any): any {
+  if (!row || typeof row !== "object") return row;
+  const children = row.childCommonComments ?? row.storeComment ?? [];
+  const normalizedChildren = Array.isArray(children) ? children.map(normalizeCommonCommentListItem) : [];
+  return {
+    ...row,
+    userAvatar: row.userAvatar ?? row.headImg,
+    userName: row.userName ?? row.headName ?? row.headPhone ?? "用户",
+    commentContent: row.commentContent ?? row.content ?? "",
+    isLiked: row.isLiked === true || row.isLiked === 1 || row.isLike === "1" || row.isLike === 1,
+    userImage: row.userImage ?? row.headImg,
+    storeComment: normalizedChildren
+  };
+}
+
+/**
+ * 解析列表接口 data:支持 data 为数组,或分页 records
+ */
+export function normalizeCommonCommentListResponse(resData: unknown): any[] {
+  if (Array.isArray(resData)) return resData.map(normalizeCommonCommentListItem);
+  const rec = (resData as { records?: unknown })?.records;
+  if (Array.isArray(rec)) return rec.map(normalizeCommonCommentListItem);
+  return [];
+}
+
+export function countTopAndNestedComments(list: { storeComment?: unknown[] }[]): number {
+  return list.reduce((n, c) => n + 1 + (Array.isArray(c.storeComment) ? c.storeComment.length : 0), 0);
+}

+ 20 - 0
src/utils/config.ts

@@ -0,0 +1,20 @@
+/**
+ * AI Tus 上传与内容审核服务基址(与 uni 端逻辑对齐,适配 Web)
+ * 开发环境默认走 Vite 代理前缀,需在 .env.development 的 VITE_PROXY 中配置 /ai-upload、/ai-moderate
+ */
+const trimSlash = (s: string) => s.replace(/\/$/, "");
+
+export const BASE_AI_URL = trimSlash(
+  String(import.meta.env.VITE_AI_UPLOAD_BASE || "").trim() ||
+    (import.meta.env.DEV ? "/ai-upload" : "https://upload.ailien.shop:8443")
+);
+
+export const BASE_AI_MODERATE_URL = trimSlash(
+  String(import.meta.env.VITE_AI_MODERATE_BASE || "").trim() ||
+    (import.meta.env.DEV ? "/ai-moderate" : "https://verify.ailien.shop:8444")
+);
+
+/** 上传完成后对外可访问的文件 URL:`${AI_UPLOAD_FILES_PUBLIC_BASE}/${uploadId}` */
+export const AI_UPLOAD_FILES_PUBLIC_BASE = trimSlash(
+  String(import.meta.env.VITE_AI_FILES_PUBLIC_BASE || "").trim() || "https://upload.ailien.shop:8443/files"
+);

+ 7 - 7
src/views/accountRoleManagement/roleManagement/create.vue

@@ -146,13 +146,13 @@ const transformMenuData = (menuList: MenuItem[]): any[] => {
       node.children = transformMenuData(menu.children);
       node.children = transformMenuData(menu.children);
     }
     }
     // 判断是否是门店装修
     // 判断是否是门店装修
-    if (localGet("storeTickets") == 0) {
-      if (menu.menuName === "门店装修") {
-        node.disabled = true;
-        node.disableByStoreDecorate = true;
-        if (node.children?.length) setStoreDecorateDisabledRecursive(node.children);
-      }
-    }
+    // if (localGet("storeTickets") == 0) {
+    //   if (menu.menuName === "门店装修") {
+    //     node.disabled = true;
+    //     node.disableByStoreDecorate = true;
+    //     if (node.children?.length) setStoreDecorateDisabledRecursive(node.children);
+    //   }
+    // }
 
 
     return node;
     return node;
   });
   });

+ 31 - 21
src/views/appoinmentManagement/appoinmentInfo.vue

@@ -6,7 +6,12 @@
         <span class="filter-label">姓名</span>
         <span class="filter-label">姓名</span>
         <el-input v-model="searchForm.reservationUserName" placeholder="请输入姓名" clearable style="width: 160px" />
         <el-input v-model="searchForm.reservationUserName" placeholder="请输入姓名" clearable style="width: 160px" />
         <span class="filter-label">状态</span>
         <span class="filter-label">状态</span>
-        <el-select v-model="searchForm.orderStatus" placeholder="请选择" clearable style="width: 180px">
+        <el-select
+          v-model="searchForm.orderStatus"
+          clearable
+          style="width: 180px"
+          @clear="searchForm.orderStatus = STATUS_FILTER_ALL"
+        >
           <el-option
           <el-option
             v-for="opt in statusOptions"
             v-for="opt in statusOptions"
             :key="`${opt.label}-${String(opt.value)}`"
             :key="`${opt.label}-${String(opt.value)}`"
@@ -65,21 +70,17 @@
           >
           >
             <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
             <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
           </template>
           </template>
+          <!-- 已过期(3) 且结束未超 3 小时:付费先判断(退款+删除),否则仅删除;顺序不可颠倒,否则宽条件会吃掉窄条件 -->
           <template
           <template
-            v-else-if="
-              (isOrderStatus(scope.row, 2) || isOrderStatus(scope.row, 7) || isOrderStatus(scope.row, 3)) &&
-              !isMoreThanThreeHoursAfterEnd(scope.row)
-            "
+            v-else-if="isOrderStatus(scope.row, 3) && !isMoreThanThreeHoursAfterEnd(scope.row) && orderCostTypeIsPaid(scope.row)"
           >
           >
+            <el-button link type="primary" @click="handleRefund(scope.row)"> 退款 </el-button>
             <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
             <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
           </template>
           </template>
-          <template v-else-if="isOrderStatus(scope.row, 7) && !isMoreThanThreeHoursAfterEnd(scope.row)">
+          <template v-else-if="isOrderStatus(scope.row, 3) && !isMoreThanThreeHoursAfterEnd(scope.row)">
             <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
             <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
           </template>
           </template>
-          <template
-            v-else-if="isOrderStatus(scope.row, 3) && !isMoreThanThreeHoursAfterEnd(scope.row) && orderCostTypeIsPaid(scope.row)"
-          >
-            <el-button link type="primary" @click="handleRefund(scope.row)"> 退款 </el-button>
+          <template v-else-if="isOrderStatus(scope.row, 7) && !isMoreThanThreeHoursAfterEnd(scope.row)">
             <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
             <el-button link type="primary" @click="handleDelete(scope.row)"> 删除 </el-button>
           </template>
           </template>
           <template v-else-if="isOrderStatus(scope.row, 4) && !orderCostTypeIsPaid(scope.row)">
           <template v-else-if="isOrderStatus(scope.row, 4) && !orderCostTypeIsPaid(scope.row)">
@@ -97,13 +98,19 @@
     </ProTable>
     </ProTable>
 
 
     <!-- 查看原因 -->
     <!-- 查看原因 -->
-    <el-dialog v-model="reasonDialogVisible" title="原因" width="420px" append-to-body destroy-on-close>
-      <div class="reason-dialog-body">取消原因:</div>
-      <div class="reason-dialog-body">
+    <el-dialog
+      v-model="reasonDialogVisible"
+      title="取消原因"
+      width="420px"
+      append-to-body
+      destroy-on-close
+      class="cancel-reason-dialog"
+    >
+      <div class="reason-dialog-body" style="padding-left: 20px">
         {{ reasonDialogText || "—" }}
         {{ reasonDialogText || "—" }}
       </div>
       </div>
       <template #footer>
       <template #footer>
-        <el-button type="primary" @click="reasonDialogVisible = false"> 知道了 </el-button>
+        <el-button type="primary" @click="reasonDialogVisible = false"> 返回 </el-button>
       </template>
       </template>
     </el-dialog>
     </el-dialog>
 
 
@@ -237,9 +244,11 @@ const columns: ColumnProps<ReservationRow>[] = [
  */
  */
 const STATUS_FILTER_MERCHANT_CANCEL = "merchant_cancel";
 const STATUS_FILTER_MERCHANT_CANCEL = "merchant_cancel";
 const STATUS_FILTER_USER_CANCEL = "user_cancel";
 const STATUS_FILTER_USER_CANCEL = "user_cancel";
+/** 占位选项值:勿用 "",el-select 常无法匹配空串而不显示「全部」 */
+const STATUS_FILTER_ALL = "__all__";
 
 
 const statusOptions: { label: string; value: number | string }[] = [
 const statusOptions: { label: string; value: number | string }[] = [
-  { label: "全部", value: "" },
+  { label: "全部", value: STATUS_FILTER_ALL },
   { label: "待使用", value: 1 },
   { label: "待使用", value: 1 },
   { label: "退款成功", value: 7 },
   { label: "退款成功", value: 7 },
   { label: "商家取消", value: STATUS_FILTER_MERCHANT_CANCEL },
   { label: "商家取消", value: STATUS_FILTER_MERCHANT_CANCEL },
@@ -281,14 +290,14 @@ const initParam = reactive({
 /** 已生效的查询条件(点击搜索后写入;接口字段 reservationUserName、orderStatus) */
 /** 已生效的查询条件(点击搜索后写入;接口字段 reservationUserName、orderStatus) */
 const listFilter = reactive({
 const listFilter = reactive({
   reservationUserName: "",
   reservationUserName: "",
-  orderStatus: "" as number | string,
+  orderStatus: STATUS_FILTER_ALL as number | string,
   startDate: "",
   startDate: "",
   endDate: ""
   endDate: ""
 });
 });
 
 
 const searchForm = reactive({
 const searchForm = reactive({
   reservationUserName: "",
   reservationUserName: "",
-  orderStatus: "" as number | string,
+  orderStatus: STATUS_FILTER_ALL as number | string,
   dateRange: [] as string[]
   dateRange: [] as string[]
 });
 });
 
 
@@ -478,7 +487,7 @@ async function getTableList(params: any) {
     req.reservationUserName = listFilter.reservationUserName.trim();
     req.reservationUserName = listFilter.reservationUserName.trim();
   }
   }
   const sf = listFilter.orderStatus;
   const sf = listFilter.orderStatus;
-  if (sf !== undefined && sf !== "" && sf !== null) {
+  if (sf !== undefined && sf !== "" && sf !== null && sf !== STATUS_FILTER_ALL) {
     if (sf === STATUS_FILTER_USER_CANCEL || sf === STATUS_FILTER_MERCHANT_CANCEL) {
     if (sf === STATUS_FILTER_USER_CANCEL || sf === STATUS_FILTER_MERCHANT_CANCEL) {
       req.orderStatus = 4;
       req.orderStatus = 4;
     } else {
     } else {
@@ -529,10 +538,10 @@ function handleSearch() {
 
 
 function handleReset() {
 function handleReset() {
   searchForm.reservationUserName = "";
   searchForm.reservationUserName = "";
-  searchForm.orderStatus = "";
+  searchForm.orderStatus = STATUS_FILTER_ALL;
   searchForm.dateRange = [];
   searchForm.dateRange = [];
   listFilter.reservationUserName = "";
   listFilter.reservationUserName = "";
-  listFilter.orderStatus = "";
+  listFilter.orderStatus = STATUS_FILTER_ALL;
   listFilter.startDate = "";
   listFilter.startDate = "";
   listFilter.endDate = "";
   listFilter.endDate = "";
   proTable.value?.getTableList();
   proTable.value?.getTableList();
@@ -654,7 +663,7 @@ function handleDelete(row: ReservationRow) {
   })
   })
     .then(async () => {
     .then(async () => {
       try {
       try {
-        await reservationDelete({ id: row.id });
+        await reservationDelete({ reservationId: row.id });
         ElMessage.success("删除成功");
         ElMessage.success("删除成功");
         proTable.value?.getTableList();
         proTable.value?.getTableList();
       } catch (e: any) {
       } catch (e: any) {
@@ -766,6 +775,7 @@ function handleRefund(row: ReservationRow) {
   color: #606266;
   color: #606266;
 }
 }
 .cancel-reason-dialog.el-dialog .el-dialog__body {
 .cancel-reason-dialog.el-dialog .el-dialog__body {
+  height: 300px;
   padding-top: 8px;
   padding-top: 8px;
 }
 }
 .cancel-reason-form {
 .cancel-reason-form {

+ 7 - 4
src/views/appoinmentManagement/classifyManagement.vue

@@ -33,6 +33,7 @@
       v-model="dialogVisible"
       v-model="dialogVisible"
       :title="editId == null ? '新建分类' : '编辑分类'"
       :title="editId == null ? '新建分类' : '编辑分类'"
       width="480px"
       width="480px"
+      class="classify-edit-dialog"
       append-to-body
       append-to-body
       destroy-on-close
       destroy-on-close
       @close="onDialogClose"
       @close="onDialogClose"
@@ -438,12 +439,14 @@ async function submitForm() {
   }
   }
 }
 }
 </script>
 </script>
-
-<style scoped lang="scss">
-:deep(.el-dialog__body) {
+<!-- append-to-body 时弹窗在 body 下,不是 .classify-management 子节点,需用 dialog 自身 class 命中 -->
+<style lang="scss">
+.classify-edit-dialog .el-dialog__body {
+  box-sizing: border-box;
   height: 400px;
   height: 400px;
-  border: 1px solid red;
 }
 }
+</style>
+<style scoped lang="scss">
 .classify-management {
 .classify-management {
   padding: 0;
   padding: 0;
 }
 }

+ 6 - 1
src/views/appoinmentManagement/tableManagement.vue

@@ -544,7 +544,12 @@ onMounted(() => {
   loadCategories();
   loadCategories();
 });
 });
 </script>
 </script>
-
+<style lang="scss">
+.table-management-dialog .el-dialog__body {
+  box-sizing: border-box;
+  height: 300px;
+}
+</style>
 <style scoped lang="scss">
 <style scoped lang="scss">
 .table-management {
 .table-management {
   padding: 0;
   padding: 0;

+ 2 - 2
src/views/businessData/compare.vue

@@ -148,7 +148,7 @@
               </div>
               </div>
             </div>
             </div>
           </el-tab-pane>
           </el-tab-pane>
-          <el-tab-pane label="代金券" name="voucher">
+          <!-- <el-tab-pane label="代金券1" name="voucher">
             <div class="compare-cards">
             <div class="compare-cards">
               <div v-for="item in voucherCompareList" :key="item.key" class="compare-card">
               <div v-for="item in voucherCompareList" :key="item.key" class="compare-card">
                 <div class="card-title">
                 <div class="card-title">
@@ -181,7 +181,7 @@
                 </div>
                 </div>
               </div>
               </div>
             </div>
             </div>
-          </el-tab-pane>
+          </el-tab-pane> -->
           <el-tab-pane label="服务质量" name="service">
           <el-tab-pane label="服务质量" name="service">
             <div class="compare-cards">
             <div class="compare-cards">
               <div v-for="item in serviceCompareList" :key="item.key" class="compare-card">
               <div v-for="item in serviceCompareList" :key="item.key" class="compare-card">

+ 493 - 0
src/views/businessInfo/accountInfo.vue

@@ -0,0 +1,493 @@
+<template>
+  <div class="account-info-page">
+    <h1 class="page-title">结算账户</h1>
+
+    <section class="form-block">
+      <h2 class="section-head">
+        <span class="section-bar" aria-hidden="true" />
+        结算账户
+      </h2>
+
+      <el-form
+        ref="formRef"
+        class="account-form"
+        :model="form"
+        :rules="rules"
+        label-width="120px"
+        require-asterisk-position="right"
+        label-position="right"
+      >
+        <el-form-item label="账户户名" prop="accountName">
+          <el-input v-model="form.accountName" placeholder="请输入账户户名" clearable maxlength="64" style="max-width: 480px" />
+        </el-form-item>
+
+        <el-form-item label="账户类型" prop="accountType">
+          <el-radio-group v-model="form.accountType" class="account-type-radio">
+            <el-radio :value="BANK_ACCOUNT_TYPE_CORPORATE"> 对公账户 </el-radio>
+            <el-radio :value="BANK_ACCOUNT_TYPE_PERSONAL"> 个人储蓄卡 </el-radio>
+          </el-radio-group>
+        </el-form-item>
+
+        <el-form-item label="银行账号" prop="bankAccountNo">
+          <div class="field-stack">
+            <el-input
+              v-model="form.bankAccountNo"
+              placeholder="请输入开户银行账号"
+              clearable
+              maxlength="32"
+              style="max-width: 480px"
+            />
+            <p class="field-tip">
+              {{ bankAccountTip }}
+            </p>
+          </div>
+        </el-form-item>
+
+        <el-form-item label="开户银行" prop="bankCode">
+          <div class="field-stack">
+            <el-popover
+              v-model:visible="bankPickerVisible"
+              placement="bottom-start"
+              :width="580"
+              trigger="click"
+              popper-class="bank-picker-popper"
+            >
+              <template #reference>
+                <el-input
+                  readonly
+                  :model-value="selectedBankLabel"
+                  placeholder="请选择开户银行"
+                  style="max-width: 480px"
+                  class="bank-trigger-input"
+                  :class="{ 'is-focus-like': bankPickerVisible }"
+                >
+                  <template #suffix>
+                    <el-icon class="el-select__caret">
+                      <ArrowDown />
+                    </el-icon>
+                  </template>
+                </el-input>
+              </template>
+              <div class="bank-picker" @click.stop>
+                <el-radio-group v-model="bankTab" size="small" class="bank-tab-group">
+                  <el-radio-button value="common"> 常用银行 </el-radio-button>
+                  <el-radio-button value="A-F"> ABCDEF </el-radio-button>
+                  <el-radio-button value="G-L"> GHJKL </el-radio-button>
+                  <el-radio-button value="M-P"> MNOP </el-radio-button>
+                  <el-radio-button value="Q-U"> QRSTU </el-radio-button>
+                  <el-radio-button value="V-Z"> VWXYZ </el-radio-button>
+                </el-radio-group>
+                <div class="bank-grid-wrap">
+                  <div class="bank-grid">
+                    <button
+                      v-for="b in filteredBanks"
+                      :key="b.code"
+                      type="button"
+                      class="bank-cell"
+                      :class="{ 'is-active': form.bankCode === b.code }"
+                      @click="selectBank(b)"
+                    >
+                      <span class="bank-logo" :style="{ background: b.color }">{{ b.logoText }}</span>
+                      <span class="bank-name">{{ b.shortName }}</span>
+                    </button>
+                  </div>
+                </div>
+              </div>
+            </el-popover>
+          </div>
+        </el-form-item>
+      </el-form>
+    </section>
+
+    <div class="footer-actions">
+      <el-button @click="onBack"> 返回 </el-button>
+      <el-button type="primary" class="btn-next" :loading="submitLoading" @click="onSubmit"> 确定 </el-button>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed, nextTick, onMounted, reactive, ref, watch } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
+import type { FormInstance, FormRules } from "element-plus";
+import { ArrowDown } from "@element-plus/icons-vue";
+import { localGet, localSet } from "@/utils/index";
+
+const BUSINESS_DATA_CACHE_KEY = "businessData";
+
+const BANK_ACCOUNT_TYPE_CORPORATE = "BANK_ACCOUNT_TYPE_CORPORATE" as const;
+const BANK_ACCOUNT_TYPE_PERSONAL = "BANK_ACCOUNT_TYPE_PERSONAL" as const;
+
+const formRef = ref<FormInstance>();
+const submitLoading = ref(false);
+const bankPickerVisible = ref(false);
+const bankTab = ref("common");
+const route = useRoute();
+const router = useRouter();
+
+export interface BankItem {
+  code: string;
+  shortName: string;
+  tabKey: "common" | "A-F" | "G-L" | "M-P" | "Q-U" | "V-Z";
+  logoText: string;
+  color: string;
+}
+
+/** 演示数据:常用 + 按首字母分组(与示意图「标签 + 网格」一致) */
+const BANK_LIST: BankItem[] = [
+  { code: "ICBC", shortName: "工商银行", tabKey: "common", logoText: "工", color: "#c62828" },
+  { code: "ABC", shortName: "农业银行", tabKey: "common", logoText: "农", color: "#2e7d32" },
+  { code: "BOC", shortName: "中国银行", tabKey: "common", logoText: "中", color: "#b71c1c" },
+  { code: "CCB", shortName: "建设银行", tabKey: "common", logoText: "建", color: "#1565c0" },
+  { code: "COMM", shortName: "交通银行", tabKey: "common", logoText: "交", color: "#283593" },
+  { code: "PSBC", shortName: "邮储银行", tabKey: "common", logoText: "邮", color: "#00695c" },
+  { code: "CMB", shortName: "招商银行", tabKey: "common", logoText: "招", color: "#c62828" },
+  { code: "SPDB", shortName: "浦发银行", tabKey: "common", logoText: "浦", color: "#0d47a1" },
+  { code: "CIB", shortName: "兴业银行", tabKey: "common", logoText: "兴", color: "#1565c0" },
+  { code: "CMBC", shortName: "民生银行", tabKey: "common", logoText: "民", color: "#4e342e" },
+  { code: "HXB", shortName: "华夏银行", tabKey: "G-L", logoText: "华", color: "#d84315" },
+  { code: "GDB", shortName: "广发银行", tabKey: "G-L", logoText: "广", color: "#c62828" },
+  { code: "PAB", shortName: "平安银行", tabKey: "M-P", logoText: "平", color: "#f57f17" },
+  { code: "CITIC", shortName: "中信银行", tabKey: "M-P", logoText: "信", color: "#c62828" },
+  { code: "CEB", shortName: "光大银行", tabKey: "G-L", logoText: "光", color: "#6a1b9a" },
+  { code: "BOSH", shortName: "上海银行", tabKey: "G-L", logoText: "上", color: "#283593" },
+  { code: "BRCB", shortName: "北京银行", tabKey: "A-F", logoText: "京", color: "#c62828" },
+  { code: "NJCB", shortName: "南京银行", tabKey: "M-P", logoText: "宁", color: "#c62828" },
+  { code: "HZCB", shortName: "杭州银行", tabKey: "G-L", logoText: "杭", color: "#1565c0" },
+  { code: "ASB", shortName: "鞍山银行", tabKey: "A-F", logoText: "鞍", color: "#37474f" },
+  { code: "BSB", shortName: "包商银行", tabKey: "A-F", logoText: "包", color: "#455a64" },
+  { code: "QDCCB", shortName: "青岛银行", tabKey: "M-P", logoText: "青", color: "#0d47a1" },
+  { code: "WFCB", shortName: "潍坊银行", tabKey: "V-Z", logoText: "潍", color: "#1565c0" },
+  { code: "WZCB", shortName: "温州银行", tabKey: "V-Z", logoText: "温", color: "#c62828" },
+  { code: "XMBANK", shortName: "厦门银行", tabKey: "Q-U", logoText: "厦", color: "#00695c" },
+  { code: "YTBANK", shortName: "烟台银行", tabKey: "V-Z", logoText: "烟", color: "#37474f" },
+  { code: "ZZBANK", shortName: "郑州银行", tabKey: "V-Z", logoText: "郑", color: "#c62828" }
+];
+
+const form = reactive({
+  accountName: "",
+  accountType: "BANK_ACCOUNT_TYPE_CORPORATE" as "BANK_ACCOUNT_TYPE_CORPORATE" | "BANK_ACCOUNT_TYPE_PERSONAL",
+  bankAccountNo: "",
+  bankCode: ""
+});
+
+const selectedBankLabel = computed(() => {
+  if (!form.bankCode) return "";
+  const b = BANK_LIST.find(x => x.code === form.bankCode);
+  return b ? b.shortName : "";
+});
+
+const bankAccountTip = computed(() => {
+  if (form.accountType === "BANK_ACCOUNT_TYPE_CORPORATE") {
+    return "请务必填写与账户户名一致的对公银行账户。";
+  }
+  return "请务必填写与账户户名一致的个人储蓄卡账号。";
+});
+
+const tabToKey = computed<BankItem["tabKey"] | "common">(() => {
+  const m: Record<string, BankItem["tabKey"] | "common"> = {
+    common: "common",
+    "A-F": "A-F",
+    "G-L": "G-L",
+    "M-P": "M-P",
+    "Q-U": "Q-U",
+    "V-Z": "V-Z"
+  };
+  return m[bankTab.value] ?? "common";
+});
+
+const filteredBanks = computed(() => {
+  const k = tabToKey.value;
+  if (k === "common") return BANK_LIST.filter(b => b.tabKey === "common");
+  return BANK_LIST.filter(b => b.tabKey === k);
+});
+
+const rules: FormRules = {
+  accountName: [{ required: true, message: "请输入账户户名", trigger: "blur" }],
+  accountType: [{ required: true, message: "请选择账户类型", trigger: "change" }],
+  bankAccountNo: [
+    { required: true, message: "请输入银行账号", trigger: "blur" },
+    { pattern: /^[\d\s-]{8,40}$/, message: "请输入有效的银行账号", trigger: "blur" }
+  ],
+  bankCode: [{ required: true, message: "请选择开户银行", trigger: "change" }]
+};
+
+function selectBank(b: BankItem) {
+  form.bankCode = b.code;
+  bankPickerVisible.value = false;
+  formRef.value?.validateField("bankCode").catch(() => {});
+}
+
+function onBack() {
+  router.push({ path: "/businessInfo/industryQualifications", query: { ...route.query } });
+}
+
+function onSaveDraft() {
+  ElMessage.success("草稿已保存(可对接接口)");
+}
+
+/** 账户户名:subject_info.business_license_info.merchant_name */
+function readMerchantNameFromSubjectInfo(): string {
+  const raw = localGet(BUSINESS_DATA_CACHE_KEY) as Record<string, unknown> | null | undefined;
+  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return "";
+  const si = raw.subject_info as Record<string, unknown> | undefined;
+  if (!si || typeof si !== "object" || Array.isArray(si)) return "";
+  const bli = si.business_license_info as Record<string, unknown> | undefined;
+  if (!bli || typeof bli !== "object" || Array.isArray(bli)) return "";
+  return String(bli.merchant_name ?? "").trim();
+}
+
+function resolveBankCodeFromAccountBank(accountBank: string): string {
+  const s = accountBank.trim();
+  if (!s) return "";
+  const byCode = BANK_LIST.find(b => b.code === s);
+  if (byCode) return byCode.code;
+  const byShort = BANK_LIST.find(b => b.shortName === s);
+  if (byShort) return byShort.code;
+  return "";
+}
+
+/** 从缓存 bank_account_info 反显;无户名时用 subject_info 营业执照商户名 */
+function hydrateAccountFormFromBusinessDataCache() {
+  const raw = localGet(BUSINESS_DATA_CACHE_KEY) as Record<string, unknown> | null | undefined;
+  if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
+    const m = readMerchantNameFromSubjectInfo();
+    if (m) form.accountName = m;
+    return;
+  }
+  const ba = raw.bank_account_info as Record<string, unknown> | undefined;
+  if (!ba || typeof ba !== "object" || Array.isArray(ba)) {
+    const m = readMerchantNameFromSubjectInfo();
+    if (m) form.accountName = m;
+    return;
+  }
+
+  const accName = String(ba.account_name ?? "").trim();
+  form.accountName = accName || readMerchantNameFromSubjectInfo();
+
+  const t = String(ba.bank_account_type ?? "").trim();
+  if (t === BANK_ACCOUNT_TYPE_CORPORATE || t === BANK_ACCOUNT_TYPE_PERSONAL) {
+    form.accountType = t;
+  }
+
+  form.bankAccountNo = String(ba.account_number ?? "").trim();
+
+  const bankLabel = String(ba.account_bank ?? "").trim();
+  form.bankCode = resolveBankCodeFromAccountBank(bankLabel);
+}
+
+onMounted(() => {
+  hydrateAccountFormFromBusinessDataCache();
+  nextTick(() => formRef.value?.clearValidate());
+});
+
+function mergeBankAccountIntoBusinessDataCache() {
+  const prev = localGet(BUSINESS_DATA_CACHE_KEY);
+  const base = prev && typeof prev === "object" && !Array.isArray(prev) ? { ...(prev as Record<string, unknown>) } : {};
+  const prevBa =
+    base.bank_account_info && typeof base.bank_account_info === "object" && !Array.isArray(base.bank_account_info)
+      ? { ...(base.bank_account_info as Record<string, unknown>) }
+      : {};
+
+  const accountBankName = selectedBankLabel.value || String(form.bankCode || "").trim();
+
+  base.bank_account_info = {
+    ...prevBa,
+    bank_account_type: form.accountType,
+    account_bank: accountBankName,
+    account_number: String(form.bankAccountNo || "")
+      .replace(/\s+/g, "")
+      .trim(),
+    account_name: String(form.accountName || "").trim()
+  };
+  localSet(BUSINESS_DATA_CACHE_KEY, base);
+}
+
+async function onSubmit() {
+  if (!formRef.value) return;
+  submitLoading.value = true;
+  try {
+    await formRef.value.validate();
+    mergeBankAccountIntoBusinessDataCache();
+    await router.push({
+      path: "/businessInfo/adminInfo",
+      query: { ...route.query }
+    });
+  } catch {
+    ElMessage.warning("请完善必填信息");
+  } finally {
+    submitLoading.value = false;
+  }
+}
+
+watch(
+  () => form.accountType,
+  () => {
+    formRef.value?.validateField("bankAccountNo").catch(() => {});
+  }
+);
+</script>
+
+<style scoped lang="scss">
+$wechat-green: #07c160;
+.account-info-page {
+  box-sizing: border-box;
+  min-height: 100%;
+  padding: 24px 32px 40px;
+  margin: 0 auto;
+  background: #ffffff;
+}
+.page-title {
+  margin: 0 0 24px;
+  font-size: 20px;
+  font-weight: 600;
+  color: #303133;
+}
+.form-block {
+  margin-bottom: 24px;
+}
+.section-head {
+  display: flex;
+  align-items: center;
+  margin: 0 0 20px;
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+}
+.section-bar {
+  display: inline-block;
+  flex-shrink: 0;
+  width: 4px;
+  height: 16px;
+  margin-right: 8px;
+  background: $wechat-green;
+  border-radius: 2px;
+}
+.account-form {
+  :deep(.el-form-item__label) {
+    font-weight: 500;
+    color: #606266;
+  }
+}
+.field-stack {
+  width: 100%;
+}
+.field-tip {
+  margin: 8px 0 0;
+  font-size: 12px;
+  line-height: 1.65;
+  color: #909399;
+}
+.account-type-radio {
+  :deep(.el-radio__input.is-checked .el-radio__inner) {
+    background: $wechat-green;
+    border-color: $wechat-green;
+  }
+  :deep(.el-radio__input.is-checked + .el-radio__label) {
+    color: #303133;
+  }
+}
+.bank-trigger-input {
+  cursor: pointer;
+  &.is-focus-like {
+    :deep(.el-input__wrapper) {
+      box-shadow: 0 0 0 1px $wechat-green inset;
+    }
+  }
+}
+.footer-actions {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding-top: 24px;
+  margin-top: 16px;
+  border-top: 1px solid #ebeef5;
+}
+.footer-center {
+  display: flex;
+  flex: 1;
+  justify-content: center;
+}
+.btn-next {
+  min-width: 100px;
+  background: $wechat-green;
+  border-color: $wechat-green;
+  &:hover {
+    background: #06ad56;
+    border-color: #06ad56;
+  }
+}
+</style>
+
+<style lang="scss">
+$wechat-green: #07c160;
+.bank-picker-popper {
+  padding: 0 !important;
+}
+.bank-picker {
+  .bank-tab-group {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 6px;
+    padding: 8px 4px 4px;
+    :deep(.el-radio-button__inner) {
+      padding: 6px 10px;
+      font-size: 12px;
+    }
+    :deep(.el-radio-button.is-active .el-radio-button__inner) {
+      color: #ffffff;
+      background: $wechat-green;
+      border-color: $wechat-green;
+      box-shadow: -1px 0 0 0 $wechat-green;
+    }
+  }
+  .bank-grid-wrap {
+    max-height: 280px;
+    padding: 8px 4px 12px;
+    overflow: auto;
+  }
+  .bank-grid {
+    display: grid;
+    grid-template-columns: repeat(3, 1fr);
+    gap: 8px 12px;
+  }
+  .bank-cell {
+    display: flex;
+    gap: 8px;
+    align-items: center;
+    padding: 8px 10px;
+    margin: 0;
+    text-align: left;
+    cursor: pointer;
+    background: #ffffff;
+    border: 1px solid transparent;
+    border-radius: 6px;
+    transition: background 0.15s;
+    &:hover {
+      background: #f5f7fa;
+    }
+    &.is-active {
+      background: #e8f5e9;
+      border-color: $wechat-green;
+    }
+  }
+  .bank-logo {
+    display: inline-flex;
+    flex-shrink: 0;
+    align-items: center;
+    justify-content: center;
+    width: 28px;
+    height: 28px;
+    font-size: 12px;
+    font-weight: 600;
+    color: #ffffff;
+    border-radius: 4px;
+  }
+  .bank-name {
+    font-size: 13px;
+    line-height: 1.3;
+    color: #303133;
+  }
+}
+</style>

+ 461 - 0
src/views/businessInfo/adminInfo.vue

@@ -0,0 +1,461 @@
+<template>
+  <div class="admin-info-page">
+    <h1 class="page-title">超级管理员</h1>
+
+    <section class="form-block">
+      <h2 class="section-head">
+        <span class="section-bar" aria-hidden="true" />
+        超级管理员信息
+      </h2>
+      <p class="section-intro">
+        超级管理员将接收开户信息及完成签约,并可进行商户号日常重要管理及资金操作。请确定超级管理员为商户法定代表人或经办人。
+      </p>
+
+      <el-form
+        ref="formRef"
+        class="admin-form"
+        :model="form"
+        :rules="rules"
+        label-width="140px"
+        require-asterisk-position="right"
+        label-position="right"
+      >
+        <el-form-item label="超管身份" prop="managerIdentity">
+          <el-radio-group v-model="form.managerIdentity" class="identity-radio">
+            <el-radio value="LEGAL"> 法定代表人/经营者 </el-radio>
+            <el-radio value="SUPER"> 经办人 </el-radio>
+          </el-radio-group>
+        </el-form-item>
+
+        <el-form-item label="超管姓名" prop="managerName">
+          <el-input v-model="form.managerName" placeholder="请输入超管姓名" clearable style="max-width: 420px" />
+        </el-form-item>
+
+        <el-form-item label="超管资料类型" prop="managerDocType">
+          <el-select v-model="form.managerDocType" placeholder="请选择" clearable style="max-width: 420px">
+            <el-option label="身份证" value="IDENTIFICATION_TYPE_IDCARD" />
+            <el-option label="护照" value="IDENTIFICATION_TYPE_OVERSEA_PASSPORT" />
+            <el-option label="香港居民来往内地通行证" value="IDENTIFICATION_TYPE_HONGKONG_PASSPORT" />
+            <el-option label="台湾居民来往大陆通行证" value="IDENTIFICATION_TYPE_TAIWAN_PASSPORT" />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="证件号码" prop="managerDocNo">
+          <el-input v-model="form.managerDocNo" placeholder="请输入证件号码" clearable style="max-width: 420px" />
+        </el-form-item>
+
+        <el-form-item label="手机号码" prop="mobile">
+          <div class="field-stack">
+            <el-input v-model="form.mobile" placeholder="请输入手机号" clearable maxlength="11" style="max-width: 420px" />
+            <p class="field-tip">用于接收微信支付的重要管理信息及日常操作验证码,超管签约时可自助修改手机号,并进行短信验证</p>
+          </div>
+        </el-form-item>
+
+        <el-form-item label="邮箱" prop="email">
+          <div class="field-stack">
+            <el-input v-model="form.email" placeholder="请输入邮箱" clearable style="max-width: 420px" />
+            <p class="field-tip">用于接收微信支付的开户邮件及日常业务通知</p>
+          </div>
+        </el-form-item>
+      </el-form>
+    </section>
+
+    <div class="footer-actions">
+      <el-button @click="onBack"> 返回 </el-button>
+      <el-button type="danger" class="btn-next" :loading="submitLoading" @click="onSubmit"> 提交 </el-button>
+    </div>
+
+    <el-dialog
+      v-model="signDialogVisible"
+      title="签约链接"
+      width="480px"
+      align-center
+      destroy-on-close
+      @closed="onSignDialogClosed"
+    >
+      <div class="sign-dialog">
+        <div v-if="signQrImageUrl && !signQrError" class="sign-dialog__qr-wrap">
+          <img class="sign-dialog__qr" :src="signQrImageUrl" alt="签约二维码" @error="signQrError = true" />
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed, nextTick, onMounted, reactive, ref } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
+import type { FormInstance, FormRules } from "element-plus";
+import { localGet, localSet } from "@/utils/index";
+import { applyment, getPaymentApplyment } from "@/api/modules/businessInfo";
+
+const BUSINESS_DATA_CACHE_KEY = "businessData";
+const GEEKER_USER_KEY = "geeker-user";
+
+function resolveApplymentStoreId(): string | number | null {
+  const geeker = localGet(GEEKER_USER_KEY) as { userInfo?: { storeId?: string | number | null } } | null | undefined;
+  const sid = geeker?.userInfo?.storeId ?? localGet("createdId");
+  if (sid === undefined || sid === null || sid === "") return null;
+  return sid;
+}
+
+const formRef = ref<FormInstance>();
+const submitLoading = ref(false);
+const signDialogVisible = ref(false);
+const signUrlText = ref("");
+const signQrError = ref(false);
+const route = useRoute();
+const router = useRouter();
+
+const signQrImageUrl = computed(() => {
+  const u = signUrlText.value.trim();
+  if (!/^https?:\/\//i.test(u)) return "";
+  return `https://api.qrserver.com/v1/create-qr-code/?size=280x280&data=${encodeURIComponent(u)}`;
+});
+
+function pickApplymentIdFromApplymentResponse(res: unknown): string {
+  const r = res as Record<string, unknown> | null | undefined;
+  const top = r?.data !== undefined ? r.data : r;
+  if (!top || typeof top !== "object" || Array.isArray(top)) return "";
+  const t = top as Record<string, unknown>;
+  const inner =
+    t.data !== undefined && t.data !== null && typeof t.data === "object" && !Array.isArray(t.data)
+      ? (t.data as Record<string, unknown>)
+      : t;
+  const id = inner.applyment_id ?? inner.applymentId;
+  return String(id ?? "").trim();
+}
+
+function pickSignUrlFromPaymentApplymentResponse(res: unknown): string {
+  const r = res as Record<string, unknown> | null | undefined;
+  const top = r?.data !== undefined ? r.data : r;
+  if (!top || typeof top !== "object" || Array.isArray(top)) return "";
+  const t = top as Record<string, unknown>;
+  const inner =
+    t.data !== undefined && t.data !== null && typeof t.data === "object" && !Array.isArray(t.data)
+      ? (t.data as Record<string, unknown>)
+      : t;
+  const url = inner.sign_url ?? inner.signUrl;
+  return String(url ?? "").trim();
+}
+
+function onSignDialogClosed() {
+  signUrlText.value = "";
+  signQrError.value = false;
+}
+
+async function copySignUrl() {
+  const u = signUrlText.value.trim();
+  if (!u) return;
+  try {
+    await navigator.clipboard.writeText(u);
+    ElMessage.success("链接已复制");
+  } catch {
+    ElMessage.warning("复制失败,请手动选中复制");
+  }
+}
+
+const form = reactive({
+  managerIdentity: "LEGAL" as "SUPER" | "LEGAL",
+  managerName: "",
+  managerDocType: "",
+  managerDocNo: "",
+  mobile: "",
+  email: ""
+});
+
+const rules: FormRules = {
+  managerIdentity: [{ required: true, message: "请选择超管身份", trigger: "change" }],
+  managerName: [{ required: true, message: "请输入超管姓名", trigger: "blur" }],
+  managerDocType: [{ required: true, message: "请选择超管资料类型", trigger: "change" }],
+  managerDocNo: [{ required: true, message: "请输入证件号码", trigger: "blur" }],
+  mobile: [
+    { required: true, message: "请输入手机号", trigger: "blur" },
+    { pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号", trigger: "blur" }
+  ],
+  email: [
+    { required: true, message: "请输入邮箱", trigger: "blur" },
+    { type: "email", message: "请输入正确的邮箱格式", trigger: ["blur", "change"] }
+  ]
+};
+
+function openMobileGuide() {
+  ElMessage.info("超管修改手机号指引(可对接文档)");
+}
+
+function onBack() {
+  router.push({ path: "/businessInfo/accountInfo", query: { ...route.query } });
+}
+
+function onSaveDraft() {
+  ElMessage.success("草稿已保存(可对接接口)");
+}
+
+/** 与 mergeContactInfoIntoBusinessDataCache 字段互逆;并从未填写的 subject_info 补全超管姓名/证件/类型 */
+function hydrateAdminFormFromBusinessDataCache() {
+  const raw = localGet(BUSINESS_DATA_CACHE_KEY) as Record<string, unknown> | null | undefined;
+  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
+
+  const ci = raw.contact_info as Record<string, unknown> | undefined;
+  if (ci && typeof ci === "object" && !Array.isArray(ci)) {
+    const ct = String(ci.contact_type ?? "").trim();
+    if (ct === "LEGAL" || ct === "SUPER") {
+      form.managerIdentity = ct;
+    }
+    form.managerName = String(ci.contact_name ?? "").trim();
+    form.managerDocType = String(ci.contact_id_doc_type ?? "").trim();
+    form.managerDocNo = String(ci.contact_id_number ?? "").trim();
+    form.mobile = String(ci.mobile_phone ?? "").trim();
+    form.email = String(ci.contact_email ?? "").trim();
+  }
+
+  const hadContactTypeFromCi = !!(
+    ci &&
+    typeof ci === "object" &&
+    !Array.isArray(ci) &&
+    ["LEGAL", "SUPER"].includes(String(ci.contact_type ?? "").trim())
+  );
+
+  const si = raw.subject_info as Record<string, unknown> | undefined;
+  if (!si || typeof si !== "object" || Array.isArray(si)) {
+    return;
+  }
+
+  if (!hadContactTypeFromCi) {
+    const ctSi = String(si.contact_type ?? "").trim();
+    if (ctSi === "LEGAL" || ctSi === "SUPER") {
+      form.managerIdentity = ctSi;
+    }
+  }
+
+  const ii = si.identity_info as Record<string, unknown> | undefined;
+  const docType = ii && typeof ii === "object" && !Array.isArray(ii) ? String(ii.id_doc_type ?? "").trim() : "";
+  const ici =
+    ii && typeof ii === "object" && !Array.isArray(ii) ? (ii.id_card_info as Record<string, unknown> | undefined) : undefined;
+  const idNum = ici && typeof ici === "object" && !Array.isArray(ici) ? String(ici.id_card_number ?? "").trim() : "";
+  const idName = ici && typeof ici === "object" && !Array.isArray(ici) ? String(ici.id_card_name ?? "").trim() : "";
+
+  const bli = si.business_license_info as Record<string, unknown> | undefined;
+  const legalPerson = bli && typeof bli === "object" && !Array.isArray(bli) ? String(bli.legal_person ?? "").trim() : "";
+
+  if (!String(form.managerName || "").trim()) {
+    form.managerName = idName || legalPerson;
+  }
+  if (!String(form.managerDocNo || "").trim()) {
+    form.managerDocNo = idNum;
+  }
+  if (!String(form.managerDocType || "").trim()) {
+    form.managerDocType = docType || (idNum ? "IDENTIFICATION_TYPE_IDCARD" : "");
+  }
+}
+
+onMounted(() => {
+  hydrateAdminFormFromBusinessDataCache();
+  nextTick(() => formRef.value?.clearValidate());
+});
+
+function mergeContactInfoIntoBusinessDataCache() {
+  const prev = localGet(BUSINESS_DATA_CACHE_KEY);
+  const base = prev && typeof prev === "object" && !Array.isArray(prev) ? { ...(prev as Record<string, unknown>) } : {};
+  const prevCi =
+    base.contact_info && typeof base.contact_info === "object" && !Array.isArray(base.contact_info)
+      ? { ...(base.contact_info as Record<string, unknown>) }
+      : {};
+
+  base.contact_info = {
+    ...prevCi,
+    contact_type: form.managerIdentity,
+    contact_name: String(form.managerName || "").trim(),
+    contact_id_doc_type: String(form.managerDocType || "").trim(),
+    contact_id_number: String(form.managerDocNo || "").trim(),
+    mobile_phone: String(form.mobile || "").trim(),
+    contact_email: String(form.email || "").trim()
+  };
+  localSet(BUSINESS_DATA_CACHE_KEY, base);
+}
+
+async function onSubmit() {
+  if (!formRef.value) return;
+  try {
+    await formRef.value.validate();
+  } catch {
+    ElMessage.warning("请完善必填信息");
+    return;
+  }
+
+  submitLoading.value = true;
+  try {
+    mergeContactInfoIntoBusinessDataCache();
+    const businessData = localGet(BUSINESS_DATA_CACHE_KEY);
+    if (!businessData || typeof businessData !== "object" || Array.isArray(businessData)) {
+      ElMessage.warning("未找到进件数据,请重新填写");
+      return;
+    }
+    const storeIdRaw = resolveApplymentStoreId();
+    if (storeIdRaw === null) {
+      ElMessage.warning("未获取到门店 storeId,请重新登录");
+      return;
+    }
+    const n = Number(storeIdRaw);
+    const storeId = Number.isNaN(n) ? storeIdRaw : n;
+    const payload = { ...(businessData as Record<string, unknown>) };
+    const res: unknown = await applyment(payload, storeId);
+    const r = res as Record<string, unknown> | undefined;
+    if (r?.code === 200 || r?.code === "200") {
+      const applymentId = pickApplymentIdFromApplymentResponse(res);
+      if (applymentId) {
+        try {
+          const detailRes: unknown = await getPaymentApplyment(applymentId);
+          const dr = detailRes as Record<string, unknown> | undefined;
+          const nested = dr?.data as Record<string, unknown> | undefined;
+          const dCode = dr?.code ?? nested?.code;
+          if (dCode === 200 || dCode === "200") {
+            const signUrl = pickSignUrlFromPaymentApplymentResponse(detailRes);
+            if (/^https?:\/\//i.test(signUrl)) {
+              signUrlText.value = signUrl;
+              signQrError.value = false;
+              signDialogVisible.value = true;
+            }
+          }
+        } catch (e) {
+          console.warn("[adminInfo] getPaymentApplyment", e);
+        }
+      }
+      ElMessage.success((r?.msg as string) || "提交成功");
+    } else {
+      ElMessage.warning((r?.msg as string) || "提交失败,请稍后重试");
+    }
+  } catch {
+    ElMessage.error("提交失败,请稍后重试");
+  } finally {
+    submitLoading.value = false;
+  }
+}
+</script>
+
+<style scoped lang="scss">
+$wechat-green: #07c160;
+.admin-info-page {
+  box-sizing: border-box;
+  min-height: 100%;
+  padding: 24px 32px 40px;
+  margin: 0 auto;
+  background: #ffffff;
+}
+.page-title {
+  margin: 0 0 24px;
+  font-size: 20px;
+  font-weight: 600;
+  color: #303133;
+}
+.form-block {
+  margin-bottom: 24px;
+}
+.section-head {
+  display: flex;
+  align-items: center;
+  margin: 0 0 12px;
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+}
+.section-bar {
+  display: inline-block;
+  flex-shrink: 0;
+  width: 4px;
+  height: 16px;
+  margin-right: 8px;
+  background: $wechat-green;
+  border-radius: 2px;
+}
+.section-intro {
+  margin: 0 0 20px;
+  font-size: 12px;
+  line-height: 1.65;
+  color: #909399;
+}
+.admin-form {
+  :deep(.el-form-item__label) {
+    font-weight: 500;
+    color: #606266;
+  }
+}
+.identity-radio {
+  :deep(.el-radio__input.is-checked .el-radio__inner) {
+    background: $wechat-green;
+    border-color: $wechat-green;
+  }
+  :deep(.el-radio__input.is-checked + .el-radio__label) {
+    color: #303133;
+  }
+}
+.tip-icon {
+  margin-left: 4px;
+  color: #c0c4cc;
+}
+.field-stack {
+  width: 100%;
+}
+.field-tip {
+  margin: 8px 0 0;
+  font-size: 12px;
+  line-height: 1.65;
+  color: #909399;
+}
+.footer-actions {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding-top: 24px;
+  margin-top: 16px;
+  border-top: 1px solid #ebeef5;
+}
+.footer-center {
+  display: flex;
+  flex: 1;
+  justify-content: center;
+}
+.btn-next {
+  min-width: 100px;
+  background: $wechat-green;
+  border-color: $wechat-green;
+  &:hover {
+    background: #06ad56;
+    border-color: #06ad56;
+  }
+}
+.sign-dialog {
+  padding: 0 4px 8px;
+}
+.sign-dialog__qr-wrap {
+  display: flex;
+  justify-content: center;
+  margin-bottom: 16px;
+}
+.sign-dialog__qr {
+  width: 240px;
+  height: 240px;
+  object-fit: contain;
+  background: #fafafa;
+}
+.sign-dialog__fail {
+  margin: 0 0 12px;
+  font-size: 13px;
+  line-height: 1.6;
+  color: #909399;
+}
+.sign-dialog__hint {
+  margin: 0 0 12px;
+  font-size: 14px;
+  color: #606266;
+  text-align: center;
+}
+.sign-dialog__url {
+  margin-bottom: 16px;
+}
+.sign-dialog__actions {
+  display: flex;
+  justify-content: center;
+}
+</style>

+ 4383 - 0
src/views/businessInfo/category.json

@@ -0,0 +1,4383 @@
+{
+    "data": {
+        "childrenNodes": [
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0150",
+                        "creator": "john.wy",
+                        "description": "适用于提供眼科医疗相关服务的场所申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1724913433000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "眼科医疗服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 11,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0151",
+                        "creator": "john.wy",
+                        "description": "适用于提供口腔医疗相关服务的场所申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1724896295000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "口腔医疗服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 12,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0140",
+                        "creator": "john.wy",
+                        "description": "适用于药品的销售、配送等服务。如药店、药品生产商、销售商等。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1713922706000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "医药销售",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 1,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0149",
+                        "creator": "john.wy",
+                        "description": "适用于提供医疗美容相关服务的场所申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1724900615000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "医疗美容",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 10,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0152",
+                        "creator": "john.wy",
+                        "description": "适用于提供医学实验室及诊断中心的场所申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "医学实验室及诊断中心",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 13,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0141",
+                        "creator": "john.wy",
+                        "description": "适用于医疗器械的销售等服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "医疗器械销售",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 2,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0153",
+                        "creator": "john.wy",
+                        "description": "适用于互联网医院主体/医疗服务平台提供在线看诊、疾病咨询等综合性线上医疗服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1631672817000,
+                        "level": 2,
+                        "modifier": "size.lsz",
+                        "name": "线上医疗服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 14,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0142",
+                        "creator": "john.wy",
+                        "description": "适用于保健辅助治疗器材的销售等服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1723192335000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "健康食品/设备",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 3,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0154",
+                        "creator": "john.wy",
+                        "description": "适用于养老、医疗护理等相关的服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "护理机构服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 15,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0143",
+                        "creator": "john.wy",
+                        "description": "适用于主体为公立医院提供的就医、健康咨询/问诊、医疗保健信息等服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1680162439000,
+                        "level": 2,
+                        "modifier": "swl01119956",
+                        "name": "公立医院",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 4,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0155",
+                        "creator": "john.wy",
+                        "description": "适用于健康体检预约、专业体检机构、健康咨询等服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622187068000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "体检/健康咨询",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 16,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0144",
+                        "creator": "john.wy",
+                        "description": "适用于主体为社区卫生服务中心提供的就医、健康咨询/问诊、医疗保健信息等服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1716961342000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "社区卫生服务中心/乡镇卫生院",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 5,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0156",
+                        "creator": "john.wy",
+                        "description": "其他医疗保健服务",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "其他医疗保健服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 17,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0145",
+                        "creator": "john.wy",
+                        "description": "适用于各级卫生行政机构、疾病控制机构,卫生监督机构、妇幼保健机构、慢性病防治机构、社区卫生服务机构及公共卫生研究机构",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1716965619000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "专业公共卫生机构",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 6,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0146",
+                        "creator": "john.wy",
+                        "description": "适用于主体为民营医院提供的就医、健康咨询/问诊、医疗保健信息等服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "民营医院",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 7,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0147",
+                        "creator": "john.wy",
+                        "description": "适用于私人开业的医生诊治病人的场所申请使用",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1713926965000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "诊所",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 8,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0148",
+                        "creator": "john.wy",
+                        "description": "适用于个体行医的医护人员申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "个体医生",
+                        "needSpecialQual": true,
+                        "parentCode": "A0009",
+                        "parentName": "医疗卫生",
+                        "sortNum": 9,
+                        "special": true,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0009",
+                "creator": "john.wy",
+                "description": "医疗卫生",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767921000,
+                "gmtModified": 1602767922000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "医疗卫生",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 9,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0127",
+                        "creator": "john.wy",
+                        "description": "适用于国内三大运营商以及获得虚拟运营商牌照的电信公司申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1723448663000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "电信运营商",
+                        "needSpecialQual": true,
+                        "parentCode": "A0007",
+                        "parentName": "网络通讯",
+                        "sortNum": 20,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0128",
+                        "creator": "john.wy",
+                        "description": "适用于付费电视服务申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "付费电视",
+                        "needSpecialQual": true,
+                        "parentCode": "A0007",
+                        "parentName": "网络通讯",
+                        "sortNum": 21,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0129",
+                        "creator": "john.wy",
+                        "description": "适用于网络电话、传真服务申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1602767823000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "网络电话、传真服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0007",
+                        "parentName": "网络通讯",
+                        "sortNum": 22,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0120",
+                        "creator": "john.wy",
+                        "description": "适用于提供互联网基础平台服务(服务器托管、虚拟主机、邮件缓存、虚拟邮件等)以及各种增值服务(场地的租用服务、域名系统服务、负载均衡系统、数据库系统、数据备份服务等)。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "互联网数据服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0007",
+                        "parentName": "网络通讯",
+                        "sortNum": 13,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0121",
+                        "creator": "john.wy",
+                        "description": "提供域名注册、网站建设等服务的公司申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "软件开发服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0007",
+                        "parentName": "网络通讯",
+                        "sortNum": 14,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0113",
+                        "creator": "john.wy",
+                        "description": "提供网站论坛、咨询信息等服务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "信息检索服务/网络论坛",
+                        "needSpecialQual": false,
+                        "parentCode": "A0007",
+                        "parentName": "网络通讯",
+                        "sortNum": 6,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0125",
+                        "creator": "john.wy",
+                        "description": "适用于提供其他在线应用或综合类服务的公司申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "其他在线应用或综合类服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0007",
+                        "parentName": "网络通讯",
+                        "sortNum": 18,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0126",
+                        "creator": "john.wy",
+                        "description": "适用于提供网络广告制作、网络视频制作、搜索引擎的广告位等服务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "网络推广/网络广告",
+                        "needSpecialQual": false,
+                        "parentCode": "A0007",
+                        "parentName": "网络通讯",
+                        "sortNum": 19,
+                        "special": false,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0007",
+                "creator": "john.wy",
+                "description": "网络和通讯",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767921000,
+                "gmtModified": 1612260356000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "网络通讯",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 7,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0138",
+                        "creator": "john.wy",
+                        "description": "适用于少年宫及青少年发展中心等主体,提供教育相关服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1663772383000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "少年宫及青少年发展中心",
+                        "needSpecialQual": true,
+                        "parentCode": "A0008",
+                        "parentName": "教育服务",
+                        "sortNum": 9,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0139",
+                        "creator": "john.wy",
+                        "description": "适用于提供教育相关服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1665645259000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "其他教育/培训",
+                        "needSpecialQual": true,
+                        "parentCode": "A0008",
+                        "parentName": "教育服务",
+                        "sortNum": 10,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0130",
+                        "creator": "john.wy",
+                        "description": "适用于校园场景下的学前教育服务,如公立幼儿园等。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1664163627000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "儿童保育服务(公立,含学前教育)",
+                        "needSpecialQual": true,
+                        "parentCode": "A0008",
+                        "parentName": "教育服务",
+                        "sortNum": 1,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0131",
+                        "creator": "john.wy",
+                        "description": "适用于校园场景下的学前教育服务,如民办幼儿园等。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1664170806000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "儿童保育服务(民办,含学前教育)",
+                        "needSpecialQual": true,
+                        "parentCode": "A0008",
+                        "parentName": "教育服务",
+                        "sortNum": 2,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0132",
+                        "creator": "john.wy",
+                        "description": "适用于校园场景下的公立小学、初中、高中学历教育等服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1663675003000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "中小学校(公立)",
+                        "needSpecialQual": true,
+                        "parentCode": "A0008",
+                        "parentName": "教育服务",
+                        "sortNum": 3,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0133",
+                        "creator": "john.wy",
+                        "description": "适用于校园场景下的民办小学、初中、高中学历教育等服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1663928786000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "中小学校(民办)",
+                        "needSpecialQual": true,
+                        "parentCode": "A0008",
+                        "parentName": "教育服务",
+                        "sortNum": 4,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0134",
+                        "creator": "john.wy",
+                        "description": "适用于校园场景下的公立大学学历教育等服务",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1663901535000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "大学与学院(公立)",
+                        "needSpecialQual": true,
+                        "parentCode": "A0008",
+                        "parentName": "教育服务",
+                        "sortNum": 5,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0135",
+                        "creator": "john.wy",
+                        "description": "适用于校园场景下的民办大学学历教育等服务",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1663909973000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "大学与学院(民办)",
+                        "needSpecialQual": true,
+                        "parentCode": "A0008",
+                        "parentName": "教育服务",
+                        "sortNum": 6,
+                        "special": true,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0008",
+                "creator": "john.wy",
+                "description": "教育",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767822000,
+                "gmtModified": 1628663807000,
+                "level": 1,
+                "modifier": "size.lsz",
+                "name": "教育服务",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 8,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0180",
+                        "creator": "john.wy",
+                        "description": "适用于可开展保险业务、保险代理业务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1663134412000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "保险业务/保险代理",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 15,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0181",
+                        "creator": "john.wy",
+                        "description": "适用于可开展典当业务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "典当",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 16,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0170",
+                        "creator": "john.wy",
+                        "description": "适用于小额贷款公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "小贷公司",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 5,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0171",
+                        "creator": "john.wy",
+                        "description": "适用于与持牌的消费金融公司、小贷公司、银行等持牌机构的有业务合作,且合作协议内容需要体现平台用户的放款由对应合作机构发放的平台类公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "借贷消费平台",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 6,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0172",
+                        "creator": "john.wy",
+                        "description": "适用于可开展融资租赁业务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "融资租赁公司",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 7,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0173",
+                        "creator": "john.wy",
+                        "description": "适用于可开展金融租赁业务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "金融租赁公司",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 8,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0174",
+                        "creator": "john.wy",
+                        "description": "适用于可开展汽车金融业务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "汽车金融公司",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 9,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0175",
+                        "creator": "john.wy",
+                        "description": "适用于可开展消费金融业务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "消费金融公司",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 10,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0176",
+                        "creator": "john.wy",
+                        "description": "适用于可开展信托业务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "信托公司",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 11,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0177",
+                        "creator": "john.wy",
+                        "description": "适用于可开展支付业务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1724828448000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "支付机构",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 12,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0166",
+                        "creator": "john.wy",
+                        "description": "适用于可开展个人贷款业务、信用卡业务的机构",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "金融机构",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 1,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0178",
+                        "creator": "john.wy",
+                        "description": "适用于可开展融资担保业务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "融资担保公司",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 13,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0167",
+                        "creator": "john.wy",
+                        "description": "适用于可开展其他金融服务业务的机构",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "金融机构-其他服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 2,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0179",
+                        "creator": "john.wy",
+                        "description": "适用于其他金融服务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "其他金融服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 14,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0168",
+                        "creator": "john.wy",
+                        "description": "适用于经营本、外币业务的机构或个人",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "外币汇兑",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 3,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0169",
+                        "creator": "john.wy",
+                        "description": "适用于拥有证监会关于同意开展证券经营业务的批复、证监会及其派出机构颁布的基金类业务相关资格证书的提供股票基金服务的机构",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "股票基金服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0012",
+                        "parentName": "金融理财",
+                        "sortNum": 4,
+                        "special": true,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0012",
+                "creator": "john.wy",
+                "description": "金融",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767921000,
+                "gmtModified": 1612260432000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "金融理财",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 12,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0006",
+                        "creator": "john.wy",
+                        "description": "适用于正式饭菜以外的熟食或点心铺出售的熟食或饭馆中的经济膳食的商家申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1693275211000,
+                        "level": 2,
+                        "modifier": "zhize.zy",
+                        "name": "小吃/熟食",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 6,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0117",
+                        "creator": "john.wy",
+                        "description": "提供订餐服务的信息服务平台。如平台参与餐饮的加工服务,建议选择“餐饮”",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1612260112000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "订餐服务平台",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 10,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0007",
+                        "creator": "john.wy",
+                        "description": "适用于校园食堂申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1661837595000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "校园团餐",
+                        "needSpecialQual": true,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 7,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0008",
+                        "creator": "john.wy",
+                        "description": "适用于以一定的服务标准和模式提供定量的餐饮产品和与之配套的现场服务门店",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1657522537000,
+                        "level": 2,
+                        "modifier": "mingyang.gmy",
+                        "name": "综合团餐",
+                        "needSpecialQual": true,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 8,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0009",
+                        "creator": "john.wy",
+                        "description": "适用于奶茶/甜品店铺申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1602767823000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "饮品/甜品",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 9,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0010",
+                        "creator": "john.wy",
+                        "description": "适用于拥有烘焙糕点生产场所的商户",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "烘焙糕点",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 10,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0011",
+                        "creator": "john.wy",
+                        "description": "适用于多种类酒调制,现场消费的商户",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "酒吧/清吧",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 11,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0012",
+                        "creator": "john.wy",
+                        "description": "适用于多种类咖啡、茶水现场消费的商户",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "咖啡馆/茶馆",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 12,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0001",
+                        "creator": "john.wy",
+                        "description": "适用于经营场所经营多品种的中式餐品,出餐或用餐时间均较长的商家申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "中式正餐",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 1,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0199",
+                        "creator": "john.wy",
+                        "description": "适用于经营火锅的商家申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1609322097000,
+                        "gmtModified": 1622187153000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "火锅",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 1,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0002",
+                        "creator": "john.wy",
+                        "description": "适用于经营场所经营多品种的西式餐品,出餐或用餐时间均较长的商家申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1622186907000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "西式正餐",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 2,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0200",
+                        "creator": "john.wy",
+                        "description": "适用于餐食宴会供应商申请使用",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1609322153000,
+                        "gmtModified": 1609322154000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "宴会提供商",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 13,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0003",
+                        "creator": "john.wy",
+                        "description": "适用于经营场所经营日式、韩式、东南亚菜的商家申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622186903000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "日韩/东南亚菜",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 3,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0004",
+                        "creator": "john.wy",
+                        "description": "适用于经营场所经营中式的仅做食材简单的加工处理即可出餐,面条类、盖饭、面点类的商家申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "中式快餐",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 4,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0005",
+                        "creator": "john.wy",
+                        "description": "适用于经营场所经营西式的仅做食材简单的加工处理即可出餐的商家申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622186898000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "西式快餐",
+                        "needSpecialQual": false,
+                        "parentCode": "A0001",
+                        "parentName": "餐饮",
+                        "sortNum": 5,
+                        "special": false,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0001",
+                "creator": "john.wy",
+                "description": "餐饮",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767822000,
+                "gmtModified": 1602767823000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "餐饮",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 1,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0190",
+                        "creator": "john.wy",
+                        "description": "适用于***法院",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1673577670000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "法庭费用",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 9,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0191",
+                        "creator": "john.wy",
+                        "description": "适用于***公安局(厅)",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1673938030000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "保释金",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 10,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0192",
+                        "creator": "john.wy",
+                        "description": "适用于***税务局",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1673510129000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "税务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 11,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0182",
+                        "creator": "john.wy",
+                        "description": "适用于***财政局(厅)/公安局(厅)/行政执法队/警察总队/人民政府(办公厅、室)/***人力资源和社会保障****中心(局、办公室)/***公积金管理中心/***医保局/**医疗保障局",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1674012064000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "政府机构",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 1,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0193",
+                        "creator": "john.wy",
+                        "description": "适用于慈善和社会公益机构",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1662607673000,
+                        "level": 2,
+                        "modifier": "sisi.fss",
+                        "name": "慈善和社会公益服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 12,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0183",
+                        "creator": "john.wy",
+                        "description": "适用于***财政局(厅)",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1673857964000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "行政费用和罚款(非税)",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 2,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0194",
+                        "creator": "john.wy",
+                        "description": "适用于使领馆申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1680154051000,
+                        "level": 2,
+                        "modifier": "yumai.cw",
+                        "name": "使领馆",
+                        "needSpecialQual": false,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 13,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0184",
+                        "creator": "john.wy",
+                        "description": "适用于***公积金管理中心",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1673849973000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "公积金",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 3,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0195",
+                        "creator": "john.wy",
+                        "description": "适用于各行业协会或专业社团申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "行业协会和专业社团",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 14,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0226",
+                        "creator": "size.lsz",
+                        "description": "适用于“一网通办”服务机构使用",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1635218130000,
+                        "gmtModified": 1673338973000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "一网通办",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 20,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0196",
+                        "creator": "john.wy",
+                        "description": "适用于汽车协会申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "汽车协会",
+                        "needSpecialQual": false,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 15,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0185",
+                        "creator": "john.wy",
+                        "description": "适用于***公安局(厅)/行政执法队/警察总队/**交通管理局",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1673921878000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "公安交管",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 4,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0197",
+                        "creator": "john.wy",
+                        "description": "适用于宗教组织申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "宗教组织",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 16,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0186",
+                        "creator": "john.wy",
+                        "description": "适用于***医保局/**医疗保障局",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1721281709000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "医保",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 5,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0198",
+                        "creator": "john.wy",
+                        "description": "适用于其他会员组织申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "其他会员组织",
+                        "needSpecialQual": false,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 17,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0187",
+                        "creator": "john.wy",
+                        "description": "适用于***人力资源和社会保障****中心/局/办公室",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1673493388000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "社会保障服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 6,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0188",
+                        "creator": "john.wy",
+                        "description": "适用于政府采购相关服务",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1680147626000,
+                        "level": 2,
+                        "modifier": "yumai.cw",
+                        "name": "政府采购",
+                        "needSpecialQual": false,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 7,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0222",
+                        "creator": "john.wy",
+                        "description": "适用于***文化局、***体育局申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1609328692000,
+                        "gmtModified": 1622187075000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "文体机构",
+                        "needSpecialQual": false,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 7,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0189",
+                        "creator": "john.wy",
+                        "description": "适用于政府贷款相关服务",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622187135000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "政府贷款",
+                        "needSpecialQual": false,
+                        "parentCode": "A0013",
+                        "parentName": "公共管理和社会组织",
+                        "sortNum": 8,
+                        "special": false,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0013",
+                "creator": "john.wy",
+                "description": "公共管理和社会组织",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767921000,
+                "gmtModified": 1602767922000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "公共管理和社会组织",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 13,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0040",
+                        "creator": "john.wy",
+                        "description": "适用于主售危险化工产品的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "危险化工产品",
+                        "needSpecialQual": true,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 28,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0041",
+                        "creator": "john.wy",
+                        "description": "适用于主售石油及石油产品的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622186878000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "石油及石油产品",
+                        "needSpecialQual": true,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 29,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0039",
+                        "creator": "john.wy",
+                        "description": "适用于主售烟花爆竹的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "烟花爆竹",
+                        "needSpecialQual": true,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 27,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0017",
+                        "creator": "john.wy",
+                        "description": "适用于集中收银台收银的购物商场",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1602767823000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "百货商场",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 5,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0018",
+                        "creator": "john.wy",
+                        "description": "适用于商家独立分散收银的购物商场",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "购物中心",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 6,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0216",
+                        "creator": "john.wy",
+                        "description": "适用于家居、家具、家纺类商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1609322390000,
+                        "gmtModified": 1609322388000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "家居家纺",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 24,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0118",
+                        "creator": "john.wy",
+                        "description": "提供团购服务信息的平台,平台不参与生产销售。如涉及加工,建议选择餐饮类目",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622187036000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "社区团购服务平台",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 11,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0019",
+                        "creator": "john.wy",
+                        "description": "适用于品牌折扣店集中的购物商场",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622186887000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "奥特莱斯",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 7,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0031",
+                        "creator": "john.wy",
+                        "description": "适用于主售图书、文具、音乐影像制品、工艺美术制品、乐器的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "图文音像/工美乐器",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 19,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0032",
+                        "creator": "john.wy",
+                        "description": "适用于主售母婴用品、儿童玩具的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "母婴用品/儿童玩具",
+                        "needSpecialQual": true,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 20,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0033",
+                        "creator": "john.wy",
+                        "description": "适用于主售宠物本体、宠物日用品的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "宠物/宠物用品",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 21,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0034",
+                        "creator": "john.wy",
+                        "description": "适用于主售户外装备、运动器材的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "户外运动器材",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 22,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0232",
+                        "creator": "pxy02075401",
+                        "description": "适用于B2B电商市场,包括企业采购批发、供应链金融及综合生活消费场景。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1739931917000,
+                        "gmtModified": 1739931917000,
+                        "level": 2,
+                        "modifier": "pxy02075401",
+                        "name": "商品批发/企业采购/供应链服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 40,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0035",
+                        "creator": "john.wy",
+                        "description": "适用于主售五金建材的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "五金建材",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 23,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0013",
+                        "creator": "john.wy",
+                        "description": "适用于个人商户的小型零售店",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1612260445000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "杂货店",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 1,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0036",
+                        "creator": "john.wy",
+                        "description": "适用于主售鲜花绿植的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "鲜花/绿植",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 24,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0014",
+                        "creator": "john.wy",
+                        "description": "适用于标准装修、自选式购物的小型零售店",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622186891000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "连锁便利店",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 2,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0037",
+                        "creator": "john.wy",
+                        "description": "适用于主售文物、文物复制品的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "文物经营/文物复制品",
+                        "needSpecialQual": true,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 25,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0114",
+                        "creator": "john.wy",
+                        "description": "适用于综合类网上商城",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1612260128000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "互联网综合电商平台",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 7,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0015",
+                        "creator": "john.wy",
+                        "description": "适用于线下实体,千平、交易量大的超市",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1629254004000,
+                        "level": 2,
+                        "modifier": "size.lsz",
+                        "name": "超市",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 3,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0038",
+                        "creator": "john.wy",
+                        "description": "适用于主售计生类用品的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "计生用品",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 26,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0115",
+                        "creator": "john.wy",
+                        "description": "适用于垂直类网上商城",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622187010000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "互联网垂直电商平台",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 8,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0016",
+                        "creator": "john.wy",
+                        "description": "适用于以超市为主体辐射多个小商家的综合卖场",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "大卖场",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 4,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0030",
+                        "creator": "john.wy",
+                        "description": "适用于主售数码3C、电脑、家用电器的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "3C数码/家用电器",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 18,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0028",
+                        "creator": "john.wy",
+                        "description": "适用于主售黄金首饰、珠宝首饰、钟表、各类时尚饰品的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "黄金珠宝/钟表饰品",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 16,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0029",
+                        "creator": "john.wy",
+                        "description": "适用于主售近视眼镜、隐形眼镜、太阳眼镜及其他眼镜的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "眼镜店",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 17,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0020",
+                        "creator": "john.wy",
+                        "description": "适用于各地特殊的商业街,含美食、购物、休闲娱乐等服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622186882000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "商业街",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 8,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0042",
+                        "creator": "john.wy",
+                        "description": "适用于主售工业制成品的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "工业产品",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 30,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0021",
+                        "creator": "john.wy",
+                        "description": "适用水果的售卖场所",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "水果店",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 9,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0043",
+                        "creator": "john.wy",
+                        "description": "其他专业零售店",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "其他专业零售店",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 31,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0022",
+                        "creator": "john.wy",
+                        "description": "适用于主售茶叶的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "茶叶",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 10,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0023",
+                        "creator": "john.wy",
+                        "description": "适用于主售酒类的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1653548586000,
+                        "level": 2,
+                        "modifier": "size.lsz",
+                        "name": "酒类",
+                        "needSpecialQual": true,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 11,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0024",
+                        "creator": "john.wy",
+                        "description": "适用于主售烟草制品/雪茄的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "烟草/雪茄",
+                        "needSpecialQual": true,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 12,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0025",
+                        "creator": "john.wy",
+                        "description": "适用于主售营养保健类的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "营养品/保健品",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 13,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0201",
+                        "creator": "john.wy",
+                        "description": "适用于零食、食品经营场所申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1609322234000,
+                        "gmtModified": 1609322235000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "食品零售",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 11,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0026",
+                        "creator": "john.wy",
+                        "description": "适用于主售服饰类、鞋类、箱包类的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "服饰鞋包",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 14,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0202",
+                        "creator": "john.wy",
+                        "description": "适用于蔬菜、肉、蛋、海鲜水产销售经营场所申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1609322316000,
+                        "gmtModified": 1609322316000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "蔬菜/肉蛋/水产",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 11,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0027",
+                        "creator": "john.wy",
+                        "description": "适用于主售化妆品、护理品的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "美妆个护",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 15,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0203",
+                        "creator": "john.wy",
+                        "description": "适用于主售办公用品的商户申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1609322345000,
+                        "gmtModified": 1609322346000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "办公用品",
+                        "needSpecialQual": false,
+                        "parentCode": "A0002",
+                        "parentName": "零售批发",
+                        "sortNum": 20,
+                        "special": false,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0002",
+                "creator": "john.wy",
+                "description": "零售和批发",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767921000,
+                "gmtModified": 1612260314000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "零售批发",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 2,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0119",
+                        "creator": "john.wy",
+                        "description": "提供旅游信息服务的平台",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1612260295000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "旅游服务平台(OTA)",
+                        "needSpecialQual": false,
+                        "parentCode": "A0010",
+                        "parentName": "酒旅景区",
+                        "sortNum": 12,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0219",
+                        "creator": "john.wy",
+                        "description": "适用于风景区系统开发维护服务商申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1609328459000,
+                        "gmtModified": 1622187166000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "风景区系统商",
+                        "needSpecialQual": false,
+                        "parentCode": "A0010",
+                        "parentName": "酒旅景区",
+                        "sortNum": 5,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0160",
+                        "creator": "john.wy",
+                        "description": "适用于旅游相关服务直销的公司申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "旅游相关服务直销",
+                        "needSpecialQual": true,
+                        "parentCode": "A0010",
+                        "parentName": "酒旅景区",
+                        "sortNum": 4,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0220",
+                        "creator": "john.wy",
+                        "description": "适用于景区内游览观光车经营主体公司申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1609328489000,
+                        "gmtModified": 1622187172000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "观光车",
+                        "needSpecialQual": false,
+                        "parentCode": "A0010",
+                        "parentName": "酒旅景区",
+                        "sortNum": 6,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0221",
+                        "creator": "john.wy",
+                        "description": "适用于景区内游船码头服务主体公司申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1609328489000,
+                        "gmtModified": 1609328519000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "游船码头",
+                        "needSpecialQual": false,
+                        "parentCode": "A0010",
+                        "parentName": "酒旅景区",
+                        "sortNum": 7,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0157",
+                        "creator": "john.wy",
+                        "description": "适用于提供酒店、旅馆、民宿等住宿场景服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "酒店/旅馆/民宿",
+                        "needSpecialQual": false,
+                        "parentCode": "A0010",
+                        "parentName": "酒旅景区",
+                        "sortNum": 1,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0158",
+                        "creator": "john.wy",
+                        "description": "适用于景区管理公司申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1663746196000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "景区",
+                        "needSpecialQual": true,
+                        "parentCode": "A0010",
+                        "parentName": "酒旅景区",
+                        "sortNum": 2,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0159",
+                        "creator": "john.wy",
+                        "description": "适用于旅行社、旅游咨询等公司的申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "旅行社和旅游服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0010",
+                        "parentName": "酒旅景区",
+                        "sortNum": 3,
+                        "special": true,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0010",
+                "creator": "john.wy",
+                "description": "旅游",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767921000,
+                "gmtModified": 1612260391000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "酒旅景区",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 10,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0204",
+                        "creator": "john.wy",
+                        "description": "适用于电力缴费管理公司申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1609816623000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "公共事业-电力缴费",
+                        "needSpecialQual": true,
+                        "parentCode": "A0011",
+                        "parentName": "生活缴费",
+                        "sortNum": 2,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0206",
+                        "creator": "john.wy",
+                        "description": "适用于煤气缴费管理公司申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1609328618000,
+                        "gmtModified": 1636359338000,
+                        "level": 2,
+                        "modifier": "size.lsz",
+                        "name": "公共事业-煤气缴费",
+                        "needSpecialQual": true,
+                        "parentCode": "A0011",
+                        "parentName": "生活缴费",
+                        "sortNum": 4,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0207",
+                        "creator": "john.wy",
+                        "description": "适用于清洁服务缴费公司申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1609328641000,
+                        "gmtModified": 1609328655000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "公共事业-清洁服务缴费",
+                        "needSpecialQual": false,
+                        "parentCode": "A0011",
+                        "parentName": "生活缴费",
+                        "sortNum": 6,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0161",
+                        "creator": "john.wy",
+                        "description": "适用于自来水公司、电力公司申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "公共事业(电、气、水)",
+                        "needSpecialQual": true,
+                        "parentCode": "A0011",
+                        "parentName": "生活缴费",
+                        "sortNum": 1,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0162",
+                        "creator": "john.wy",
+                        "description": "适用于有线电视缴费代理公司申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622187081000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "公共事业-有线电视缴费",
+                        "needSpecialQual": true,
+                        "parentCode": "A0011",
+                        "parentName": "生活缴费",
+                        "sortNum": 2,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0163",
+                        "creator": "john.wy",
+                        "description": "其他生活缴费类服务",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "公共事业-其他缴费",
+                        "needSpecialQual": false,
+                        "parentCode": "A0011",
+                        "parentName": "生活缴费",
+                        "sortNum": 3,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0164",
+                        "creator": "john.wy",
+                        "description": "移动、联通、电信公司授权的第三方经营话费充值、流量充值等业务的公司",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "话费充值与缴费",
+                        "needSpecialQual": false,
+                        "parentCode": "A0011",
+                        "parentName": "生活缴费",
+                        "sortNum": 4,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0211",
+                        "creator": "john.wy",
+                        "description": "适用于自来水缴费管理公司申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1609328576000,
+                        "gmtModified": 1635929466000,
+                        "level": 2,
+                        "modifier": "size.lsz",
+                        "name": "公共事业-自来水缴费",
+                        "needSpecialQual": true,
+                        "parentCode": "A0011",
+                        "parentName": "生活缴费",
+                        "sortNum": 3,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0225",
+                        "creator": "size.lsz",
+                        "description": "供供暖缴费相关商户申请使用",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1632377565000,
+                        "gmtModified": 1632625395000,
+                        "level": 2,
+                        "modifier": "size.lsz",
+                        "name": "供暖缴费",
+                        "needSpecialQual": true,
+                        "parentCode": "A0011",
+                        "parentName": "生活缴费",
+                        "sortNum": 9,
+                        "special": true,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0011",
+                "creator": "john.wy",
+                "description": "生活缴费",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767921000,
+                "gmtModified": 1602767922000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "生活缴费",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 11,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0080",
+                        "creator": "john.wy",
+                        "description": "适用于ETC办理、充值、缴费等业务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1658714457000,
+                        "level": 2,
+                        "modifier": "mingyang.gmy",
+                        "name": "ETC不停车自动缴费",
+                        "needSpecialQual": true,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 10,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0081",
+                        "creator": "john.wy",
+                        "description": "适用于MTC收费业务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "MTC半自动车道收费",
+                        "needSpecialQual": true,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 11,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0082",
+                        "creator": "john.wy",
+                        "description": "适用于高速服务区申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622186941000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "高速服务区",
+                        "needSpecialQual": false,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 12,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0071",
+                        "creator": "john.wy",
+                        "description": "适用于主售汽车摩托车零配件、汽车摩托车用品精品的商家申请。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "车辆零配件/用品精品",
+                        "needSpecialQual": false,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 1,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0083",
+                        "creator": "john.wy",
+                        "description": "适用于提供交通紧急救援服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "道路救援",
+                        "needSpecialQual": false,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 13,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0072",
+                        "creator": "john.wy",
+                        "description": "适用于提供汽车维修/汽车美容/汽车养护等服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "汽车洗美/维修养护",
+                        "needSpecialQual": false,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 2,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0073",
+                        "creator": "john.wy",
+                        "description": "适用于销售新车的商家申请。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "车辆销售",
+                        "needSpecialQual": false,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 3,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0074",
+                        "creator": "john.wy",
+                        "description": "适用于销售二手车的商家申请。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622186871000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "二手车销售",
+                        "needSpecialQual": false,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 4,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0075",
+                        "creator": "john.wy",
+                        "description": "适用于车辆停车使用相关的服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "停车服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 5,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0076",
+                        "creator": "john.wy",
+                        "description": "适用于提供专业驾驶协助相关的服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622186923000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "代驾服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 6,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0077",
+                        "creator": "john.wy",
+                        "description": "适用于提供电动汽车充换电相关的服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "电动汽车充换电",
+                        "needSpecialQual": true,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 7,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0078",
+                        "creator": "john.wy",
+                        "description": "适用于提供两轮电瓶车充换电相关的服务",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1722829204000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "两轮电瓶车充换电",
+                        "needSpecialQual": false,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 8,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0079",
+                        "creator": "john.wy",
+                        "description": "适用于租车公司,提供汽车租赁、人工咨询、在线预约、在线下单、在线/当面付费等服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "汽车租赁",
+                        "needSpecialQual": false,
+                        "parentCode": "A0005",
+                        "parentName": "车主生活",
+                        "sortNum": 9,
+                        "special": false,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0005",
+                "creator": "john.wy",
+                "description": "车生活服务",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767921000,
+                "gmtModified": 1612260327000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "车主生活",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 5,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0090",
+                        "creator": "john.wy",
+                        "description": "适用于提供加油卡相关资讯、销售、充值服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "加油卡、加油服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 7,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0091",
+                        "creator": "john.wy",
+                        "description": "适用于提供加油、高速公路休息等服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "加油站、加气站",
+                        "needSpecialQual": true,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 8,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0084",
+                        "creator": "john.wy",
+                        "description": "适用于提供公路客运的服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1664248639000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "公路客运",
+                        "needSpecialQual": true,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 1,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0085",
+                        "creator": "john.wy",
+                        "description": "适用于提供出租车客运的服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1664196666000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "出租车客运",
+                        "needSpecialQual": true,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 2,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0097",
+                        "creator": "john.wy",
+                        "description": "适用于提供航空客运服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1675240439000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "航空公司",
+                        "needSpecialQual": true,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 14,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0086",
+                        "creator": "john.wy",
+                        "description": "适用于提供快车、专车或其他网约车在线预约/支付、出行交通行程信息展示等服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1724998178000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "网约车客运",
+                        "needSpecialQual": true,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 3,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0098",
+                        "creator": "john.wy",
+                        "description": "适用于机场申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "机场",
+                        "needSpecialQual": false,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 15,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0087",
+                        "creator": "john.wy",
+                        "description": "适用于提供地铁客运的服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "地铁",
+                        "needSpecialQual": true,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 4,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0099",
+                        "creator": "john.wy",
+                        "description": "适用于提供中国民用航空运输销售代理业务服务的公司申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1648192281000,
+                        "level": 2,
+                        "modifier": "size.lsz",
+                        "name": "机票代理人",
+                        "needSpecialQual": true,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 16,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0088",
+                        "creator": "john.wy",
+                        "description": "适用于提供公共交通客运的服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1665458996000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "公共交通",
+                        "needSpecialQual": true,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 5,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0100",
+                        "creator": "john.wy",
+                        "description": "适用于提供航空客运资讯查询、人工咨询服务、在线预约、在线购票、值机等服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "航空系统商",
+                        "needSpecialQual": false,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 17,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0089",
+                        "creator": "john.wy",
+                        "description": "适用于提供两轮车出行的服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622186996000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "共享两轮车服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 6,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0101",
+                        "creator": "john.wy",
+                        "description": "适用于提供火车票预定、购票、退票、火车出行资讯或人工服务等服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "铁路旅客运输",
+                        "needSpecialQual": true,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 18,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0102",
+                        "creator": "john.wy",
+                        "description": "适用于游轮及巡游航线的服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "游轮及巡游航线服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0006",
+                        "parentName": "交通出行",
+                        "sortNum": 19,
+                        "special": false,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0006",
+                "creator": "john.wy",
+                "description": "出行物流运输",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767921000,
+                "gmtModified": 1612260340000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "交通出行",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 6,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0060",
+                        "creator": "john.wy",
+                        "description": "适用于提供拍卖、收藏的服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1621324651000,
+                        "level": 2,
+                        "modifier": "yumai.cw",
+                        "name": "拍卖/收藏",
+                        "needSpecialQual": true,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 17,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0061",
+                        "creator": "john.wy",
+                        "description": "其他商业及生活服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "其他商业及生活服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 18,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0116",
+                        "creator": "john.wy",
+                        "description": "提供本地综合类生活信息服务的平台",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622187023000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "生活服务平台",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 9,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0053",
+                        "creator": "john.wy",
+                        "description": "适用于个人提供婚介、婚庆周边、丽人摄影等相关服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "婚介/婚庆/摄影服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 10,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0054",
+                        "creator": "john.wy",
+                        "description": "适用于提供商业广告、会展设计、图文印刷等相关等服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1602767823000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "广告/会展/图文印刷",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 11,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0230",
+                        "creator": "zxl01535939",
+                        "description": "适用场景包括但不限于,场站(机场/高铁/公交等)、场域(商圈/运动场馆/滑雪场等)、门店等提供实物及相关配套租赁服务的商家申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1717567450000,
+                        "gmtModified": 1717567450000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "目的地租赁",
+                        "needSpecialQual": true,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 29,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0055",
+                        "creator": "john.wy",
+                        "description": "适用于提供法律咨询、付费法律协助等服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "法律咨询/律师事务所",
+                        "needSpecialQual": true,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 12,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0231",
+                        "creator": "zxl01535939",
+                        "description": "适用于长租/短租,住房、商铺和企业办公场地租赁等商家申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1717643244000,
+                        "gmtModified": 1717643244000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "房产租赁",
+                        "needSpecialQual": true,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 30,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0056",
+                        "creator": "john.wy",
+                        "description": "适用于提供证券、基金、期货投资等在线咨询、培训服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "会计/金融咨询服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 13,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0057",
+                        "creator": "john.wy",
+                        "description": "适用于提供征信和信用报告咨询服务。",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "征信和信用报告咨询服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 14,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0112",
+                        "creator": "john.wy",
+                        "description": "适用于提供在线工具类服务公司申请,如网盘、下载软件等",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622187017000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "在线工具",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 5,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0058",
+                        "creator": "john.wy",
+                        "description": "适用于提供猎头、职业中介等招聘服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "人才招聘服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 15,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0212",
+                        "creator": "john.wy",
+                        "description": "适用于提供共享充电宝及共享雨伞等信用借还服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1609322436000,
+                        "gmtModified": 1609322438000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "共享充电宝及其他共享租赁",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 10,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0059",
+                        "creator": "john.wy",
+                        "description": "适用于提供丧仪殡葬的服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1609816623000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "丧葬服务",
+                        "needSpecialQual": true,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 16,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0213",
+                        "creator": "john.wy",
+                        "description": "适用于提供自助售卖机等零售相关服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1609322481000,
+                        "gmtModified": 1609322482000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "无人值守自助零售",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 11,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0214",
+                        "creator": "john.wy",
+                        "description": "适用于提供自助KTV、夹娃娃机等娱乐服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1609322528000,
+                        "gmtModified": 1609322527000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "无人值守自助娱乐",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 12,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0050",
+                        "creator": "john.wy",
+                        "description": "适用于宠物医院提供宠物、家禽治疗预约,宠物美容、宠物资讯等服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622186875000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "宠物医院/其他宠物服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 7,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0051",
+                        "creator": "john.wy",
+                        "description": "适用于3C数码,如手机、电脑、相机、无人机、游戏机、智能配件等;时尚生活,如奢侈品包、珠宝首饰(含门店);居家生活,如家具、家电、母婴医疗器械(含门店);运动健康,如自行车(含门店);教育艺术,如乐器(含门店)等场景经营的商家申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1722235304000,
+                        "level": 2,
+                        "modifier": "wb-zh854279",
+                        "name": "消费品租赁",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 8,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0052",
+                        "creator": "john.wy",
+                        "description": "适用于提供自助按摩椅、自助洗衣机等服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "无人值守自助服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 9,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0227",
+                        "creator": "swl01119956",
+                        "description": "适用于提供送水订奶相关服务的商户",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1677652205000,
+                        "gmtModified": 1681985780000,
+                        "level": 2,
+                        "modifier": "swl01119956",
+                        "name": "送水订奶",
+                        "needSpecialQual": true,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 26,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0229",
+                        "creator": "zxl01535939",
+                        "description": "适用于以企业为承租主体,开展租赁业务的模式;主要涵盖办公设备租赁、商用设备租赁、工程器械租赁三大业务场景的商家申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1717556662000,
+                        "gmtModified": 1717556662000,
+                        "level": 2,
+                        "modifier": "zxl01535939",
+                        "name": "企业租赁",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 28,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0044",
+                        "creator": "john.wy",
+                        "description": "适用于美容美体场所,提供美甲、美容、美睫、美发、纹身、祛斑、祛痘、纤体瘦身等服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "美发/美容/美甲服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 1,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0165",
+                        "creator": "john.wy",
+                        "description": "适用于物业公司申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1655117190000,
+                        "level": 2,
+                        "modifier": "size.lsz",
+                        "name": "物业管理",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 5,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0045",
+                        "creator": "john.wy",
+                        "description": "适用于提供洗浴/保健养生等服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "洗浴/保健养生服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 2,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0046",
+                        "creator": "john.wy",
+                        "description": "适用于提供家政服务,衣物干洗清洁的服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "家政/清洁服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 3,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0047",
+                        "creator": "john.wy",
+                        "description": "适用于提供家电维修、数码电器维修等服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1602767823000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "电器/家具/其他维修",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 4,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0048",
+                        "creator": "john.wy",
+                        "description": "适用于提供房屋设计、装修相关的服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "建筑装饰/装修服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 5,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0049",
+                        "creator": "john.wy",
+                        "description": "适用于提供租房、新房、二手房等房源信息等服务。",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "地产/房屋中介代理",
+                        "needSpecialQual": false,
+                        "parentCode": "A0003",
+                        "parentName": "商业生活服务",
+                        "sortNum": 6,
+                        "special": false,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0003",
+                "creator": "john.wy",
+                "description": "商业生活服务",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767921000,
+                "gmtModified": 1602767922000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "商业生活服务",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 3,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0106",
+                        "creator": "john.wy",
+                        "description": "适用于国际货运代理和报关服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1612259870000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "国际货运代理和报关行",
+                        "needSpecialQual": false,
+                        "parentCode": "A0015",
+                        "parentName": "物流运输",
+                        "sortNum": 11,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0107",
+                        "creator": "john.wy",
+                        "description": "其他运输代理业",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1612259889000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "其他运输代理业",
+                        "needSpecialQual": false,
+                        "parentCode": "A0015",
+                        "parentName": "物流运输",
+                        "sortNum": 12,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0092",
+                        "creator": "john.wy",
+                        "description": "适用于公司主体的物流/快递申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1612683420000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "物流/快递公司",
+                        "needSpecialQual": true,
+                        "parentCode": "A0015",
+                        "parentName": "物流运输",
+                        "sortNum": 9,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0093",
+                        "creator": "john.wy",
+                        "description": "适用于个人商户集合多家快递的收发服务申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1664243692000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "快递服务(个人商户)",
+                        "needSpecialQual": false,
+                        "parentCode": "A0015",
+                        "parentName": "物流运输",
+                        "sortNum": 2,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0094",
+                        "creator": "john.wy",
+                        "description": "适用于***邮政管理局(非快递公司,中国邮政不属于国家邮政)申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1612259754000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "邮政基本服务",
+                        "needSpecialQual": false,
+                        "parentCode": "A0015",
+                        "parentName": "物流运输",
+                        "sortNum": 5,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0095",
+                        "creator": "john.wy",
+                        "description": "适用于公司主体的驿站、自提柜服务申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1669702063000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "驿站/自提柜",
+                        "needSpecialQual": true,
+                        "parentCode": "A0015",
+                        "parentName": "物流运输",
+                        "sortNum": 6,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0103",
+                        "creator": "john.wy",
+                        "description": "适用于提供铁路货物运输的服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1612259809000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "铁路货物运输",
+                        "needSpecialQual": true,
+                        "parentCode": "A0015",
+                        "parentName": "物流运输",
+                        "sortNum": 8,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0104",
+                        "creator": "john.wy",
+                        "description": "适用于船舶、海运的服务",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1612259841000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "船舶、海运服务提供商",
+                        "needSpecialQual": true,
+                        "parentCode": "A0015",
+                        "parentName": "物流运输",
+                        "sortNum": 9,
+                        "special": true,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0015",
+                "creator": "john.wy",
+                "description": "物流运输",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1612259245000,
+                "gmtModified": 1612259245000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "物流运输",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 15,
+                "special": false,
+                "status": "VALID"
+            },
+            {
+                "childrenNodes": [
+                    {
+                        "childrenNodes": [],
+                        "code": "B0062",
+                        "creator": "john.wy",
+                        "description": "适用于歌舞厅、夜店、休闲会所、KTV等场所申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1602767823000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "歌舞厅/休闲会所/KTV",
+                        "needSpecialQual": false,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 1,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0063",
+                        "creator": "john.wy",
+                        "description": "适用于棋牌桌游/电玩网吧等场所申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "棋牌桌游/电玩网吧",
+                        "needSpecialQual": false,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 2,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0205",
+                        "creator": "john.wy",
+                        "description": "适用于游戏充值平台、游戏金币交易的公司等申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1609322703000,
+                        "gmtModified": 1631095459000,
+                        "level": 2,
+                        "modifier": "size.lsz",
+                        "name": "游戏周边服务/交易平台",
+                        "needSpecialQual": true,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 4,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0108",
+                        "creator": "john.wy",
+                        "description": "适用于在线社交类服务提供公司申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1612260220000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "网络社交",
+                        "needSpecialQual": false,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 1,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0109",
+                        "creator": "john.wy",
+                        "description": "适用于提供在线视频点播、在线小说、图书以及音乐等下载服务等公司申请",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1612260237000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "网络图书/视频/音乐",
+                        "needSpecialQual": true,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 2,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0064",
+                        "creator": "john.wy",
+                        "description": "适用于健身场所、瑜伽房、舞蹈室等场所申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "健身房/瑜伽/舞蹈",
+                        "needSpecialQual": false,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 3,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0065",
+                        "creator": "john.wy",
+                        "description": "适用于话剧演出、体育赛事、演唱会等场所申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "院线影城/演出赛事",
+                        "needSpecialQual": false,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 4,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0110",
+                        "creator": "john.wy",
+                        "description": "适用于游戏开发、运营公司申请使用",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1633757690000,
+                        "level": 2,
+                        "modifier": "size.lsz",
+                        "name": "游戏",
+                        "needSpecialQual": true,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 3,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0066",
+                        "creator": "john.wy",
+                        "description": "适用于游乐园/嘉年华等场所申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "游乐园/嘉年华",
+                        "needSpecialQual": false,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 5,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0111",
+                        "creator": "john.wy",
+                        "description": "适用于提供在线直播等服务",
+                        "display": true,
+                        "door": false,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1622187003000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "网络直播",
+                        "needSpecialQual": true,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 4,
+                        "special": true,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0067",
+                        "creator": "john.wy",
+                        "description": "适用于图书馆、档案馆、美术馆等场所申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "文化场馆",
+                        "needSpecialQual": false,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 6,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0068",
+                        "creator": "john.wy",
+                        "description": "适用于体育场馆等场所申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767921000,
+                        "gmtModified": 1602767922000,
+                        "level": 2,
+                        "modifier": "john.wy",
+                        "name": "体育场馆",
+                        "needSpecialQual": false,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 7,
+                        "special": false,
+                        "status": "VALID"
+                    },
+                    {
+                        "childrenNodes": [],
+                        "code": "B0069",
+                        "creator": "john.wy",
+                        "description": "适用于体育/福利彩票售卖点等场所申请",
+                        "display": true,
+                        "door": true,
+                        "gmtCreate": 1602767822000,
+                        "gmtModified": 1671096732000,
+                        "level": 2,
+                        "modifier": "yan.zhouzy",
+                        "name": "彩票",
+                        "needSpecialQual": true,
+                        "parentCode": "A0004",
+                        "parentName": "休闲娱乐",
+                        "sortNum": 8,
+                        "special": true,
+                        "status": "VALID"
+                    }
+                ],
+                "code": "A0004",
+                "creator": "john.wy",
+                "description": "休闲娱乐",
+                "display": true,
+                "door": true,
+                "gmtCreate": 1602767921000,
+                "gmtModified": 1602767922000,
+                "level": 1,
+                "modifier": "john.wy",
+                "name": "休闲娱乐",
+                "needSpecialQual": false,
+                "parentCode": "ROOT",
+                "parentName": "根节点",
+                "sortNum": 4,
+                "special": false,
+                "status": "VALID"
+            }
+        ],
+        "code": "ROOT",
+        "description": "根节点",
+        "display": true,
+        "door": false,
+        "level": 1,
+        "name": "根节点",
+        "needSpecialQual": false,
+        "sortNum": 0,
+        "special": false,
+        "status": "VALID"
+    },
+    "success": true,
+    "traceId": "21d562b217755422801731698e7173"
+}

+ 154 - 0
src/views/businessInfo/createApply.vue

@@ -0,0 +1,154 @@
+<template>
+  <div class="create-apply-page">
+    <div class="page-header">
+      <h1 class="page-title">选择主体类型</h1>
+    </div>
+
+    <div class="card-grid">
+      <div v-for="item in entityTypeList" :key="item.key" class="entity-card">
+        <h3 class="card-title">
+          {{ item.title }}
+        </h3>
+        <p class="card-desc">
+          {{ item.desc }}
+        </p>
+        <el-button class="btn-select" @click="onSelectEntity(item)"> 选择 </el-button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
+import { localSet } from "@/utils/index";
+
+const router = useRouter();
+
+const BUSINESS_DATA_CACHE_KEY = "businessData";
+
+type EntityTypeKey = "individual" | "enterprise" | "publicInstitution" | "socialOrganization" | "government" | "type";
+
+interface EntityTypeItem {
+  key: EntityTypeKey;
+  title: string;
+  desc: string;
+  type: "SUPER" | "LEGAL";
+}
+
+const entityTypeList: EntityTypeItem[] = [
+  {
+    key: "individual",
+    type: "SUPER",
+    title: "个体工商户",
+    desc: "营业执照上的主体类型一般为个体户、个体工商户、个体经营"
+  },
+  {
+    key: "enterprise",
+    title: "企业",
+    type: "LEGAL",
+    desc: "营业执照上的主体类型一般为有限公司、有限责任公司"
+  }
+];
+
+function openEntityGuide() {
+  ElMessage.info("主体指引说明可在此接入文档或弹窗");
+}
+
+function onSelectEntity(item: EntityTypeItem) {
+  const businessData = {
+    entityType: item.key,
+    contact_type: item.type
+  };
+  localSet(BUSINESS_DATA_CACHE_KEY, businessData);
+  router.push({
+    path: "/businessInfo/dataEntry",
+    query: { entityType: item.key }
+  });
+}
+</script>
+
+<style scoped lang="scss">
+.create-apply-page {
+  box-sizing: border-box;
+  min-height: 100%;
+  padding: 24px 32px 48px;
+  background: #ffffff;
+}
+.page-header {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px;
+  align-items: center;
+  justify-content: space-between;
+  margin: 0 auto 28px;
+}
+.page-title {
+  margin: 0;
+  font-size: 22px;
+  font-weight: 600;
+  color: #303133;
+  letter-spacing: 0.02em;
+}
+.guide-link {
+  font-size: 14px;
+}
+.card-grid {
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  gap: 20px;
+  margin: 0 auto;
+}
+
+@media (width <= 1100px) {
+  .card-grid {
+    grid-template-columns: repeat(2, 1fr);
+  }
+}
+
+@media (width <= 640px) {
+  .card-grid {
+    grid-template-columns: 1fr;
+  }
+}
+.entity-card {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: flex-start;
+  min-height: 220px;
+  padding: 24px 20px 20px;
+  text-align: center;
+  background: #ffffff;
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  box-shadow: 0 1px 2px rgb(0 0 0 / 4%);
+}
+.card-title {
+  margin: 0 0 12px;
+  font-size: 16px;
+  font-weight: 600;
+  line-height: 1.4;
+  color: #303133;
+}
+.card-desc {
+  flex: 1;
+  margin: 0 0 20px;
+  font-size: 13px;
+  line-height: 1.65;
+  color: #909399;
+}
+.btn-select {
+  min-width: 120px;
+  height: 34px;
+  padding: 0 20px;
+  font-size: 14px;
+  color: #ffffff !important;
+  background: #00c05b !important;
+  border: none !important;
+  border-radius: 4px;
+  &:hover {
+    background: #00a850 !important;
+  }
+}
+</style>

+ 356 - 0
src/views/businessInfo/dataEntry.vue

@@ -0,0 +1,356 @@
+<template>
+  <div class="data-entry-page">
+    <h1 class="page-main-title">资料填写</h1>
+
+    <!-- 申请单信息 -->
+    <section class="content-block">
+      <h2 class="section-head">
+        <span class="section-bar" aria-hidden="true" />
+        申请单信息
+      </h2>
+      <div class="app-info-row">
+        <div class="app-info-item">
+          <span class="label">已选主体类型</span>
+          <span class="value">{{ entityTypeLabel }}</span>
+          <el-link type="primary" :underline="false" class="modify-link" @click="onModifyEntityType"> 修改 </el-link>
+        </div>
+        <div class="app-info-item">
+          <span class="label">创建时间</span>
+          <span class="value mono">{{ applicationMeta.createdAt }}</span>
+        </div>
+        <div class="app-info-item">
+          <span class="label">申请单编号</span>
+          <span class="value mono">{{ applicationMeta.applicationNo }}</span>
+        </div>
+      </div>
+    </section>
+
+    <!-- 必填信息 -->
+    <section class="content-block">
+      <h2 class="section-head">
+        <span class="section-bar" aria-hidden="true" />
+        必填信息
+      </h2>
+      <ul class="step-list" role="list">
+        <li v-for="step in requiredSteps" :key="step.key" class="step-item">
+          <div class="step-indicator" :class="{ 'is-current': step.active }" aria-hidden="true">
+            <span v-if="step.active" class="dot-inner" />
+          </div>
+          <div class="step-main">
+            <div class="step-title-row">
+              <span class="step-title">{{ step.title }}</span>
+              <el-link v-if="step.showAction" type="info" :underline="false" class="step-action" @click="onGoFill(step.key)">
+                去填写 &gt;
+              </el-link>
+            </div>
+            <p class="step-desc">
+              {{ step.desc }}
+            </p>
+          </div>
+        </li>
+      </ul>
+    </section>
+
+    <!-- 选填信息 -->
+    <section class="content-block">
+      <h2 class="section-head">
+        <span class="section-bar" aria-hidden="true" />
+        选填信息
+      </h2>
+      <div class="optional-block">
+        <div class="optional-title">补充材料</div>
+        <p class="optional-desc">根据实际审核情况,额外要求商家提供指定的补充资料</p>
+      </div>
+    </section>
+
+    <!-- 协议 -->
+    <div class="agreement-block">
+      <el-checkbox v-model="agreementChecked" class="agreement-checkbox">
+        <span class="agreement-text">
+          商户自愿申请微信支付商户号,以上申请单资料由商户整理并委托本机构代为填写;最终提交资料以商户确认信息为准。
+        </span>
+      </el-checkbox>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed, reactive, ref } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
+
+/** 与 createApply 主体类型 key 对齐,便于路由 query 传入 */
+export type EntityTypeKey = "individual" | "enterprise" | "publicInstitution" | "socialOrganization" | "government";
+
+const ENTITY_LABEL: Record<EntityTypeKey, string> = {
+  individual: "个体工商户",
+  enterprise: "企业",
+  publicInstitution: "事业单位",
+  socialOrganization: "社会组织",
+  government: "政府机关"
+};
+
+const props = withDefaults(
+  defineProps<{
+    /** 路由或父组件传入的主体类型 */
+    entityType?: EntityTypeKey | string;
+  }>(),
+  {
+    entityType: undefined
+  }
+);
+
+const route = useRoute();
+const router = useRouter();
+
+const entityTypeLabel = computed(() => {
+  const k = (props.entityType ?? route.query.entityType ?? "individual") as EntityTypeKey;
+  return ENTITY_LABEL[k] ?? "个体工商户";
+});
+
+const applicationMeta = reactive({
+  createdAt: "2026-03-30 16:59:12",
+  applicationNo: "2000002773599273"
+});
+
+interface RequiredStep {
+  key: string;
+  title: string;
+  desc: string;
+  active: boolean;
+  showAction: boolean;
+}
+
+const requiredSteps = ref<RequiredStep[]>([
+  {
+    key: "entity",
+    title: "主体信息",
+    desc: "请填写商家的营业执照/登记证书、经营者/法人的证件等信息",
+    active: true,
+    showAction: true
+  },
+  {
+    key: "business",
+    title: "经营信息",
+    desc: "请填写商家的经营业务信息、售卖商品/提供服务场景信息",
+    active: false,
+    showAction: false
+  },
+  {
+    key: "industry",
+    title: "行业资质",
+    desc: "请填写商家所属行业、特殊资质等信息",
+    active: false,
+    showAction: false
+  },
+  {
+    key: "settlement",
+    title: "结算账户",
+    desc: "请填写商家提现收款的银行账户信息",
+    active: false,
+    showAction: false
+  },
+  {
+    key: "admin",
+    title: "超级管理员",
+    desc: "请填写商家的超级管理员信息,超级管理员需在开户后进行签约,并接收日常重要管理信息和进行资金操作,请确定其为商户法定代表人或负责人",
+    active: false,
+    showAction: false
+  }
+]);
+
+const agreementChecked = ref(true);
+
+function onModifyEntityType() {
+  router.push({
+    path: "/businessInfo/weChartIndex"
+  });
+}
+
+function onGoFill(stepKey: string) {
+  if (stepKey === "entity") {
+    router.push({
+      path: "/businessInfo/subjectInfo",
+      query: { ...route.query }
+    });
+    return;
+  }
+  ElMessage.info(`进入填写:${stepKey}(可接路由)`);
+}
+</script>
+
+<style scoped lang="scss">
+$wechat-green: #07c160;
+.data-entry-page {
+  box-sizing: border-box;
+  min-height: 100%;
+  padding: 24px 32px 48px;
+  margin: 0 auto;
+  background: #ffffff;
+}
+.page-main-title {
+  margin: 0 0 28px;
+  font-size: 20px;
+  font-weight: 600;
+  color: #303133;
+}
+.content-block {
+  padding-bottom: 28px;
+  margin-bottom: 32px;
+  border-bottom: 1px solid #ebeef5;
+  &:last-of-type {
+    padding-bottom: 0;
+    margin-bottom: 24px;
+    border-bottom: none;
+  }
+}
+.section-head {
+  display: flex;
+  align-items: center;
+  margin: 0 0 16px;
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+}
+.section-bar {
+  display: inline-block;
+  flex-shrink: 0;
+  width: 4px;
+  height: 16px;
+  margin-right: 8px;
+  background: $wechat-green;
+  border-radius: 2px;
+}
+.app-info-row {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 16px 32px;
+  align-items: baseline;
+  font-size: 14px;
+  line-height: 1.6;
+  color: #606266;
+}
+.app-info-item {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 6px 8px;
+  align-items: center;
+}
+.app-info-item .label {
+  color: #909399;
+}
+.app-info-item .value {
+  color: #303133;
+}
+.app-info-item .value.mono {
+  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+  font-size: 13px;
+}
+.modify-link {
+  margin-left: 4px;
+  font-size: 14px;
+}
+.step-list {
+  padding: 0;
+  margin: 0;
+  list-style: none;
+}
+.step-item {
+  display: flex;
+  gap: 12px;
+  padding: 16px 0;
+  border-bottom: 1px solid #f0f2f5;
+  &:last-child {
+    padding-bottom: 0;
+    border-bottom: none;
+  }
+}
+.step-indicator {
+  flex-shrink: 0;
+  width: 14px;
+  height: 14px;
+  margin-top: 4px;
+  border: 2px solid #dcdfe6;
+  border-radius: 50%;
+  &.is-current {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: $wechat-green;
+    border-color: $wechat-green;
+  }
+}
+.dot-inner {
+  width: 5px;
+  height: 5px;
+  background: #ffffff;
+  border-radius: 50%;
+}
+.step-main {
+  flex: 1;
+  min-width: 0;
+}
+.step-title-row {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px 16px;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 6px;
+}
+.step-title {
+  font-size: 15px;
+  font-weight: 600;
+  color: #303133;
+}
+.step-desc {
+  margin: 0;
+  font-size: 13px;
+  line-height: 1.65;
+  color: #909399;
+}
+.step-action {
+  flex-shrink: 0;
+  font-size: 13px;
+  color: #909399 !important;
+  &:hover {
+    color: #606266 !important;
+  }
+}
+.optional-block {
+  padding: 4px 0 0;
+}
+.optional-title {
+  margin-bottom: 8px;
+  font-size: 15px;
+  font-weight: 600;
+  color: #303133;
+}
+.optional-desc {
+  margin: 0;
+  font-size: 13px;
+  line-height: 1.65;
+  color: #909399;
+}
+.agreement-block {
+  padding-top: 8px;
+}
+.agreement-checkbox {
+  align-items: flex-start;
+  :deep(.el-checkbox__label) {
+    line-height: 1.65;
+    white-space: normal;
+  }
+  :deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
+    background-color: $wechat-green;
+    border-color: $wechat-green;
+  }
+  :deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
+    color: #606266;
+  }
+}
+.agreement-text {
+  font-size: 13px;
+  color: #606266;
+}
+</style>

+ 257 - 0
src/views/businessInfo/industryQualifications.vue

@@ -0,0 +1,257 @@
+<template>
+  <div class="industry-qual-page">
+    <h1 class="page-title">行业资质</h1>
+
+    <section class="form-block">
+      <h2 class="section-head">
+        <span class="section-bar" aria-hidden="true" />
+        行业资质
+        <span class="section-intro">请填写商家的所属行业、特殊资质等信息</span>
+      </h2>
+
+      <el-form
+        ref="formRef"
+        class="industry-form"
+        :model="form"
+        :rules="rules"
+        label-width="160px"
+        require-asterisk-position="right"
+        label-position="right"
+      >
+        <el-form-item label="所属行业" prop="industry">
+          <el-select
+            v-model="form.industry"
+            placeholder="请选择"
+            filterable
+            clearable
+            style="max-width: 480px"
+            @change="onIndustryChange"
+          >
+            <el-option v-for="o in industryOptions" :key="o.value" :label="o.label" :value="o.value" />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="结算费率">
+          <span class="settlement-rate-text">{{ settlementRateText }}</span>
+        </el-form-item>
+
+        <!-- <el-form-item label="优惠费率活动(选填)" prop="discountActivity">
+          <div class="field-stack">
+            <el-select
+              v-model="form.discountActivity"
+              placeholder="请选择"
+              clearable
+              style="max-width: 480px"
+            >
+              <el-option
+                v-for="o in discountActivityOptions"
+                :key="o.value"
+                :label="o.label"
+                :value="o.value"
+              />
+            </el-select>
+            <p class="field-tip">
+              部分行业可报名优惠费率活动,活动介绍请查看
+              <el-link type="primary" :underline="false" @click="openDiscountDetail">查看详情</el-link>
+            </p>
+          </div>
+        </el-form-item> -->
+      </el-form>
+    </section>
+
+    <div class="footer-actions">
+      <el-button @click="onBack"> 返回 </el-button>
+      <el-button type="primary" class="btn-next" :loading="submitLoading" @click="onSubmit"> 确定 </el-button>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed, reactive, ref } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
+import type { FormInstance, FormRules } from "element-plus";
+import { localGet, localSet } from "@/utils/index";
+
+const BUSINESS_DATA_CACHE_KEY = "businessData";
+
+const formRef = ref<FormInstance>();
+const submitLoading = ref(false);
+const route = useRoute();
+const router = useRouter();
+
+/** 演示选项,可对接字典/接口 */
+const industryOptions = [
+  { label: "餐饮", value: "716" },
+  { label: "零售", value: "catering_retail_retail" },
+  { label: "生活服务", value: "life_service" },
+  { label: "电商平台", value: "ecommerce" }
+];
+
+const discountActivityOptions = [
+  { label: "活动一:新商户费率优惠", value: "act_1" },
+  { label: "活动二:行业专项优惠", value: "act_2" }
+];
+
+/** 按行业展示结算费率(演示:默认与示意图一致) */
+const industryRateMap: Record<string, string> = {
+  "716": "0.6%",
+  catering_retail_catering: "0.6%",
+  catering_retail_retail: "0.6%",
+  life_service: "0.6%",
+  ecommerce: "0.6%"
+};
+
+const form = reactive({
+  industry: "716",
+  discountActivity: "" as string
+});
+
+const settlementRateText = computed(() => {
+  if (!form.industry) return "—";
+  return industryRateMap[form.industry] ?? "0.6%";
+});
+
+const rules: FormRules = {
+  industry: [{ required: true, message: "请选择所属行业", trigger: "change" }]
+};
+
+function onIndustryChange() {
+  formRef.value?.validateField("industry").catch(() => {});
+}
+
+function openDiscountDetail() {
+  ElMessage.info("优惠费率活动说明(可对接文档或外链)");
+}
+
+function onBack() {
+  router.push({ path: "/businessInfo/manageInfo", query: { ...route.query } });
+}
+
+function onSaveDraft() {
+  ElMessage.success("草稿已保存(可对接接口)");
+}
+
+function mergeSettlementIntoBusinessDataCache() {
+  const prev = localGet(BUSINESS_DATA_CACHE_KEY);
+  const base = prev && typeof prev === "object" && !Array.isArray(prev) ? { ...(prev as Record<string, unknown>) } : {};
+  const prevSt =
+    base.settlement_info && typeof base.settlement_info === "object" && !Array.isArray(base.settlement_info)
+      ? { ...(base.settlement_info as Record<string, unknown>) }
+      : {};
+
+  const selected = industryOptions.find(o => o.value === form.industry);
+  const industryLabel = (selected?.label ?? "").trim();
+  const settlementId = selected != null ? String(selected.value).trim() : "";
+
+  base.settlement_info = {
+    ...prevSt,
+    qualification_type: industryLabel,
+    settlement_id: settlementId
+  };
+  localSet(BUSINESS_DATA_CACHE_KEY, base);
+}
+
+async function onSubmit() {
+  if (!formRef.value) return;
+  submitLoading.value = true;
+  try {
+    await formRef.value.validate();
+    mergeSettlementIntoBusinessDataCache();
+    await router.push({
+      path: "/businessInfo/accountInfo",
+      query: { ...route.query }
+    });
+  } catch {
+    ElMessage.warning("请完善必填信息");
+  } finally {
+    submitLoading.value = false;
+  }
+}
+</script>
+
+<style scoped lang="scss">
+$wechat-green: #07c160;
+.industry-qual-page {
+  box-sizing: border-box;
+  min-height: 100%;
+  padding: 24px 32px 40px;
+  margin: 0 auto;
+  background: #ffffff;
+}
+.page-title {
+  margin: 0 0 24px;
+  font-size: 20px;
+  font-weight: 600;
+  color: #303133;
+}
+.form-block {
+  margin-bottom: 24px;
+}
+.section-head {
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
+  margin: 0 0 20px;
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+}
+.section-bar {
+  display: inline-block;
+  flex-shrink: 0;
+  width: 4px;
+  height: 16px;
+  margin-right: 8px;
+  background: $wechat-green;
+  border-radius: 2px;
+}
+.section-intro {
+  margin-left: 12px;
+  font-size: 13px;
+  font-weight: 400;
+  line-height: 1.65;
+  color: #909399;
+}
+.industry-form {
+  :deep(.el-form-item__label) {
+    font-weight: 500;
+    color: #606266;
+  }
+}
+.settlement-rate-text {
+  font-size: 14px;
+  color: #303133;
+}
+.field-stack {
+  width: 100%;
+}
+.field-tip {
+  margin: 8px 0 0;
+  font-size: 12px;
+  line-height: 1.65;
+  color: #909399;
+}
+.footer-actions {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding-top: 24px;
+  margin-top: 16px;
+  border-top: 1px solid #ebeef5;
+}
+.footer-center {
+  display: flex;
+  flex: 1;
+  justify-content: center;
+}
+.btn-next {
+  min-width: 100px;
+  background: $wechat-green;
+  border-color: $wechat-green;
+  &:hover {
+    background: #06ad56;
+    border-color: #06ad56;
+  }
+}
+</style>

+ 1114 - 0
src/views/businessInfo/manageInfo.vue

@@ -0,0 +1,1114 @@
+<template>
+  <div class="manage-info-page">
+    <h1 class="page-title">经营信息</h1>
+
+    <el-form
+      ref="formRef"
+      class="manage-form"
+      :model="form"
+      :rules="rules"
+      label-width="200px"
+      require-asterisk-position="right"
+      label-position="right"
+    >
+      <!-- 基础经营信息 -->
+      <section class="form-block">
+        <h2 class="section-head">
+          <span class="section-bar" aria-hidden="true" />
+          经营信息
+        </h2>
+
+        <el-form-item prop="merchantShortName">
+          <template #label>
+            <span class="label-with-icon">
+              商户简称
+              <el-tooltip placement="top" content="简称将展示给消费者,需与营业执照或品牌一致,勿使用无关或违规词汇。">
+                <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+              </el-tooltip>
+            </span>
+          </template>
+          <div class="field-stack">
+            <el-input
+              v-model="form.merchantShortName"
+              placeholder="请输入商户简称"
+              clearable
+              maxlength="64"
+              show-word-limit
+              style="max-width: 480px"
+            />
+            <p class="field-tip">
+              1. 在支付完成页向买家展示,需与微信经营类目相关。<br />
+              2.简称要求:<br />
+              不支持单纯以人名来命名,若为个体户经营,可用“个体户+经营者名称”或“经营者名称+业务”命名,如个体户“张三”或“张三餐饮店”;<br />
+              不支持无实际意义的文案,如“XX”特约商户,“800”,“XX客服电话XXX”;
+            </p>
+          </div>
+        </el-form-item>
+
+        <el-form-item prop="servicePhone">
+          <template #label>
+            <span class="label-with-icon">
+              客服电话
+              <el-tooltip placement="top" content="用于用户咨询与平台联系,请填写真实可接通号码。">
+                <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+              </el-tooltip>
+            </span>
+          </template>
+          <div class="field-stack">
+            <el-input
+              v-model="form.servicePhone"
+              placeholder="请输入客服电话"
+              clearable
+              maxlength="20"
+              style="max-width: 480px"
+            />
+            <p class="field-tip">
+              1.请填写真实、可接通的客服电话,以便用户咨询。<br />
+              2.请确保电话畅通,以便入驻平台回拨确认。<br />
+            </p>
+          </div>
+        </el-form-item>
+
+        <el-form-item label="经营场景" prop="scenarioBits" required>
+          <div class="field-stack">
+            <div class="scenario-checks">
+              <el-checkbox v-model="form.scenarios.offline"> 线下场景 </el-checkbox>
+              <el-checkbox v-model="form.scenarios.miniProgram"> 小程序 </el-checkbox>
+              <el-checkbox v-model="form.scenarios.app"> APP </el-checkbox>
+              <el-checkbox v-model="form.scenarios.wechatAccount"> 服务号或订阅号 </el-checkbox>
+              <el-checkbox v-model="form.scenarios.website"> 互联网网站 </el-checkbox>
+              <el-checkbox v-model="form.scenarios.wecom"> 企业微信 </el-checkbox>
+            </div>
+            <p class="field-tip">
+              请勾选实际售卖商品/提供服务场景(至少一项),以便为你开通需要的支付权限<br />
+              建议只勾选目前必须的尝尽,以便尽快通过入驻审核,其他支付权限你可在入驻后再根据实际需要发起申请
+            </p>
+          </div>
+        </el-form-item>
+      </section>
+
+      <!-- 线下场景 -->
+      <section v-if="form.scenarios.offline" class="form-block sub-section">
+        <h2 class="section-head">
+          <span class="section-bar" aria-hidden="true" />
+          线下场所
+          <span class="section-intro"
+            >你选择了“线下场所”场景,入驻成功后,服务商可帮商户发起付款码支付,JSAPI支付,同时系统将会对地址等信息进行核实</span
+          >
+        </h2>
+
+        <el-form-item label="线下场所名称" prop="offlineVenueName">
+          <el-input v-model="form.offlineVenueName" placeholder="请输入线下场所名称" clearable style="max-width: 480px" />
+        </el-form-item>
+
+        <el-form-item label="线下场所省市" prop="offlineProvinceCity">
+          <el-select v-model="form.offlineProvince" placeholder="请选择省" filterable style="width: 200px">
+            <el-option v-for="p in provinceOptions" :key="p.value" :label="p.label" :value="p.value" />
+          </el-select>
+          <el-select
+            v-model="form.offlineCity"
+            placeholder="请选择市"
+            filterable
+            style="width: 200px; margin-left: 12px"
+            :disabled="!form.offlineProvince"
+          >
+            <el-option v-for="c in cityOptions" :key="c.value" :label="c.label" :value="c.value" />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="线下场所地址" prop="offlineAddress">
+          <div class="field-stack">
+            <el-input
+              v-model="form.offlineAddress"
+              type="textarea"
+              :rows="2"
+              placeholder="请输入详细地址"
+              maxlength="200"
+              show-word-limit
+              style="max-width: 480px"
+            />
+            <p class="field-tip">如有多个经营场所,请填写主要营业地址。</p>
+          </div>
+        </el-form-item>
+
+        <el-form-item prop="offlineStorefrontUrls">
+          <template #label>
+            <span class="label-with-icon">
+              线下场所门头照片
+              <el-tooltip placement="top" content="需清晰展示门头招牌与店名。">
+                <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+              </el-tooltip>
+            </span>
+          </template>
+          <div class="field-stack">
+            <el-upload
+              v-model:file-list="form.offlineStorefrontFileList"
+              list-type="picture-card"
+              :limit="5"
+              accept=".jpg,.jpeg,.png,.bmp,image/jpeg,image/png,image/bmp"
+              :before-upload="beforeImageUpload"
+              :http-request="opt => handleMultiUpload(opt, 'storefront')"
+              :on-remove="(f, fl) => onMultiRemove(f, fl, 'storefront')"
+            >
+              <el-icon><Plus /></el-icon>
+            </el-upload>
+            <p class="field-tip">
+              1.场景图片正面拍摄且清晰,完整,图片不得有遮挡;<br />
+              2.门店招牌清晰,招牌名称,文字可辨识,门框完整,且店面显示在营,若为停车场等无固定门头照片的经营场所,可上传岗亭/出入闸口。
+            </p>
+          </div>
+        </el-form-item>
+
+        <el-form-item prop="offlineInteriorUrls">
+          <template #label>
+            <span class="label-with-icon">
+              线下场所内部照片
+              <el-tooltip placement="top" content="展示店内经营环境。">
+                <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+              </el-tooltip>
+            </span>
+          </template>
+          <div class="field-stack">
+            <el-upload
+              v-model:file-list="form.offlineInteriorFileList"
+              list-type="picture-card"
+              :limit="5"
+              accept=".jpg,.jpeg,.png,.bmp,image/jpeg,image/png,image/bmp"
+              :before-upload="beforeImageUpload"
+              :http-request="opt => handleMultiUpload(opt, 'interior')"
+              :on-remove="(f, fl) => onMultiRemove(f, fl, 'interior')"
+            >
+              <el-icon><Plus /></el-icon>
+            </el-upload>
+            <p class="field-tip">
+              1.场景图片正面拍摄且清晰,完整,图片不得有遮挡;<br />
+              2.门店招牌清晰,招牌名称,文字可辨识,门框完整,且店面显示在营,若为停车场等无固定门头照片的经营场所,可上传岗亭/出入闸口。
+            </p>
+          </div>
+        </el-form-item>
+
+        <el-form-item label="线下场所对应的服务号或公众号 APPID">
+          <div class="field-stack">
+            <el-input v-model="form.offlineMpAppId" placeholder="选填" clearable style="max-width: 480px" />
+            <p class="field-tip">
+              1.可填写已认领的服务号或公众号(需时已认证的服务号,政府或媒体类型的公众号),小程序,应用的APPID.<br />
+              2.完成进件后,系统发起特约商户号与该APPID的绑定(即配置为sub_appid,可在发起支付时传入)<br />
+              (1)若APPID主体与商家主体一致,则直接完成绑定;<br />
+              (2)若APPID主体与商家主体不一致,则需商户提供主体变更证明材料,审核通过后完成绑定。
+            </p>
+          </div>
+        </el-form-item>
+      </section>
+
+      <!-- 小程序 -->
+      <section v-if="form.scenarios.miniProgram" class="form-block sub-section">
+        <h2 class="section-head">
+          <span class="section-bar" aria-hidden="true" />
+          小程序<span class="section-intro">你选择了“小程序”场景,入驻成功后,服务商可帮商户发起JSAPI支付</span>
+        </h2>
+
+        <el-form-item label="小程序 APPID" prop="miniProgramAppId">
+          <div class="field-stack">
+            <el-input v-model="form.miniProgramAppId" placeholder="请输入小程序 APPID" clearable style="max-width: 480px" />
+            <p class="field-tip">
+              1.请填写已认证小程序的 APPID。<br />
+              2.完成进件后,系统发起特约商户号与该APPID的绑定(即配置为sub_appid,可在发起支付时传入)<br />
+              (1)若APPID主体与商家主体一致,则直接完成绑定;<br />
+              (2)若APPID主体与商家主体不一致,则需商户提供主体变更证明材料,审核通过后完成绑定。
+            </p>
+          </div>
+        </el-form-item>
+
+        <el-form-item label="小程序截图">
+          <div class="field-stack">
+            <el-upload
+              v-model:file-list="form.miniProgramShotFileList"
+              list-type="picture-card"
+              :limit="5"
+              accept=".jpg,.jpeg,.png,.bmp,image/jpeg,image/png,image/bmp"
+              :before-upload="beforeImageUpload"
+              :http-request="opt => handleMultiUpload(opt, 'miniShot')"
+              :on-remove="(f, fl) => onMultiRemove(f, fl, 'miniShot')"
+            >
+              <el-icon><Plus /></el-icon>
+            </el-upload>
+            <p class="field-tip">请提供展示商品/服务的页面截图/设计稿(最多5张),若小程序胃建设完善或未上线请务必提供。</p>
+          </div>
+        </el-form-item>
+      </section>
+
+      <!-- APP -->
+      <section v-if="form.scenarios.app" class="form-block sub-section">
+        <h2 class="section-head">
+          <span class="section-bar" aria-hidden="true" />
+          APP<span class="section-intro">你选择了“APP”场景,入驻成功后,服务商可帮商户发起APP支付</span>
+        </h2>
+
+        <el-form-item label="AppID 来源" prop="appIdSource" required>
+          <el-radio-group v-model="form.appIdSource">
+            <el-radio value="provider"> 服务商应用 AppID </el-radio>
+            <el-radio value="merchant"> 商家应用 AppID </el-radio>
+          </el-radio-group>
+        </el-form-item>
+
+        <el-form-item v-if="form.appIdSource === 'provider'" label="服务商应用 AppID" prop="providerAppId">
+          <div class="field-stack">
+            <el-select v-model="form.providerAppId" placeholder="请选择" filterable style="max-width: 480px">
+              <el-option v-for="o in providerAppOptions" :key="o.value" :label="o.label" :value="o.value" />
+            </el-select>
+          </div>
+        </el-form-item>
+
+        <el-form-item prop="appShotUrls">
+          <template #label>
+            <span class="label-with-icon">
+              APP 截图
+              <el-tooltip placement="top" content="首页、商品列表、详情、支付等相关页面。">
+                <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+              </el-tooltip>
+            </span>
+          </template>
+          <div class="field-stack">
+            <el-upload
+              v-model:file-list="form.appShotFileList"
+              list-type="picture-card"
+              :limit="5"
+              accept=".jpg,.jpeg,.png,.bmp,image/jpeg,image/png,image/bmp"
+              :before-upload="beforeImageUpload"
+              :http-request="opt => handleMultiUpload(opt, 'appShot')"
+              :on-remove="(f, fl) => onMultiRemove(f, fl, 'appShot')"
+            >
+              <el-icon><Plus /></el-icon>
+            </el-upload>
+            <p class="field-tip">请提供APP首页截图,尾页截图,应用内截图,支付页截图各1张</p>
+          </div>
+        </el-form-item>
+      </section>
+    </el-form>
+
+    <div class="footer-actions">
+      <el-button @click="onBack"> 返回 </el-button>
+      <el-button type="primary" class="btn-next" :loading="submitLoading" @click="onSubmit"> 确定 </el-button>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed, nextTick, onMounted, reactive, ref, watch } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
+import type { FormInstance, FormRules } from "element-plus";
+import type { UploadRequestOptions, UploadUserFile } from "element-plus";
+import { Plus, InfoFilled } from "@element-plus/icons-vue";
+import { getUpload } from "@/api/modules/businessInfo";
+import { localGet, localSet } from "@/utils/index";
+import cityJson from "@/assets/json/city.json";
+
+const BUSINESS_DATA_CACHE_KEY = "businessData";
+
+const formRef = ref<FormInstance>();
+const submitLoading = ref(false);
+const route = useRoute();
+const router = useRouter();
+
+type UploadKind = "storefront" | "interior" | "miniShot" | "appShot";
+
+const form = reactive({
+  merchantShortName: "",
+  servicePhone: "",
+  scenarios: {
+    offline: true,
+    miniProgram: true,
+    app: true,
+    wechatAccount: false,
+    website: false,
+    wecom: false
+  },
+  offlineVenueName: "",
+  offlineProvince: "",
+  offlineCity: "",
+  offlineAddress: "",
+  offlineStorefrontFileList: [] as UploadUserFile[],
+  offlineStorefrontUrls: [] as string[],
+  offlineInteriorFileList: [] as UploadUserFile[],
+  offlineInteriorUrls: [] as string[],
+  offlineMpAppId: "",
+  miniProgramAppId: "",
+  miniProgramShotFileList: [] as UploadUserFile[],
+  miniProgramShotUrls: [] as string[],
+  appIdSource: "provider" as "provider" | "merchant",
+  providerAppId: "",
+  merchantAppId: "",
+  appShotFileList: [] as UploadUserFile[],
+  appShotUrls: [] as string[],
+  /** 用于校验至少选一种经营场景 */
+  scenarioBits: "1"
+});
+
+/** 与进件文档 business_info.sales_info.sales_scenes_type 枚举对应 */
+function buildSalesScenesType(): string[] {
+  const s = form.scenarios;
+  const types: string[] = [];
+  if (s.offline) types.push("SALES_SCENES_STORE");
+  if (s.miniProgram) types.push("SALES_SCENES_MINI_PROGRAM");
+  if (s.app) types.push("SALES_SCENES_APP");
+  if (s.wechatAccount) types.push("SALES_SCENES_MP");
+  if (s.website) types.push("SALES_SCENES_WEB");
+  if (s.wecom) types.push("SALES_SCENES_WEWORK");
+  return types;
+}
+
+/** 上传组件更新 file-list 时可能丢 response,用 uid 备份 media_id */
+const wechatMediaIdByFileUid = new Map<number, string>();
+
+function getMediaIdFromUploadFile(f: UploadUserFile): string {
+  const tagged = String((f as UploadUserFile & { __wxMediaId?: string }).__wxMediaId ?? "").trim();
+  if (tagged) return tagged;
+  const uid = (f as UploadUserFile & { uid?: number }).uid;
+  if (uid != null && wechatMediaIdByFileUid.has(uid)) {
+    return wechatMediaIdByFileUid.get(uid) ?? "";
+  }
+  const r = (f as UploadUserFile & { response?: unknown }).response;
+  if (r && typeof r === "object" && !Array.isArray(r)) {
+    const o = r as Record<string, unknown>;
+    const direct = String(o.media_id ?? o.mediaId ?? "").trim();
+    if (direct) return direct;
+    const nested = extractMediaUploadMeta(r).mediaId;
+    if (nested) return nested;
+  }
+  return "";
+}
+
+/** 写入进件缓存的四处图片字段均为微信 media/upload 返回的 media_id */
+function collectMediaIdsForMerge(list: UploadUserFile[]): string[] {
+  return list
+    .filter(f => f.status === "success")
+    .map(f => getMediaIdFromUploadFile(f))
+    .filter(Boolean);
+}
+
+function mergeManageInfoIntoBusinessDataCache() {
+  const prev = localGet(BUSINESS_DATA_CACHE_KEY);
+  const base = prev && typeof prev === "object" && !Array.isArray(prev) ? { ...(prev as Record<string, unknown>) } : {};
+  const prevBi =
+    base.business_info && typeof base.business_info === "object" && !Array.isArray(base.business_info)
+      ? { ...(base.business_info as Record<string, unknown>) }
+      : {};
+  const prevSales =
+    prevBi.sales_info && typeof prevBi.sales_info === "object" && !Array.isArray(prevBi.sales_info)
+      ? { ...(prevBi.sales_info as Record<string, unknown>) }
+      : {};
+
+  const sales_info: Record<string, unknown> = {
+    ...prevSales,
+    sales_scenes_type: buildSalesScenesType()
+  };
+  if (form.scenarios.offline) {
+    sales_info.biz_store_info = {
+      biz_store_name: String(form.offlineVenueName || "").trim(),
+      biz_address_code: String(form.offlineCity || "").trim(),
+      biz_store_address: String(form.offlineAddress || "").trim(),
+      store_entrance_pic: collectMediaIdsForMerge(form.offlineStorefrontFileList),
+      indoor_pic: collectMediaIdsForMerge(form.offlineInteriorFileList),
+      biz_sub_appid: String(form.offlineMpAppId || "").trim()
+    };
+  } else {
+    delete sales_info.biz_store_info;
+  }
+
+  if (form.scenarios.miniProgram) {
+    sales_info.mini_program_info = {
+      mini_program_sub_appid: String(form.miniProgramAppId || "").trim(),
+      mini_program_pics: collectMediaIdsForMerge(form.miniProgramShotFileList)
+    };
+  } else {
+    delete sales_info.mini_program_info;
+  }
+
+  if (form.scenarios.app) {
+    sales_info.app_info = {
+      app_appid: String(form.providerAppId || "").trim(),
+      app_sub_appid: String(form.merchantAppId || "").trim(),
+      app_pics: collectMediaIdsForMerge(form.appShotFileList)
+    };
+  } else {
+    delete sales_info.app_info;
+  }
+
+  base.business_info = {
+    ...prevBi,
+    merchant_shortname: String(form.merchantShortName || "").trim(),
+    service_phone: String(form.servicePhone || "").trim(),
+    sales_info
+  };
+  localSet(BUSINESS_DATA_CACHE_KEY, base);
+}
+
+type CityJsonEntry = { name: string; adCode: string; cityCode: string; type?: string };
+type CityJsonRoot = { cityList: { letter: string; list: CityJsonEntry[] }[] };
+
+/** GB 行政区划代码前两位 → 省级名称(与 city.json 中 adCode 对应) */
+const PROVINCE_ROWS: [string, string][] = [
+  ["11", "北京市"],
+  ["12", "天津市"],
+  ["13", "河北省"],
+  ["14", "山西省"],
+  ["15", "内蒙古自治区"],
+  ["21", "辽宁省"],
+  ["22", "吉林省"],
+  ["23", "黑龙江省"],
+  ["31", "上海市"],
+  ["32", "江苏省"],
+  ["33", "浙江省"],
+  ["34", "安徽省"],
+  ["35", "福建省"],
+  ["36", "江西省"],
+  ["37", "山东省"],
+  ["41", "河南省"],
+  ["42", "湖北省"],
+  ["43", "湖南省"],
+  ["44", "广东省"],
+  ["45", "广西壮族自治区"],
+  ["46", "海南省"],
+  ["50", "重庆市"],
+  ["51", "四川省"],
+  ["52", "贵州省"],
+  ["53", "云南省"],
+  ["54", "西藏自治区"],
+  ["61", "陕西省"],
+  ["62", "甘肃省"],
+  ["63", "青海省"],
+  ["64", "宁夏回族自治区"],
+  ["65", "新疆维吾尔自治区"],
+  ["71", "台湾省"],
+  ["81", "香港特别行政区"],
+  ["82", "澳门特别行政区"]
+];
+const PROVINCE_BY_PREFIX = Object.fromEntries(PROVINCE_ROWS) as Record<string, string>;
+const PROVINCE_PREFIX_ORDER = PROVINCE_ROWS.map(([k]) => k);
+
+function buildProvinceCityOptions(): {
+  label: string;
+  value: string;
+  cities: { label: string; value: string }[];
+}[] {
+  const root = cityJson as CityJsonRoot;
+  const flat = root.cityList.flatMap(g => g.list);
+  const bucket = new Map<string, Map<string, CityJsonEntry>>();
+  for (const c of flat) {
+    const digits = String(c.adCode ?? "").replace(/\D/g, "");
+    const code = digits.length >= 6 ? digits.slice(-6) : digits.padStart(6, "0");
+    if (code.length !== 6) continue;
+    const prefix = code.slice(0, 2);
+    if (!PROVINCE_BY_PREFIX[prefix]) continue;
+    if (!bucket.has(prefix)) bucket.set(prefix, new Map());
+    bucket.get(prefix)!.set(c.adCode, c);
+  }
+  const out = [...bucket.entries()].map(([prefix, cityMap]) => ({
+    value: prefix,
+    label: PROVINCE_BY_PREFIX[prefix],
+    cities: [...cityMap.values()]
+      .sort((a, b) => a.name.localeCompare(b.name, "zh-CN"))
+      .map(ci => ({ label: ci.name, value: ci.adCode }))
+  }));
+  out.sort((a, b) => {
+    const ia = PROVINCE_PREFIX_ORDER.indexOf(a.value);
+    const ib = PROVINCE_PREFIX_ORDER.indexOf(b.value);
+    return (ia === -1 ? 999 : ia) - (ib === -1 ? 999 : ib);
+  });
+  return out;
+}
+
+const provinceOptions = buildProvinceCityOptions();
+
+const cityOptions = ref<{ label: string; value: string }[]>([]);
+
+watch(
+  () => form.offlineProvince,
+  code => {
+    form.offlineCity = "";
+    const p = provinceOptions.find(x => x.value === code);
+    cityOptions.value = p?.cities ?? [];
+  }
+);
+
+const providerAppOptions = [
+  { label: "请选择", value: "" },
+  { label: "wxf5f1efe3a9f5012e", value: "wxf5f1efe3a9f5012e" }
+];
+
+const scenarioChecked = computed(() => {
+  const s = form.scenarios;
+  return s.offline || s.miniProgram || s.app || s.wechatAccount || s.website || s.wecom;
+});
+
+watch(
+  () => form.scenarios,
+  () => {
+    form.scenarioBits = scenarioChecked.value ? "1" : "";
+  },
+  { deep: true }
+);
+
+function asStringArray(v: unknown): string[] {
+  if (!Array.isArray(v)) return [];
+  return v.map(x => String(x ?? "").trim()).filter(Boolean);
+}
+
+/** 从 localStorage businessData.business_info 回显经营信息表单 */
+function hydrateManageFormFromBusinessDataCache() {
+  const raw = localGet(BUSINESS_DATA_CACHE_KEY) as Record<string, unknown> | null | undefined;
+  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
+  const bi = raw.business_info as Record<string, unknown> | undefined;
+  if (!bi || typeof bi !== "object" || Array.isArray(bi)) return;
+
+  form.merchantShortName = String(bi.merchant_shortname ?? "").trim();
+  form.servicePhone = String(bi.service_phone ?? "").trim();
+
+  let pendingOfflineCity = "";
+
+  const si = bi.sales_info as Record<string, unknown> | undefined;
+  if (si && typeof si === "object" && !Array.isArray(si)) {
+    const sceneTypes = si.sales_scenes_type;
+    if (Array.isArray(sceneTypes)) {
+      const set = new Set(sceneTypes.map(t => String(t)));
+      form.scenarios.offline = set.has("SALES_SCENES_STORE");
+      form.scenarios.miniProgram = set.has("SALES_SCENES_MINI_PROGRAM");
+      form.scenarios.app = set.has("SALES_SCENES_APP");
+      form.scenarios.wechatAccount = set.has("SALES_SCENES_MP");
+      form.scenarios.website = set.has("SALES_SCENES_WEB");
+      form.scenarios.wecom = set.has("SALES_SCENES_WEWORK");
+      form.scenarioBits = scenarioChecked.value ? "1" : "";
+    }
+
+    const bzs = si.biz_store_info as Record<string, unknown> | undefined;
+    if (bzs && typeof bzs === "object" && !Array.isArray(bzs)) {
+      form.offlineVenueName = String(bzs.biz_store_name ?? "").trim();
+      const digits = String(bzs.biz_address_code ?? "").replace(/\D/g, "");
+      const code6 = digits.length >= 6 ? digits.slice(-6) : digits;
+      if (code6.length >= 2) {
+        const prefix = code6.slice(0, 2);
+        form.offlineProvince = prefix;
+        const p = provinceOptions.find(x => x.value === prefix);
+        cityOptions.value = p?.cities ?? [];
+        if (code6.length >= 6) pendingOfflineCity = code6;
+      }
+      form.offlineAddress = String(bzs.biz_store_address ?? "").trim();
+      const se = asStringArray(bzs.store_entrance_pic);
+      const indoor = asStringArray(bzs.indoor_pic);
+      form.offlineStorefrontUrls = [...se];
+      form.offlineInteriorUrls = [...indoor];
+      form.offlineStorefrontFileList = se.map(
+        (url, i) =>
+          ({
+            name: `storefront-${i + 1}.jpg`,
+            url,
+            status: "success",
+            response: { url, media_id: url, mediaId: url },
+            __wxMediaId: url
+          }) as UploadUserFile
+      );
+      form.offlineInteriorFileList = indoor.map(
+        (url, i) =>
+          ({
+            name: `interior-${i + 1}.jpg`,
+            url,
+            status: "success",
+            response: { url, media_id: url, mediaId: url },
+            __wxMediaId: url
+          }) as UploadUserFile
+      );
+      form.offlineMpAppId = String(bzs.biz_sub_appid ?? "").trim();
+    }
+
+    const mpi = si.mini_program_info as Record<string, unknown> | undefined;
+    if (mpi && typeof mpi === "object" && !Array.isArray(mpi)) {
+      form.miniProgramAppId = String(mpi.mini_program_sub_appid ?? "").trim();
+      const pics = asStringArray(mpi.mini_program_pics);
+      form.miniProgramShotUrls = [...pics];
+      form.miniProgramShotFileList = pics.map(
+        (url, i) =>
+          ({
+            name: `mini-${i + 1}.jpg`,
+            url,
+            status: "success",
+            response: { url, media_id: url, mediaId: url },
+            __wxMediaId: url
+          }) as UploadUserFile
+      );
+    }
+
+    const appInf = si.app_info as Record<string, unknown> | undefined;
+    if (appInf && typeof appInf === "object" && !Array.isArray(appInf)) {
+      form.providerAppId = String(appInf.app_appid ?? "").trim();
+      form.merchantAppId = String(appInf.app_sub_appid ?? "").trim();
+      form.appIdSource = form.providerAppId ? "provider" : "merchant";
+      const pics = asStringArray(appInf.app_pics);
+      form.appShotUrls = [...pics];
+      form.appShotFileList = pics.map(
+        (url, i) =>
+          ({
+            name: `app-${i + 1}.jpg`,
+            url,
+            status: "success",
+            response: { url, media_id: url, mediaId: url },
+            __wxMediaId: url
+          }) as UploadUserFile
+      );
+    }
+  }
+
+  nextTick(() => {
+    if (pendingOfflineCity) form.offlineCity = pendingOfflineCity;
+    formRef.value?.clearValidate();
+  });
+}
+
+onMounted(() => {
+  hydrateManageFormFromBusinessDataCache();
+});
+
+const rules: FormRules = {
+  merchantShortName: [{ required: true, message: "请输入商户简称", trigger: "blur" }],
+  servicePhone: [
+    { required: true, message: "请输入客服电话", trigger: "blur" },
+    { pattern: /^[\d\-+\s]{5,20}$/, message: "请输入有效电话号码", trigger: "blur" }
+  ],
+  scenarioBits: [{ required: true, message: "请至少选择一种经营场景", trigger: "change" }],
+  offlineVenueName: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.scenarios.offline && !String(form.offlineVenueName).trim()) {
+          cb(new Error("请输入线下场所名称"));
+        } else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  offlineProvinceCity: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.scenarios.offline && (!form.offlineProvince || !form.offlineCity)) {
+          cb(new Error("请选择线下场所省市"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  offlineAddress: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.scenarios.offline && !String(form.offlineAddress).trim()) {
+          cb(new Error("请输入线下场所地址"));
+        } else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  offlineStorefrontUrls: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.scenarios.offline && form.offlineStorefrontUrls.length < 1) {
+          cb(new Error("请上传门头照片"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  offlineInteriorUrls: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.scenarios.offline && form.offlineInteriorUrls.length < 1) {
+          cb(new Error("请上传内部照片"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  miniProgramAppId: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.scenarios.miniProgram && !String(form.miniProgramAppId).trim()) {
+          cb(new Error("请输入小程序 APPID"));
+        } else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  providerAppId: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.scenarios.app && form.appIdSource === "provider" && !String(form.providerAppId).trim()) {
+          cb(new Error("请选择服务商应用 AppID"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  appShotUrls: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.scenarios.app && form.appShotUrls.length < 1) {
+          cb(new Error("请上传 APP 截图"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ]
+};
+
+const MAX_IMG_MB = 5;
+
+function beforeImageUpload(file: File) {
+  const name = file.name?.toLowerCase() || "";
+  const okExt = /\.(jpe?g|png|bmp)$/i.test(name);
+  const okMime = ["image/jpeg", "image/png", "image/bmp"].includes(file.type);
+  if (!okExt && !okMime) {
+    ElMessage.error("图片只支持 JPG、BMP、PNG 格式");
+    return false;
+  }
+  if (file.size / 1024 / 1024 > MAX_IMG_MB) {
+    ElMessage.error(`文件大小不能超过 ${MAX_IMG_MB}M`);
+    return false;
+  }
+  return true;
+}
+
+function urlListKey(kind: UploadKind): "offlineStorefrontUrls" | "offlineInteriorUrls" | "miniProgramShotUrls" | "appShotUrls" {
+  const map = {
+    storefront: "offlineStorefrontUrls",
+    interior: "offlineInteriorUrls",
+    miniShot: "miniProgramShotUrls",
+    appShot: "appShotUrls"
+  } as const;
+  return map[kind];
+}
+
+/** 解析 getUpload 响应:兼容 data 为字符串、双层 data、嵌套对象等 */
+function extractMediaUploadMeta(res: any): { fileUrl: string; mediaId: string; errMsg: string } {
+  const errMsg = String(res?.msg ?? res?.message ?? res?.data?.msg ?? res?.data?.message ?? "").trim();
+
+  const pickFromObject = (node: any): { fileUrl: string; mediaId: string } => {
+    if (!node || typeof node !== "object" || Array.isArray(node)) return { fileUrl: "", mediaId: "" };
+    const mediaId = String(node.media_id ?? node.mediaId ?? node.MediaId ?? "").trim();
+    const fileUrl = String(node.url ?? node.fileUrl ?? node.mediaUrl ?? node.picUrl ?? "").trim();
+    return { fileUrl, mediaId };
+  };
+
+  let root = res;
+  const rawData = root?.data;
+  if (rawData != null && typeof rawData === "string") {
+    const s = rawData.trim();
+    if (s.startsWith("{") || s.startsWith("[")) {
+      try {
+        root = { ...(root && typeof root === "object" ? root : {}), data: JSON.parse(s) };
+      } catch {
+        return { fileUrl: "", mediaId: s, errMsg };
+      }
+    } else if (s) {
+      return { fileUrl: "", mediaId: s, errMsg };
+    }
+  }
+
+  const candidates: any[] = [];
+  const push = (x: any) => {
+    if (x != null) candidates.push(x);
+  };
+  push(root);
+  push(root?.data);
+  if (root?.data != null && typeof root.data === "object" && !Array.isArray(root.data)) {
+    push(root.data.data);
+    for (const v of Object.values(root.data)) {
+      if (v && typeof v === "object" && !Array.isArray(v)) push(v);
+    }
+  }
+
+  let fileUrl = "";
+  let mediaId = "";
+  for (const c of candidates) {
+    if (typeof c === "string" && c.trim()) {
+      mediaId = c.trim();
+      break;
+    }
+    if (!c || typeof c !== "object") continue;
+    const p = pickFromObject(c);
+    if (p.mediaId) {
+      mediaId = p.mediaId;
+      fileUrl = p.fileUrl || fileUrl;
+      break;
+    }
+    for (const v of Object.values(c)) {
+      if (v && typeof v === "object" && !Array.isArray(v)) {
+        const p2 = pickFromObject(v);
+        if (p2.mediaId) {
+          mediaId = p2.mediaId;
+          fileUrl = p2.fileUrl || fileUrl;
+          break;
+        }
+      }
+    }
+    if (mediaId) break;
+  }
+
+  return { fileUrl, mediaId, errMsg };
+}
+
+async function handleMultiUpload(options: UploadRequestOptions, kind: UploadKind) {
+  const uploadFileItem = options.file as UploadUserFile;
+  const raw = uploadFileItem.raw || uploadFileItem;
+  const file = raw instanceof File ? raw : null;
+  if (!file) return;
+
+  uploadFileItem.status = "uploading";
+  try {
+    const fd = new FormData();
+    fd.append("file", file);
+    const res: any = await getUpload(fd);
+    const { fileUrl, mediaId, errMsg } = extractMediaUploadMeta(res);
+    if (mediaId) {
+      uploadFileItem.status = "success";
+      if (fileUrl) uploadFileItem.url = fileUrl;
+      uploadFileItem.response = { media_id: mediaId, url: fileUrl };
+      const uid = (uploadFileItem as UploadUserFile & { uid?: number }).uid;
+      if (uid != null) wechatMediaIdByFileUid.set(uid, mediaId);
+      (uploadFileItem as UploadUserFile & { __wxMediaId?: string }).__wxMediaId = mediaId;
+    } else {
+      uploadFileItem.status = "fail";
+      ElMessage.error(errMsg || "上传失败,未返回 media_id");
+    }
+  } catch {
+    uploadFileItem.status = "fail";
+  }
+  syncUrlsFromFileList(kind);
+  validateKind(kind);
+}
+
+function syncUrlsFromFileList(kind: UploadKind) {
+  const key = urlListKey(kind);
+  let list: UploadUserFile[] = [];
+  if (kind === "storefront") list = form.offlineStorefrontFileList;
+  else if (kind === "interior") list = form.offlineInteriorFileList;
+  else if (kind === "miniShot") list = form.miniProgramShotFileList;
+  else list = form.appShotFileList;
+
+  form[key] = list
+    .map(f => {
+      const fu = f as UploadUserFile & { url?: string; response?: { url?: string } };
+      const mid = getMediaIdFromUploadFile(f);
+      const url = String(fu.url ?? fu.response?.url ?? "").trim();
+      return mid || url;
+    })
+    .filter(Boolean) as string[];
+}
+
+function onMultiRemove(file: UploadUserFile, _fileList: UploadUserFile[], kind: UploadKind) {
+  const uid = (file as UploadUserFile & { uid?: number }).uid;
+  if (uid != null) wechatMediaIdByFileUid.delete(uid);
+  delete (file as UploadUserFile & { __wxMediaId?: string }).__wxMediaId;
+  syncUrlsFromFileList(kind);
+  validateKind(kind);
+}
+
+function syncAllUploadUrlArrays() {
+  syncUrlsFromFileList("storefront");
+  syncUrlsFromFileList("interior");
+  syncUrlsFromFileList("miniShot");
+  syncUrlsFromFileList("appShot");
+}
+
+function assertActiveScenarioPicsHaveMediaId(): boolean {
+  const groups: { label: string; list: UploadUserFile[] }[] = [];
+  if (form.scenarios.offline) {
+    groups.push({ label: "门头照片", list: form.offlineStorefrontFileList });
+    groups.push({ label: "内部照片", list: form.offlineInteriorFileList });
+  }
+  if (form.scenarios.miniProgram) {
+    groups.push({ label: "小程序截图", list: form.miniProgramShotFileList });
+  }
+  if (form.scenarios.app) {
+    groups.push({ label: "APP 截图", list: form.appShotFileList });
+  }
+  for (const g of groups) {
+    for (const f of g.list) {
+      if (f.status !== "success") continue;
+      if (!getMediaIdFromUploadFile(f)) {
+        ElMessage.warning(`「${g.label}」须使用微信素材上传接口返回的 media_id,请删除后重新上传`);
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+function validateKind(kind: UploadKind) {
+  const map: Partial<Record<UploadKind, string>> = {
+    storefront: "offlineStorefrontUrls",
+    interior: "offlineInteriorUrls",
+    appShot: "appShotUrls"
+  };
+  const f = map[kind];
+  if (f) formRef.value?.validateField(f).catch(() => {});
+}
+
+function openScenarioGuide() {
+  ElMessage.info("经营场景填写指引(可对接文档)");
+}
+function openStorefrontGuide() {
+  ElMessage.info("门头照片拍摄指引");
+}
+function openAppidGuide() {
+  ElMessage.info("公众号 APPID 查找说明");
+}
+function openMiniAppidGuide() {
+  ElMessage.info("小程序 APPID 说明");
+}
+function openProviderAppGuide() {
+  ElMessage.info("服务商应用说明");
+}
+function openMerchantAppGuide() {
+  ElMessage.info("商家应用说明");
+}
+function openAppShotExample() {
+  ElMessage.info("APP 截图示例");
+}
+
+function onBack() {
+  router.push({ path: "/businessInfo/dataEntry", query: { ...route.query } });
+}
+
+function onSaveDraft() {
+  ElMessage.success("草稿已保存(可对接接口)");
+}
+
+async function onSubmit() {
+  if (!formRef.value) return;
+  submitLoading.value = true;
+  try {
+    await formRef.value.validate();
+    syncAllUploadUrlArrays();
+    if (!assertActiveScenarioPicsHaveMediaId()) return;
+    mergeManageInfoIntoBusinessDataCache();
+    await router.push({
+      path: "/businessInfo/industryQualifications",
+      query: { ...route.query }
+    });
+  } catch {
+    ElMessage.warning("请完善必填信息");
+  } finally {
+    submitLoading.value = false;
+  }
+}
+</script>
+
+<style scoped lang="scss">
+$wechat-green: #07c160;
+.manage-info-page {
+  box-sizing: border-box;
+  min-height: 100%;
+  padding: 24px 32px 40px;
+  margin: 0 auto;
+  background: #ffffff;
+}
+.page-title {
+  margin: 0 0 24px;
+  font-size: 20px;
+  font-weight: 600;
+  color: #303133;
+}
+.manage-form {
+  :deep(.el-form-item__label) {
+    font-weight: 500;
+    color: #606266;
+  }
+}
+.form-block {
+  padding-bottom: 16px;
+  margin-bottom: 28px;
+  border-bottom: 1px solid #ebeef5;
+  &:last-of-type {
+    border-bottom: none;
+  }
+}
+.sub-section {
+  padding: 8px 16px 20px;
+  margin-top: 8px;
+  background: #fafafa;
+  border: 1px solid #ebeef5;
+  border-radius: 8px;
+}
+.section-head {
+  display: flex;
+  align-items: center;
+  margin: 16px 0 20px;
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+}
+.section-bar {
+  display: inline-block;
+  flex-shrink: 0;
+  width: 4px;
+  height: 16px;
+  margin-right: 8px;
+  background: $wechat-green;
+  border-radius: 2px;
+}
+.section-intro {
+  padding-left: 20px;
+  font-size: 12px;
+  color: #999999;
+}
+.field-stack {
+  width: 100%;
+}
+.field-tip {
+  margin: 8px 0 0;
+  font-size: 12px;
+  line-height: 1.65;
+  color: #909399;
+}
+.scenario-checks {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px 20px;
+  margin-bottom: 8px;
+}
+.label-with-icon {
+  display: inline-flex;
+  gap: 4px;
+  align-items: center;
+}
+.info-icon {
+  color: #909399;
+  cursor: help;
+}
+:deep(.el-upload--picture-card) {
+  --el-upload-picture-card-size: 120px;
+}
+:deep(.el-upload-list--picture-card .el-upload-list__item) {
+  width: 120px;
+  height: 120px;
+}
+.footer-actions {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding-top: 24px;
+  margin-top: 16px;
+  border-top: 1px solid #ebeef5;
+}
+.footer-center {
+  display: flex;
+  flex: 1;
+  justify-content: center;
+}
+.btn-next {
+  min-width: 100px;
+  background: $wechat-green;
+  border-color: $wechat-green;
+  &:hover {
+    background: #06ad56;
+    border-color: #06ad56;
+  }
+}
+</style>

+ 1149 - 0
src/views/businessInfo/subjectInfo.vue

@@ -0,0 +1,1149 @@
+<template>
+  <div class="subject-info-page">
+    <h1 class="page-title">主体信息</h1>
+
+    <el-form
+      ref="formRef"
+      class="subject-form"
+      :model="form"
+      :rules="rules"
+      label-width="140px"
+      require-asterisk-position="right"
+      label-position="right"
+    >
+      <!-- 主体身份 -->
+      <section class="form-block">
+        <h2 class="section-head">
+          <span class="section-bar" aria-hidden="true" />
+          主体身份 <span class="section-intro">请上传「营业执照」,需年检章齐全,当年注册除外</span>
+        </h2>
+
+        <!-- <el-form-item label="是否金融机构" prop="isFinancialInstitution">
+          <div class="field-stack">
+            <el-select v-model="form.isFinancialInstitution" placeholder="请选择" style="width: 260px">
+              <el-option label="否" :value="0" />
+              <el-option label="是" :value="1" />
+            </el-select>
+            <p class="field-tip">
+              金融机构是指从事金融类业务的机构,如信贷、融资、理财、担保、信托、货币兑换等。
+            </p>
+          </div>
+        </el-form-item> -->
+
+        <el-form-item prop="businessLicenseUrl">
+          <template #label>
+            <span class="label-with-icon">
+              营业执照照片
+              <el-tooltip placement="top" content="请上传清晰、完整的营业执照照片,需与后续填写信息一致。">
+                <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+              </el-tooltip>
+            </span>
+          </template>
+          <div class="license-upload-wrap">
+            <el-upload
+              v-model:file-list="form.businessLicenseFileList"
+              list-type="picture-card"
+              :limit="1"
+              accept=".jpg,.jpeg,.png,.bmp,image/jpeg,image/png,image/bmp"
+              :before-upload="beforeLicenseUpload"
+              :http-request="handleLicenseUpload"
+              :on-remove="onLicenseRemove"
+            >
+              <el-icon><Plus /></el-icon>
+            </el-upload>
+            <!-- <div class="license-example" aria-hidden="true" style="border:1px solid red;">
+              <div class="license-example-thumb">
+                <span class="license-example-placeholder">营业执照</span>
+              </div>
+            </div> -->
+          </div>
+          <div class="upload-rules">
+            <p>
+              1.
+              请上传彩色照片或彩色扫描件或加盖公章鲜章的复印件,要求正面拍摄,露出证件四角且清晰、完整,所有字符清晰可识别,不得反光或遮挡。不得翻拍、截图、镜像、PS。
+            </p>
+            <p>2. 图片只支持 JPG、BMP、PNG 格式,文件大小不能超过 5M。</p>
+          </div>
+        </el-form-item>
+        <div v-if="hasBusinessLicenseOcr" class="license-ocr-result">
+          <div v-if="businessLicenseOcr.creditCode" class="license-ocr-row">
+            <span class="license-ocr-label">统一社会信用代码</span>
+            <span class="license-ocr-value">{{ businessLicenseOcr.creditCode }}</span>
+          </div>
+          <div v-if="businessLicenseOcr.companyName" class="license-ocr-row">
+            <span class="license-ocr-label">企业名称</span>
+            <span class="license-ocr-value">{{ businessLicenseOcr.companyName }}</span>
+          </div>
+          <div v-if="businessLicenseOcr.legalPerson" class="license-ocr-row">
+            <span class="license-ocr-label">法定代表人</span>
+            <span class="license-ocr-value">{{ businessLicenseOcr.legalPerson }}</span>
+          </div>
+        </div>
+      </section>
+
+      <!-- 法定代表人证件 -->
+      <section class="form-block">
+        <h2 class="section-head">
+          <span class="section-bar" aria-hidden="true" />
+          法定代表人证件
+          <span class="section-intro">请上传法定代表人的证件信息</span>
+        </h2>
+
+        <el-form-item label="证件类型" prop="legalIdType">
+          <div class="field-stack">
+            <el-select v-model="form.legalIdType" placeholder="请选择" clearable style="width: 260px">
+              <el-option label="居民身份证" value="id_card" />
+              <el-option label="护照" value="passport" />
+              <el-option label="港澳居民来往内地通行证" value="hk_macau_pass" />
+              <el-option label="台湾居民来往大陆通行证" value="taiwan_pass" />
+            </el-select>
+          </div>
+        </el-form-item>
+
+        <!-- 居民身份证:人像面 / 国徽面 -->
+        <template v-if="form.legalIdType === 'id_card'">
+          <el-form-item prop="idPortraitUrl">
+            <template #label>
+              <span class="label-with-icon">
+                身份证人像面照片
+                <el-tooltip placement="top" content="请上传身份证人像面(带头像一面)清晰彩色照片。">
+                  <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+                </el-tooltip>
+              </span>
+            </template>
+            <div class="license-upload-wrap">
+              <el-upload
+                v-model:file-list="form.idPortraitFileList"
+                list-type="picture-card"
+                :limit="1"
+                accept=".jpg,.jpeg,.png,.bmp,image/jpeg,image/png,image/bmp"
+                :before-upload="beforeLicenseUpload"
+                :http-request="opt => handleIdCardUpload(opt, 'portrait')"
+                :on-remove="(_f, fl) => onIdCardRemove(fl, 'portrait')"
+              >
+                <el-icon><Plus /></el-icon>
+              </el-upload>
+              <!-- <div class="license-example" aria-hidden="true">
+                <div class="license-example-thumb id-example-thumb">
+                  <span class="license-example-badge">示例</span>
+                  <span class="license-example-placeholder">人像面</span>
+                </div>
+              </div> -->
+            </div>
+            <div class="upload-rules">
+              <p>
+                1. 请上传彩色照片 or 彩色扫描件 or
+                加盖公章鲜章的复印件,要求正面拍摄,露出证件四角且清晰、完整,所有字符清晰可识别,不得反光或遮挡。不得翻拍、截图、镜像、PS。
+              </p>
+              <p>2. 图片只支持 JPG、BMP、PNG 格式,文件大小不能超过 5M。</p>
+            </div>
+          </el-form-item>
+
+          <el-form-item prop="idEmblemUrl">
+            <template #label>
+              <span class="label-with-icon">
+                身份证国徽面照片
+                <el-tooltip placement="top" content="请上传身份证国徽面清晰彩色照片。">
+                  <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+                </el-tooltip>
+              </span>
+            </template>
+            <div class="license-upload-wrap">
+              <el-upload
+                v-model:file-list="form.idEmblemFileList"
+                list-type="picture-card"
+                :limit="1"
+                accept=".jpg,.jpeg,.png,.bmp,image/jpeg,image/png,image/bmp"
+                :before-upload="beforeLicenseUpload"
+                :http-request="opt => handleIdCardUpload(opt, 'emblem')"
+                :on-remove="(_f, fl) => onIdCardRemove(fl, 'emblem')"
+              >
+                <el-icon><Plus /></el-icon>
+              </el-upload>
+              <!-- <div class="license-example" aria-hidden="true">
+                <div class="license-example-thumb id-example-thumb">
+                  <span class="license-example-badge">示例</span>
+                  <span class="license-example-placeholder">国徽面</span>
+                </div>
+              </div> -->
+            </div>
+            <div class="upload-rules">
+              <p>
+                1. 请上传彩色照片 or 彩色扫描件 or
+                加盖公章鲜章的复印件,要求正面拍摄,露出证件四角且清晰、完整,所有字符清晰可识别,不得反光或遮挡。不得翻拍、截图、镜像、PS。
+              </p>
+              <p>2. 图片只支持 JPG、BMP、PNG 格式,文件大小不能超过 5M。</p>
+            </div>
+
+            <div v-if="showIdPortraitOcrBlock" class="ocr-result-container">
+              <div v-if="isIdPortraitOcrProcessing" class="ocr-result-item">
+                <span class="label">识别中:</span>
+                <span class="value">正在识别身份证信息,请稍候...</span>
+              </div>
+              <template v-else>
+                <div v-if="idPortraitOcr.name" class="ocr-result-item">
+                  <span class="label">姓名:</span>
+                  <span class="value">{{ idPortraitOcr.name }}</span>
+                </div>
+                <div v-if="idPortraitOcr.idNumber" class="ocr-result-item">
+                  <span class="label">身份证号:</span>
+                  <span class="value">{{ idPortraitOcr.idNumber }}</span>
+                </div>
+                <div v-if="idCardValidityDisplay" class="ocr-result-item">
+                  <span class="label">身份证有效期:</span>
+                  <span class="value">{{ idCardValidityDisplay }}</span>
+                </div>
+                <div v-if="!idPortraitOcr.name && !idPortraitOcr.idNumber && !idCardValidityDisplay" class="ocr-result-tip">
+                  请等待身份证识别完成
+                </div>
+              </template>
+            </div>
+          </el-form-item>
+
+          <p class="ubo-footer-tip">
+            平台将通过外部渠道核验该法人是否为受益人,若通过,将使用法人信息作为该主体的受益人(UBO)信息
+          </p>
+        </template>
+      </section>
+    </el-form>
+
+    <div class="footer-actions">
+      <el-button @click="onBack"> 返回 </el-button>
+      <el-button type="primary" class="btn-next" :loading="nextLoading" @click="onNext"> 确定 </el-button>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed, nextTick, onMounted, reactive, ref, watch } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
+import type { FormInstance, FormRules } from "element-plus";
+import type { UploadRequestOptions, UploadUserFile } from "element-plus";
+import { Plus, InfoFilled } from "@element-plus/icons-vue";
+import { getOcrRequestByBase64, getUpload } from "@/api/modules/businessInfo";
+import { localGet, localSet } from "@/utils/index";
+
+const BUSINESS_DATA_CACHE_KEY = "businessData";
+
+const formRef = ref<FormInstance>();
+const nextLoading = ref(false);
+const route = useRoute();
+const router = useRouter();
+
+const businessLicenseOcr = reactive({
+  creditCode: "",
+  companyName: "",
+  legalPerson: ""
+});
+
+const hasBusinessLicenseOcr = computed(
+  () => !!(businessLicenseOcr.creditCode || businessLicenseOcr.companyName || businessLicenseOcr.legalPerson)
+);
+
+function clearBusinessLicenseOcr() {
+  businessLicenseOcr.creditCode = "";
+  businessLicenseOcr.companyName = "";
+  businessLicenseOcr.legalPerson = "";
+}
+
+/** 从 ocrRequestByBase64 成功响应中取出 creditCode / companyName / legalPerson */
+function pickBusinessLicenseOcrFields(res: any) {
+  const raw = res?.data ?? res;
+  let node: any = raw;
+  if (node && typeof node === "object" && "data" in node && node.data !== undefined) {
+    node = node.data;
+  }
+  const item = Array.isArray(node) ? node[0] : node;
+  if (!item || typeof item !== "object") {
+    return { creditCode: "", companyName: "", legalPerson: "" };
+  }
+  return {
+    creditCode: String(item.creditCode ?? item.credit_code ?? "").trim(),
+    companyName: String(item.companyName ?? item.company_name ?? "").trim(),
+    legalPerson: String(item.legalPerson ?? item.legal_person ?? "").trim()
+  };
+}
+
+/** 身份证有效期文案 → YYYY-MM-DD */
+function splitIdCardValidPeriod(raw: string): { begin: string; end: string } {
+  const s = (raw || "").trim();
+  if (!s) return { begin: "", end: "" };
+  if (/长期|长期有效/.test(s)) return { begin: "", end: "长期" };
+  const norm = s
+    .replace(/年|月|日/g, ".")
+    .replace(/\.+/g, ".")
+    .trim();
+  const parts = norm.split(/[-至~~]/);
+  const normOne = (p: string) => {
+    const m = p.trim().match(/(\d{4})\D*(\d{1,2})\D*(\d{1,2})/);
+    if (m) return `${m[1]}-${m[2].padStart(2, "0")}-${m[3].padStart(2, "0")}`;
+    return p.trim();
+  };
+  if (parts.length >= 2) {
+    return { begin: normOne(parts[0]), end: normOne(parts[1]) };
+  }
+  return { begin: "", end: "" };
+}
+
+/** 人像面 getOcrRequestByBase64(ID_CARD) 成功响应 */
+function pickIdCardPortraitOcrFields(res: any): {
+  name: string;
+  idNumber: string;
+  idCardAddress: string;
+  cardPeriodBegin: string;
+  cardPeriodEnd: string;
+} {
+  const raw = res?.data ?? res;
+  let node: any = raw;
+  if (node && typeof node === "object" && "data" in node && node.data !== undefined) {
+    node = node.data;
+  }
+  const arr = Array.isArray(node) ? node : [node];
+  const item = arr[0];
+  const item2 = arr[1];
+  if (!item || typeof item !== "object") {
+    return { name: "", idNumber: "", idCardAddress: "", cardPeriodBegin: "", cardPeriodEnd: "" };
+  }
+  let name = String(item.name ?? item.userName ?? "").trim();
+  let idNumber = String(item.idNumber ?? item.id_number ?? item.idCard ?? item.id_card ?? "").trim();
+  const faceData = item.face?.data || item2?.face?.data;
+  const backData = item.back?.data || item2?.back?.data;
+  if (faceData && typeof faceData === "object") {
+    if (!name) name = String(faceData.name ?? "").trim();
+    if (!idNumber) idNumber = String(faceData.idNumber ?? faceData.id_number ?? "").trim();
+  }
+  let idCardAddress = "";
+  if (backData && typeof backData === "object") {
+    idCardAddress = String(backData.address ?? backData.registeredAddress ?? backData.issueAuthority ?? "").trim();
+  }
+  if (faceData && typeof faceData === "object" && !idCardAddress) {
+    idCardAddress = String(faceData.address ?? "").trim();
+  }
+  const faceKv = item.face?.prism_keyValueInfo || item2?.face?.prism_keyValueInfo;
+  if (Array.isArray(faceKv)) {
+    for (const row of faceKv) {
+      if (row?.key === "name" && row?.value && !name) name = String(row.value).trim();
+      if (row?.key === "idNumber" && row?.value && !idNumber) idNumber = String(row.value).trim();
+      if (row?.key === "address" && row?.value && !idCardAddress) {
+        idCardAddress = String(row.value).trim();
+      }
+    }
+  }
+  const backKv = item.back?.prism_keyValueInfo || item2?.back?.prism_keyValueInfo;
+  let validPeriodFromKv = "";
+  if (Array.isArray(backKv)) {
+    for (const row of backKv) {
+      if (row?.key === "address" && row?.value && !idCardAddress) {
+        idCardAddress = String(row.value).trim();
+      }
+      if (row?.value) {
+        const keyRaw = String(row.key || "");
+        if (/有效期限|有效期|失效日期|签发日期|validPeriod|validDate|valid_period/i.test(keyRaw)) {
+          const v = String(row.value).trim();
+          if (v && !validPeriodFromKv) validPeriodFromKv = v;
+        }
+      }
+    }
+  }
+  let vp = String(
+    (backData && (backData.validPeriod ?? backData.validDate)) ||
+      (faceData && (faceData.validPeriod ?? faceData.validDate)) ||
+      (item && (item.validPeriod ?? item.validDate)) ||
+      (item2 && (item2.validPeriod ?? item2.validDate)) ||
+      ""
+  ).trim();
+  if (!vp && validPeriodFromKv) vp = validPeriodFromKv;
+  const { begin: cardPeriodBegin, end: cardPeriodEnd } = splitIdCardValidPeriod(vp);
+  return { name, idNumber, idCardAddress, cardPeriodBegin, cardPeriodEnd };
+}
+
+const form = reactive<{
+  isFinancialInstitution: number;
+  businessLicenseFileList: UploadUserFile[];
+  businessLicenseUrl: string;
+  legalIdType: string;
+  idPortraitFileList: UploadUserFile[];
+  idEmblemFileList: UploadUserFile[];
+  idPortraitUrl: string;
+  idEmblemUrl: string;
+}>({
+  isFinancialInstitution: 0,
+  businessLicenseFileList: [],
+  businessLicenseUrl: "",
+  legalIdType: "id_card",
+  idPortraitFileList: [],
+  idEmblemFileList: [],
+  idPortraitUrl: "",
+  idEmblemUrl: ""
+});
+
+const idPortraitOcr = reactive({
+  name: "",
+  idNumber: "",
+  idCardAddress: "",
+  cardPeriodBegin: "",
+  cardPeriodEnd: ""
+});
+
+const isIdPortraitOcrProcessing = ref(false);
+
+const hasPortraitUploadSuccess = computed(() => {
+  const f = form.idPortraitFileList[0];
+  return f?.status === "success";
+});
+
+const hasEmblemUploadSuccess = computed(() => {
+  const f = form.idEmblemFileList[0];
+  return f?.status === "success";
+});
+
+/** 身份证有效期展示(国徽面 OCR 主要提供) */
+const idCardValidityDisplay = computed(() => {
+  const b = (idPortraitOcr.cardPeriodBegin || "").trim();
+  const e = (idPortraitOcr.cardPeriodEnd || "").trim();
+  if (b && e) return e === "长期" ? `${b} 至 长期` : `${b} 至 ${e}`;
+  if (e === "长期" && !b) return "长期";
+  if (b && !e) return b;
+  if (!b && e) return e;
+  return "";
+});
+
+const hasIdPortraitOcrDisplay = computed(() => !!(idPortraitOcr.name || idPortraitOcr.idNumber || idCardValidityDisplay.value));
+
+const showIdPortraitOcrBlock = computed(
+  () =>
+    form.legalIdType === "id_card" &&
+    (hasPortraitUploadSuccess.value ||
+      hasEmblemUploadSuccess.value ||
+      isIdPortraitOcrProcessing.value ||
+      hasIdPortraitOcrDisplay.value)
+);
+
+function clearIdPortraitOcr() {
+  idPortraitOcr.name = "";
+  idPortraitOcr.idNumber = "";
+  idPortraitOcr.idCardAddress = "";
+  idPortraitOcr.cardPeriodBegin = "";
+  idPortraitOcr.cardPeriodEnd = "";
+}
+
+function buildSubjectInfoForBusinessData(): {
+  contact_type: "LEGAL";
+  subject_type: "SUBJECT_TYPE_ENTERPRISE" | "SUBJECT_TYPE_INDIVIDUAL";
+  business_license_info: {
+    license_copy: string;
+    license_number: string;
+    merchant_name: string;
+    legal_person: string;
+  };
+  identity_info: {
+    id_doc_type: string;
+    id_holder_type: "LEGAL";
+    id_card_info: {
+      id_card_copy: string;
+      id_card_national: string;
+      id_card_name: string;
+      id_card_number: string;
+      id_card_address: string;
+      card_period_begin: string;
+      card_period_end: string;
+    };
+  };
+} {
+  const cached = localGet(BUSINESS_DATA_CACHE_KEY) as { entityType?: string } | null | undefined;
+  const entityType = String(
+    (cached && typeof cached === "object" && cached.entityType) ||
+      (typeof route.query.entityType === "string" ? route.query.entityType : "") ||
+      ""
+  ).trim();
+  /** 企业 → SUBJECT_TYPE_ENTERPRISE;个体工商户(entityType=individual)及其他默认 → SUBJECT_TYPE_INDIVIDUAL */
+  const subject_type = entityType === "enterprise" ? ("SUBJECT_TYPE_ENTERPRISE" as const) : ("SUBJECT_TYPE_INDIVIDUAL" as const);
+
+  return {
+    contact_type: "LEGAL" as const,
+    subject_type,
+    business_license_info: {
+      license_copy: (form.businessLicenseUrl || "").trim(),
+      license_number: (businessLicenseOcr.creditCode || "").trim(),
+      merchant_name: (businessLicenseOcr.companyName || "").trim(),
+      legal_person: (businessLicenseOcr.legalPerson || "").trim()
+    },
+    identity_info: {
+      id_doc_type: "IDENTIFICATION_TYPE_IDCARD",
+      id_holder_type: "LEGAL" as const,
+      id_card_info: {
+        id_card_copy: (form.idPortraitUrl || "").trim(),
+        id_card_national: (form.idEmblemUrl || "").trim(),
+        id_card_name: (idPortraitOcr.name || "").trim(),
+        id_card_number: (idPortraitOcr.idNumber || "").trim(),
+        id_card_address: (idPortraitOcr.idCardAddress || "").trim(),
+        card_period_begin: (idPortraitOcr.cardPeriodBegin || "").trim(),
+        card_period_end: (idPortraitOcr.cardPeriodEnd || "").trim()
+      }
+    }
+  };
+}
+
+function mergeSubjectInfoIntoBusinessDataCache() {
+  const prev = localGet(BUSINESS_DATA_CACHE_KEY);
+  const base = prev && typeof prev === "object" && !Array.isArray(prev) ? { ...(prev as Record<string, unknown>) } : {};
+  base.subject_info = buildSubjectInfoForBusinessData();
+  localSet(BUSINESS_DATA_CACHE_KEY, base);
+}
+
+function mapApiIdDocTypeToLegalId(apiType: unknown): string {
+  const s = String(apiType || "").trim();
+  switch (s) {
+    case "IDENTIFICATION_TYPE_IDCARD":
+      return "id_card";
+    case "IDENTIFICATION_TYPE_OVERSEA_PASSPORT":
+      return "passport";
+    case "IDENTIFICATION_TYPE_HONGKONG_PASSPORT":
+    case "IDENTIFICATION_TYPE_MACAO_PASSPORT":
+      return "hk_macau_pass";
+    case "IDENTIFICATION_TYPE_TAIWAN_PASSPORT":
+      return "taiwan_pass";
+    default:
+      if (/IDCARD|ID_CARD/i.test(s)) return "id_card";
+      return "id_card";
+  }
+}
+
+/** 从 localStorage businessData.subject_info 回显本页表单与 OCR 展示 */
+function hydrateSubjectFormFromBusinessDataCache() {
+  const raw = localGet(BUSINESS_DATA_CACHE_KEY) as Record<string, unknown> | null | undefined;
+  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
+  const si = raw.subject_info as Record<string, unknown> | undefined;
+  if (!si || typeof si !== "object" || Array.isArray(si)) return;
+
+  const bli = si.business_license_info as Record<string, unknown> | undefined;
+  if (bli && typeof bli === "object" && !Array.isArray(bli)) {
+    const lic = String(bli.license_copy ?? "").trim();
+    if (lic) {
+      form.businessLicenseUrl = lic;
+      form.businessLicenseFileList = [{ name: "license.jpg", url: lic, status: "success" } as UploadUserFile];
+    } else {
+      form.businessLicenseUrl = "";
+      form.businessLicenseFileList = [];
+    }
+    businessLicenseOcr.creditCode = String(bli.license_number ?? "").trim();
+    businessLicenseOcr.companyName = String(bli.merchant_name ?? "").trim();
+    businessLicenseOcr.legalPerson = String(bli.legal_person ?? "").trim();
+  }
+
+  const ii = si.identity_info as Record<string, unknown> | undefined;
+  if (ii && typeof ii === "object" && !Array.isArray(ii)) {
+    if (String(ii.id_doc_type ?? "").trim()) {
+      form.legalIdType = mapApiIdDocTypeToLegalId(ii.id_doc_type);
+    }
+    const ici = ii.id_card_info as Record<string, unknown> | undefined;
+    if (ici && typeof ici === "object" && !Array.isArray(ici)) {
+      const copy = String(ici.id_card_copy ?? "").trim();
+      const nat = String(ici.id_card_national ?? "").trim();
+      if (copy) {
+        form.idPortraitUrl = copy;
+        form.idPortraitFileList = [{ name: "id-portrait.jpg", url: copy, status: "success" } as UploadUserFile];
+      } else {
+        form.idPortraitUrl = "";
+        form.idPortraitFileList = [];
+      }
+      if (nat) {
+        form.idEmblemUrl = nat;
+        form.idEmblemFileList = [{ name: "id-emblem.jpg", url: nat, status: "success" } as UploadUserFile];
+      } else {
+        form.idEmblemUrl = "";
+        form.idEmblemFileList = [];
+      }
+      idPortraitOcr.name = String(ici.id_card_name ?? "").trim();
+      idPortraitOcr.idNumber = String(ici.id_card_number ?? "").trim();
+      idPortraitOcr.idCardAddress = String(ici.id_card_address ?? "").trim();
+      idPortraitOcr.cardPeriodBegin = String(ici.card_period_begin ?? "").trim();
+      idPortraitOcr.cardPeriodEnd = String(ici.card_period_end ?? "").trim();
+    }
+  }
+
+  nextTick(() => {
+    formRef.value?.clearValidate();
+  });
+}
+
+const rules: FormRules = {
+  businessLicenseUrl: [
+    {
+      required: true,
+      validator: (_r, _v, cb) => {
+        if (!form.businessLicenseUrl?.trim()) {
+          cb(new Error("请上传营业执照照片"));
+        } else {
+          cb();
+        }
+      },
+      trigger: "change"
+    }
+  ],
+  legalIdType: [{ required: true, message: "请选择证件类型", trigger: "change" }],
+  idPortraitUrl: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.legalIdType === "id_card" && !form.idPortraitUrl?.trim()) {
+          cb(new Error("请上传身份证人像面照片"));
+        } else {
+          cb();
+        }
+      },
+      trigger: "change"
+    }
+  ],
+  idEmblemUrl: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.legalIdType === "id_card" && !form.idEmblemUrl?.trim()) {
+          cb(new Error("请上传身份证国徽面照片"));
+        } else {
+          cb();
+        }
+      },
+      trigger: "change"
+    }
+  ]
+};
+
+watch(
+  () => form.legalIdType,
+  v => {
+    if (v !== "id_card") {
+      form.idPortraitUrl = "";
+      form.idEmblemUrl = "";
+      form.idPortraitFileList = [];
+      form.idEmblemFileList = [];
+      clearIdPortraitOcr();
+    }
+  }
+);
+
+const MAX_LICENSE_MB = 5;
+
+function beforeLicenseUpload(file: File) {
+  const name = file.name?.toLowerCase() || "";
+  const okExt = /\.(jpe?g|png|bmp)$/i.test(name);
+  const okMime = ["image/jpeg", "image/png", "image/bmp"].includes(file.type);
+  if (!okExt && !okMime) {
+    ElMessage.error("图片只支持 JPG、BMP、PNG 格式");
+    return false;
+  }
+  const sizeMb = file.size / 1024 / 1024;
+  if (sizeMb > MAX_LICENSE_MB) {
+    ElMessage.error(`文件大小不能超过 ${MAX_LICENSE_MB}M`);
+    return false;
+  }
+  return true;
+}
+
+/** 与 getUpload(微信 media/upload)返回结构对齐 */
+function parseMediaUploadResult(res: any): { fileUrl: string; mediaId: string; errMsg: string } {
+  const envelope = res?.data ?? res;
+  const body = envelope?.data !== undefined ? envelope.data : envelope;
+  const fileUrl =
+    body?.url ??
+    body?.fileUrl ??
+    envelope?.url ??
+    envelope?.data?.url ??
+    envelope?.data?.fileUrl ??
+    body?.mediaUrl ??
+    body?.data?.mediaUrl ??
+    "";
+  const mediaId =
+    body?.media_id ?? body?.mediaId ?? envelope?.media_id ?? envelope?.data?.media_id ?? envelope?.data?.mediaId ?? "";
+  const errMsg = envelope?.msg ?? body?.msg ?? res?.msg ?? "";
+  return { fileUrl, mediaId, errMsg };
+}
+
+function mergeIdCardOcrFromFields(fields: ReturnType<typeof pickIdCardPortraitOcrFields>, mode: "portrait" | "emblem") {
+  if (mode === "portrait") {
+    if (fields.name) idPortraitOcr.name = fields.name;
+    if (fields.idNumber) idPortraitOcr.idNumber = fields.idNumber;
+    if (fields.idCardAddress) idPortraitOcr.idCardAddress = fields.idCardAddress;
+    if (fields.cardPeriodBegin) idPortraitOcr.cardPeriodBegin = fields.cardPeriodBegin;
+    if (fields.cardPeriodEnd) idPortraitOcr.cardPeriodEnd = fields.cardPeriodEnd;
+  } else {
+    if (fields.cardPeriodBegin) idPortraitOcr.cardPeriodBegin = fields.cardPeriodBegin;
+    if (fields.cardPeriodEnd) idPortraitOcr.cardPeriodEnd = fields.cardPeriodEnd;
+    if (fields.idCardAddress) idPortraitOcr.idCardAddress = fields.idCardAddress;
+  }
+}
+
+async function requestIdCardPortraitOcr(file: File) {
+  const formData = new FormData();
+  formData.append("imageFile", file, file.name || "id-portrait.jpg");
+  formData.append("ocrType", "ID_CARD");
+  isIdPortraitOcrProcessing.value = true;
+  try {
+    const res: any = await getOcrRequestByBase64(formData);
+    if (res?.code === 200 || res?.code === "200") {
+      const fields = pickIdCardPortraitOcrFields(res);
+      mergeIdCardOcrFromFields(fields, "portrait");
+      ElMessage.success("身份证人像面识别成功");
+    } else {
+      clearIdPortraitOcr();
+      ElMessage.warning(res?.msg || "身份证人像面识别未通过,请核对照片清晰度");
+    }
+  } finally {
+    isIdPortraitOcrProcessing.value = false;
+  }
+}
+
+/** 国徽面单独 OCR,合并有效期限(及背面地址等),不清空人像面已识别字段 */
+async function requestIdCardEmblemOcr(file: File) {
+  const formData = new FormData();
+  formData.append("imageFile", file, file.name || "id-emblem.jpg");
+  formData.append("ocrType", "ID_CARD");
+  isIdPortraitOcrProcessing.value = true;
+  try {
+    const res: any = await getOcrRequestByBase64(formData);
+    if (res?.code === 200 || res?.code === "200") {
+      const fields = pickIdCardPortraitOcrFields(res);
+      mergeIdCardOcrFromFields(fields, "emblem");
+      if (fields.cardPeriodBegin || fields.cardPeriodEnd) {
+        ElMessage.success("身份证国徽面识别成功");
+      } else {
+        ElMessage.warning("未识别到有效期限,请确认国徽面照片清晰完整");
+      }
+    } else {
+      ElMessage.warning(res?.msg || "身份证国徽面识别未通过,请核对照片清晰度");
+    }
+  } finally {
+    isIdPortraitOcrProcessing.value = false;
+  }
+}
+
+async function requestBusinessLicenseOcr(file: File) {
+  const formData = new FormData();
+  formData.append("imageFile", file, file.name || "license.jpg");
+  formData.append("ocrType", "BUSINESS_LICENSE");
+  const res: any = await getOcrRequestByBase64(formData);
+  if (res?.code === 200 || res?.code === "200") {
+    const fields = pickBusinessLicenseOcrFields(res);
+    businessLicenseOcr.creditCode = fields.creditCode;
+    businessLicenseOcr.companyName = fields.companyName;
+    businessLicenseOcr.legalPerson = fields.legalPerson;
+    ElMessage.success("营业执照识别成功");
+  } else {
+    clearBusinessLicenseOcr();
+    ElMessage.warning(res?.msg || "营业执照识别未通过,请核对照片清晰度");
+  }
+}
+
+async function handleLicenseUpload(options: UploadRequestOptions) {
+  const uploadFileItem = options.file as UploadUserFile;
+  const raw = uploadFileItem.raw || uploadFileItem;
+  const file = raw instanceof File ? raw : null;
+  if (!file) return;
+
+  uploadFileItem.status = "uploading";
+  try {
+    const formData = new FormData();
+    formData.append("file", file);
+    const res: any = await getUpload(formData);
+    const { fileUrl, mediaId, errMsg } = parseMediaUploadResult(res);
+
+    if (fileUrl || mediaId) {
+      uploadFileItem.status = "success";
+      if (fileUrl) {
+        uploadFileItem.url = fileUrl;
+      }
+      uploadFileItem.response = { media_id: mediaId, url: fileUrl };
+      form.businessLicenseUrl = fileUrl || mediaId;
+      try {
+        await requestBusinessLicenseOcr(file);
+      } catch {
+        clearBusinessLicenseOcr();
+        ElMessage.warning("营业执照识别服务暂时不可用,请稍后重试");
+      }
+    } else {
+      uploadFileItem.status = "fail";
+      ElMessage.error(errMsg || "上传失败,未返回可用结果");
+    }
+  } catch {
+    uploadFileItem.status = "fail";
+  }
+  formRef.value?.validateField("businessLicenseUrl").catch(() => {});
+}
+
+function onLicenseRemove(_file: UploadUserFile, fileList: UploadUserFile[]) {
+  if (!fileList.length) {
+    form.businessLicenseUrl = "";
+    clearBusinessLicenseOcr();
+  } else {
+    const first = fileList[0] as UploadUserFile & { url?: string; response?: { url?: string } };
+    form.businessLicenseUrl = first?.url || first?.response?.url || "";
+  }
+  formRef.value?.validateField("businessLicenseUrl").catch(() => {});
+}
+
+type IdCardSide = "portrait" | "emblem";
+
+async function handleIdCardUpload(options: UploadRequestOptions, side: IdCardSide) {
+  const uploadFileItem = options.file as UploadUserFile;
+  const raw = uploadFileItem.raw || uploadFileItem;
+  const file = raw instanceof File ? raw : null;
+  if (!file) return;
+
+  uploadFileItem.status = "uploading";
+  try {
+    const formData = new FormData();
+    formData.append("file", file);
+    const res: any = await getUpload(formData);
+    const { fileUrl, mediaId, errMsg } = parseMediaUploadResult(res);
+
+    if (fileUrl || mediaId) {
+      uploadFileItem.status = "success";
+      if (fileUrl) {
+        uploadFileItem.url = fileUrl;
+      }
+      uploadFileItem.response = { media_id: mediaId, url: fileUrl };
+      const stored = fileUrl || mediaId;
+      if (side === "portrait") {
+        form.idPortraitUrl = stored;
+        try {
+          await requestIdCardPortraitOcr(file);
+        } catch {
+          clearIdPortraitOcr();
+          ElMessage.warning("身份证识别服务暂时不可用,请稍后重试");
+        }
+      } else {
+        form.idEmblemUrl = stored;
+        try {
+          await requestIdCardEmblemOcr(file);
+        } catch {
+          ElMessage.warning("身份证国徽面识别服务暂时不可用,请稍后重试");
+        }
+      }
+    } else {
+      uploadFileItem.status = "fail";
+      ElMessage.error(errMsg || "上传失败,未返回可用结果");
+    }
+  } catch {
+    uploadFileItem.status = "fail";
+  }
+  const field = side === "portrait" ? "idPortraitUrl" : "idEmblemUrl";
+  formRef.value?.validateField(field).catch(() => {});
+}
+
+function onIdCardRemove(fileList: UploadUserFile[], side: IdCardSide) {
+  if (!fileList.length) {
+    if (side === "portrait") {
+      form.idPortraitUrl = "";
+      clearIdPortraitOcr();
+    } else {
+      form.idEmblemUrl = "";
+      idPortraitOcr.cardPeriodBegin = "";
+      idPortraitOcr.cardPeriodEnd = "";
+    }
+  } else {
+    const first = fileList[0] as UploadUserFile & {
+      url?: string;
+      response?: { url?: string; media_id?: string; mediaId?: string };
+    };
+    const r = first?.response;
+    const stored = first?.url || r?.url || r?.media_id || r?.mediaId || "";
+    if (side === "portrait") form.idPortraitUrl = stored;
+    else form.idEmblemUrl = stored;
+  }
+  const field = side === "portrait" ? "idPortraitUrl" : "idEmblemUrl";
+  formRef.value?.validateField(field).catch(() => {});
+}
+
+/** 从草稿/详情接口 URL 还原身份证上传展示(可在外部拉取数据后调用) */
+function restoreIdCardFromUrls(portraitUrl?: string | null, emblemUrl?: string | null) {
+  if (portraitUrl) {
+    form.idPortraitUrl = portraitUrl;
+    form.idPortraitFileList = [{ name: "id-portrait.jpg", url: portraitUrl, status: "success" } as UploadUserFile];
+  }
+  if (emblemUrl) {
+    form.idEmblemUrl = emblemUrl;
+    form.idEmblemFileList = [{ name: "id-emblem.jpg", url: emblemUrl, status: "success" } as UploadUserFile];
+  }
+}
+
+onMounted(() => {
+  hydrateSubjectFormFromBusinessDataCache();
+  const q = route.query as Record<string, string | string[] | undefined>;
+  const pu = typeof q.idPortraitUrl === "string" ? q.idPortraitUrl : undefined;
+  const eu = typeof q.idEmblemUrl === "string" ? q.idEmblemUrl : undefined;
+  if (pu && !form.idPortraitUrl?.trim()) {
+    form.legalIdType = "id_card";
+    restoreIdCardFromUrls(pu, undefined);
+  }
+  if (eu && !form.idEmblemUrl?.trim()) {
+    form.legalIdType = "id_card";
+    restoreIdCardFromUrls(undefined, eu);
+  }
+});
+
+defineExpose({ restoreIdCardFromUrls, hydrateSubjectFormFromBusinessDataCache });
+
+function onModifyUbo() {
+  ElMessage.info("受益人信息修改入口可在此对接");
+}
+
+function onBack() {
+  router.push({
+    path: "/businessInfo/dataEntry",
+    query: { ...route.query }
+  });
+}
+
+function onSaveDraft() {
+  ElMessage.success("草稿已保存(可对接接口)");
+}
+
+async function onNext() {
+  if (!formRef.value) return;
+  nextLoading.value = true;
+  try {
+    await formRef.value.validate();
+    mergeSubjectInfoIntoBusinessDataCache();
+    await router.push({
+      path: "/businessInfo/manageInfo",
+      query: { ...route.query }
+    });
+  } catch {
+    ElMessage.warning("请完善必填信息");
+  } finally {
+    nextLoading.value = false;
+  }
+}
+</script>
+
+<style scoped lang="scss">
+$wechat-green: #07c160;
+.subject-info-page {
+  box-sizing: border-box;
+  min-height: 100%;
+  padding: 24px 32px 40px;
+  margin: 0 auto;
+  background: #ffffff;
+}
+.page-title {
+  margin: 0 0 24px;
+  font-size: 20px;
+  font-weight: 600;
+  color: #303133;
+}
+.subject-form {
+  :deep(.el-form-item__label) {
+    font-weight: 500;
+    color: #606266;
+  }
+}
+.form-block {
+  padding-bottom: 8px;
+  margin-bottom: 28px;
+  border-bottom: 1px solid #ebeef5;
+  &:last-of-type {
+    border-bottom: none;
+  }
+}
+.section-head {
+  display: flex;
+  align-items: center;
+  margin: 0 0 16px;
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+}
+.section-bar {
+  display: inline-block;
+  flex-shrink: 0;
+  width: 4px;
+  height: 16px;
+  margin-right: 8px;
+  background: $wechat-green;
+  border-radius: 2px;
+}
+.section-intro {
+  padding-left: 20px;
+  font-size: 13px;
+  line-height: 1.65;
+  color: #909399;
+}
+.field-stack {
+  width: 100%;
+}
+.field-tip {
+  margin: 8px 0 0;
+  font-size: 12px;
+  line-height: 1.65;
+  color: #909399;
+}
+.label-with-icon {
+  display: inline-flex;
+  gap: 4px;
+  align-items: center;
+}
+.info-icon {
+  color: #909399;
+  cursor: help;
+}
+.license-upload-wrap {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 16px;
+  align-items: flex-start;
+}
+.license-example {
+  display: flex;
+  flex-direction: column;
+  gap: 6px;
+}
+.license-example-label {
+  font-size: 12px;
+  color: #909399;
+}
+.license-example-thumb {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 148px;
+  height: 148px;
+  background: #f5f7fa;
+  border: 1px dashed #dcdfe6;
+  border-radius: 6px;
+}
+.license-example-placeholder {
+  font-size: 12px;
+  color: #c0c4cc;
+}
+.id-example-thumb {
+  position: relative;
+}
+.license-example-badge {
+  position: absolute;
+  top: 6px;
+  right: 6px;
+  padding: 2px 6px;
+  font-size: 11px;
+  color: #ffffff;
+  background: rgb(0 0 0 / 45%);
+  border-radius: 4px;
+}
+.ubo-footer-tip {
+  padding: 12px 0 0;
+  margin: 8px 0 0;
+  font-size: 12px;
+  line-height: 1.65;
+  color: #909399;
+  border-top: 1px dashed #ebeef5;
+}
+:deep(.el-form-item__content) {
+  display: block;
+}
+.upload-rules {
+  margin-top: 12px;
+  font-size: 12px;
+  line-height: 1.65;
+  color: #909399;
+  p {
+    margin: 0 0 6px;
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+}
+.ocr-result-container {
+  max-width: 640px;
+  padding: 14px 16px;
+  margin-top: 12px;
+  background: #f5f7fa;
+  border: 1px solid #ebeef5;
+  border-radius: 6px;
+}
+.ocr-result-item {
+  display: flex;
+  gap: 12px;
+  align-items: flex-start;
+  margin-bottom: 10px;
+  font-size: 13px;
+  line-height: 1.5;
+  &:last-child {
+    margin-bottom: 0;
+  }
+  .label {
+    flex-shrink: 0;
+    min-width: 88px;
+    font-weight: 600;
+    color: #606266;
+  }
+  .value {
+    flex: 1;
+    color: #303133;
+    word-break: break-all;
+  }
+}
+.ocr-result-tip {
+  font-size: 13px;
+  line-height: 1.5;
+  color: #909399;
+}
+.license-ocr-result {
+  max-width: 640px;
+  padding: 14px 16px;
+  margin-top: 12px;
+  margin-left: 140px;
+  background: #f5f7fa;
+  border: 1px solid #ebeef5;
+  border-radius: 6px;
+}
+.license-ocr-row {
+  display: flex;
+  gap: 12px;
+  align-items: flex-start;
+  margin-bottom: 10px;
+  font-size: 13px;
+  line-height: 1.5;
+  &:last-child {
+    margin-bottom: 0;
+  }
+}
+.license-ocr-label {
+  flex-shrink: 0;
+  width: 132px;
+  font-weight: 600;
+  color: #606266;
+}
+.license-ocr-value {
+  flex: 1;
+  color: #303133;
+  word-break: break-all;
+}
+:deep(.el-upload--picture-card) {
+  --el-upload-picture-card-size: 148px;
+}
+:deep(.el-upload-list--picture-card .el-upload-list__item) {
+  width: 148px;
+  height: 148px;
+}
+.footer-actions {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding-top: 24px;
+  margin-top: 8px;
+  border-top: 1px solid #ebeef5;
+}
+.footer-center {
+  display: flex;
+  flex: 1;
+  justify-content: center;
+}
+.btn-next {
+  min-width: 100px;
+  background: $wechat-green;
+  border-color: $wechat-green;
+  &:hover {
+    background: #06ad56;
+    border-color: #06ad56;
+  }
+}
+</style>

+ 266 - 0
src/views/businessInfo/weChartExamine.vue

@@ -0,0 +1,266 @@
+<template>
+  <div class="table-box we-chart-examine-page">
+    <h1 class="page-title">查看微信审核</h1>
+
+    <el-alert v-if="loadError" class="mb-16" type="warning" :closable="false" show-icon :title="loadError" />
+
+    <ProTable row-key="_rowKey" :columns="columns" :request-api="getExamineList" :init-param="initParam" :pagination="false">
+      <template #signUrl="scope">
+        <el-link v-if="isHttpUrl(scope.row.signUrl)" :href="scope.row.signUrl" target="_blank" type="primary">
+          {{ scope.row.signUrl }}
+        </el-link>
+        <span v-else>{{ scope.row.signUrl }}</span>
+      </template>
+    </ProTable>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref } from "vue";
+import { useRoute } from "vue-router";
+import ProTable from "@/components/ProTable/index.vue";
+import type { ColumnProps } from "@/components/ProTable/interface";
+import { localGet } from "@/utils/index";
+import { applymentExamine } from "@/api/modules/businessInfo";
+
+const GEEKER_USER_KEY = "geeker-user";
+
+type ExamineDisplayRow = {
+  id: string;
+  applymentNo: string;
+  signUrl: string;
+  applymentState: string;
+  rejectReason: string;
+  _rowKey: string;
+};
+
+const KEY_ID = ["id", "Id", "_id"];
+const KEY_APPLYMENT_NO = ["applyment_id", "applymentId", "out_request_no", "outRequestNo", "business_code", "businessCode"];
+const KEY_SIGN = ["sign_url", "signUrl"];
+const KEY_REJECT = ["reject_reason", "rejectReason"];
+
+/** 微信支付子商户进件申请单状态 → 中文 */
+const APPLYMENT_STATE_LABEL: Record<string, string> = {
+  APPLYMENT_STATE_EDITTING: "编辑中",
+  APPLYMENT_STATE_EDITING: "编辑中",
+  APPLYMENT_STATE_AUDITING: "审核中",
+  APPLYMENT_STATE_REJECTED: "已驳回",
+  APPLYMENT_STATE_TO_BE_CONFIRMED: "待账户验证",
+  APPLYMENT_STATE_TO_BE_SIGNED: "待签约",
+  APPLYMENT_STATE_SIGNING: "开通权限中",
+  APPLYMENT_STATE_FINISHED: "已完成",
+  APPLYMENT_STATE_CANCELED: "已作废"
+};
+
+function formatApplymentStateLabel(raw: string): string {
+  const t = String(raw ?? "").trim();
+  if (!t || t === "—") return "—";
+  const upper = t.toUpperCase().replace(/\s+/g, "_");
+  if (APPLYMENT_STATE_LABEL[upper]) return APPLYMENT_STATE_LABEL[upper];
+  if (APPLYMENT_STATE_LABEL[t]) return APPLYMENT_STATE_LABEL[t];
+  return t;
+}
+
+function pickApplymentStateRaw(row: Record<string, unknown>): string {
+  const codeKeys = ["applyment_state", "applymentState"] as const;
+  for (const k of codeKeys) {
+    if (Object.prototype.hasOwnProperty.call(row, k)) {
+      const v = row[k];
+      if (v !== undefined && v !== null && v !== "") {
+        return String(v).trim();
+      }
+    }
+  }
+  const descKeys = ["applyment_state_desc", "applymentStateDesc"] as const;
+  for (const k of descKeys) {
+    if (Object.prototype.hasOwnProperty.call(row, k)) {
+      const v = row[k];
+      if (v !== undefined && v !== null && v !== "") {
+        return String(v).trim();
+      }
+    }
+  }
+  return "";
+}
+
+function resolveApplymentStoreId(): string | number | null {
+  const geeker = localGet(GEEKER_USER_KEY) as { userInfo?: { storeId?: string | number | null } } | null | undefined;
+  const sid = geeker?.userInfo?.storeId ?? localGet("createdId");
+  if (sid === undefined || sid === null || sid === "") return null;
+  return sid;
+}
+
+const route = useRoute();
+
+function resolveStoreIdParam(): string | number | null {
+  const q = route.query.storeId;
+  if (q !== undefined && q !== null && q !== "") {
+    const s = (Array.isArray(q) ? q[0] : q) as string;
+    if (s) {
+      const n = Number(s);
+      return Number.isNaN(n) ? s : n;
+    }
+  }
+  return resolveApplymentStoreId();
+}
+
+const loadError = ref("");
+
+const initParam = reactive({
+  storeId: localGet(GEEKER_USER_KEY)?.userInfo?.storeId ?? localGet("createdId") ?? ""
+});
+
+const columns: ColumnProps<ExamineDisplayRow>[] = [
+  { prop: "id", label: "ID", width: 100, align: "center" },
+  { prop: "applymentNo", label: "申请单编号", minWidth: 180 },
+  { prop: "signUrl", label: "签约链接", minWidth: 220 },
+  { prop: "applymentState", label: "申请状态", minWidth: 140 },
+  { prop: "rejectReason", label: "驳回原因", minWidth: 200 }
+];
+
+function formatCell(v: unknown): string {
+  if (v === null || v === undefined || v === "") return "—";
+  if (typeof v === "object") {
+    try {
+      return JSON.stringify(v);
+    } catch {
+      return String(v);
+    }
+  }
+  return String(v);
+}
+
+function isHttpUrl(s: string): boolean {
+  if (!s || s === "—") return false;
+  return /^https?:\/\//i.test(s.trim());
+}
+
+function pickField(row: Record<string, unknown>, keys: string[]): string {
+  for (const k of keys) {
+    if (Object.prototype.hasOwnProperty.call(row, k)) {
+      const v = row[k];
+      if (v !== undefined && v !== null && v !== "") {
+        return formatCell(v);
+      }
+    }
+  }
+  return "—";
+}
+
+function normalizeRow(row: Record<string, unknown>): Omit<ExamineDisplayRow, "_rowKey"> {
+  const stateRaw = pickApplymentStateRaw(row);
+  return {
+    id: pickField(row, KEY_ID),
+    applymentNo: pickField(row, KEY_APPLYMENT_NO),
+    signUrl: pickField(row, KEY_SIGN),
+    applymentState: stateRaw ? formatApplymentStateLabel(stateRaw) : "—",
+    rejectReason: pickField(row, KEY_REJECT)
+  };
+}
+
+function unwrapPayload(raw: unknown): unknown {
+  if (raw === null || raw === undefined) return null;
+  if (Array.isArray(raw)) return raw;
+  if (typeof raw !== "object") return raw;
+  const o = raw as Record<string, unknown>;
+  if (Array.isArray(o.list)) return o.list;
+  if (Array.isArray(o.records)) return o.records;
+  if (Array.isArray(o.rows)) return o.rows;
+  if (o.data !== undefined && o.data !== null) {
+    const inner = o.data;
+    if (Array.isArray(inner)) return inner;
+    if (typeof inner === "object" && !Array.isArray(inner)) {
+      const obj = inner as Record<string, unknown>;
+      if (Array.isArray(obj.list)) return obj.list;
+      if (Array.isArray(obj.records)) return obj.records;
+    }
+    return inner;
+  }
+  return raw;
+}
+
+function isPlainObjectRow(x: unknown): x is Record<string, unknown> {
+  return x !== null && typeof x === "object" && !Array.isArray(x);
+}
+
+function buildDisplayRows(payload: unknown): Omit<ExamineDisplayRow, "_rowKey">[] {
+  if (payload === null || payload === undefined) return [];
+
+  if (Array.isArray(payload)) {
+    if (payload.length === 0) return [];
+    if (isPlainObjectRow(payload[0])) {
+      return (payload as Record<string, unknown>[]).map(normalizeRow);
+    }
+    return [
+      {
+        id: "—",
+        applymentNo: "—",
+        signUrl: "—",
+        applymentState: "—",
+        rejectReason: formatCell(payload)
+      }
+    ];
+  }
+
+  if (isPlainObjectRow(payload)) {
+    return [normalizeRow(payload)];
+  }
+
+  return [
+    {
+      id: "—",
+      applymentNo: "—",
+      signUrl: "—",
+      applymentState: "—",
+      rejectReason: formatCell(payload)
+    }
+  ];
+}
+
+function withRowKeys(rows: Omit<ExamineDisplayRow, "_rowKey">[]): ExamineDisplayRow[] {
+  return rows.map((r, i) => ({
+    ...r,
+    _rowKey: `examine-${i}-${r.id}-${r.applymentNo}`.replace(/\s/g, "")
+  }));
+}
+
+/**
+ * 与 tableManagement.vue 中 ProTable 约定一致:返回 { data }。
+ * 无分页时 useTable 将 data 视为列表(见 useTable 无分页分支)。
+ */
+async function getExamineList(_params: any) {
+  const storeId = resolveStoreIdParam();
+  if (storeId === null) {
+    loadError.value = "未获取到门店 storeId,请重新登录或通过路由传入 storeId。";
+    return { data: [] as ExamineDisplayRow[] };
+  }
+
+  loadError.value = "";
+  try {
+    const res = (await applymentExamine(storeId)) as { data?: unknown };
+    const payload = unwrapPayload(res?.data ?? res);
+    const list = withRowKeys(buildDisplayRows(payload));
+    return { data: list };
+  } catch (e: unknown) {
+    const msg = e && typeof e === "object" && "msg" in e ? String((e as { msg?: string }).msg) : "";
+    loadError.value = msg || "获取审核信息失败";
+    return { data: [] as ExamineDisplayRow[] };
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.we-chart-examine-page {
+  padding: 24px 32px 40px;
+  background: #ffffff;
+}
+.page-title {
+  margin: 0 0 20px;
+  font-size: 20px;
+  font-weight: 600;
+  color: #303133;
+}
+.mb-16 {
+  margin-bottom: 16px;
+}
+</style>

+ 15 - 0
src/views/businessInfo/weChartIndex.vue

@@ -0,0 +1,15 @@
+<template>
+  <div class="we-chart-index">
+    <CreateApply />
+  </div>
+</template>
+
+<script setup lang="ts">
+import CreateApply from "./createApply.vue";
+</script>
+
+<style scoped>
+.we-chart-index {
+  min-height: 100%;
+}
+</style>

+ 253 - 0
src/views/businessInfo/zfbExamine.vue

@@ -0,0 +1,253 @@
+<template>
+  <div class="table-box zfb-examine-page">
+    <h1 class="page-title">查看支付宝审核</h1>
+
+    <el-alert v-if="loadError" class="mb-16" type="warning" :closable="false" show-icon :title="loadError" />
+
+    <ProTable row-key="_rowKey" :columns="columns" :request-api="getExamineList" :init-param="initParam" :pagination="false">
+      <template #signUrl="scope">
+        <el-link v-if="isHttpUrl(scope.row.signUrl)" :href="scope.row.signUrl" target="_blank" type="primary">
+          {{ scope.row.signUrl }}
+        </el-link>
+        <span v-else>{{ scope.row.signUrl }}</span>
+      </template>
+    </ProTable>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref } from "vue";
+import ProTable from "@/components/ProTable/index.vue";
+import type { ColumnProps } from "@/components/ProTable/interface";
+import { getAlipayExamine } from "@/api/modules/businessInfo";
+
+/** 与产品约定:查询指定进件订单 */
+const ALIPAY_EXAMINE_ORDER = "2026040700502000000050184000";
+
+type ExamineDisplayRow = {
+  id: string;
+  applymentNo: string;
+  signUrl: string;
+  applymentState: string;
+  rejectReason: string;
+  _rowKey: string;
+};
+
+const KEY_ID = ["id", "Id", "_id"];
+const KEY_APPLYMENT_NO = [
+  "order",
+  "order_id",
+  "orderId",
+  "applyment_id",
+  "applymentId",
+  "out_request_no",
+  "outRequestNo",
+  "business_code",
+  "businessCode"
+];
+const KEY_SIGN = ["sign_url", "signUrl", "signing_url", "signingUrl", "agreement_url", "agreementUrl"];
+const KEY_REJECT = ["reject_reason", "rejectReason", "fail_reason", "failReason", "reason", "sub_msg", "subMsg"];
+
+/** 支付宝 / 直付通常见状态码(接口若返回英文枚举可在此补充) */
+const APPLYMENT_STATE_LABEL: Record<string, string> = {
+  AUDITING: "审核中",
+  AUDIT_PASS: "审核通过",
+  AUDIT_REJECT: "审核驳回",
+  AUDITING_WAIT_FOR_CONFIRM: "待确认",
+  CANCEL: "已撤销",
+  SUCCESS: "成功",
+  FAIL: "失败",
+  PROCESSING: "处理中"
+};
+
+function formatApplymentStateLabel(raw: string): string {
+  const t = String(raw ?? "").trim();
+  if (!t || t === "—") return "—";
+  const upper = t.toUpperCase().replace(/\s+/g, "_");
+  if (APPLYMENT_STATE_LABEL[upper]) return APPLYMENT_STATE_LABEL[upper];
+  if (APPLYMENT_STATE_LABEL[t]) return APPLYMENT_STATE_LABEL[t];
+  return t;
+}
+
+function pickApplymentStateRaw(row: Record<string, unknown>): string {
+  const codeKeys = [
+    "applyment_state",
+    "applymentState",
+    "order_status",
+    "orderStatus",
+    "status",
+    "audit_status",
+    "auditStatus",
+    "state"
+  ] as const;
+  for (const k of codeKeys) {
+    if (Object.prototype.hasOwnProperty.call(row, k)) {
+      const v = row[k];
+      if (v !== undefined && v !== null && v !== "") {
+        return String(v).trim();
+      }
+    }
+  }
+  const descKeys = ["applyment_state_desc", "applymentStateDesc", "status_desc", "statusDesc", "msg", "message"] as const;
+  for (const k of descKeys) {
+    if (Object.prototype.hasOwnProperty.call(row, k)) {
+      const v = row[k];
+      if (v !== undefined && v !== null && v !== "") {
+        return String(v).trim();
+      }
+    }
+  }
+  return "";
+}
+
+const loadError = ref("");
+
+const initParam = reactive({ order: ALIPAY_EXAMINE_ORDER });
+
+const columns: ColumnProps<ExamineDisplayRow>[] = [
+  { prop: "id", label: "ID", width: 100, align: "center" },
+  { prop: "applymentNo", label: "订单号 / 申请单号", minWidth: 200 },
+  { prop: "signUrl", label: "签约链接", minWidth: 220 },
+  { prop: "applymentState", label: "状态", minWidth: 140 },
+  { prop: "rejectReason", label: "驳回 / 失败原因", minWidth: 200 }
+];
+
+function formatCell(v: unknown): string {
+  if (v === null || v === undefined || v === "") return "—";
+  if (typeof v === "object") {
+    try {
+      return JSON.stringify(v);
+    } catch {
+      return String(v);
+    }
+  }
+  return String(v);
+}
+
+function isHttpUrl(s: string): boolean {
+  if (!s || s === "—") return false;
+  return /^https?:\/\//i.test(s.trim());
+}
+
+function pickField(row: Record<string, unknown>, keys: string[]): string {
+  for (const k of keys) {
+    if (Object.prototype.hasOwnProperty.call(row, k)) {
+      const v = row[k];
+      if (v !== undefined && v !== null && v !== "") {
+        return formatCell(v);
+      }
+    }
+  }
+  return "—";
+}
+
+function normalizeRow(row: Record<string, unknown>): Omit<ExamineDisplayRow, "_rowKey"> {
+  const stateRaw = pickApplymentStateRaw(row);
+  return {
+    id: pickField(row, KEY_ID),
+    applymentNo: pickField(row, KEY_APPLYMENT_NO),
+    signUrl: pickField(row, KEY_SIGN),
+    applymentState: stateRaw ? formatApplymentStateLabel(stateRaw) : "—",
+    rejectReason: pickField(row, KEY_REJECT)
+  };
+}
+
+function unwrapPayload(raw: unknown): unknown {
+  if (raw === null || raw === undefined) return null;
+  if (Array.isArray(raw)) return raw;
+  if (typeof raw !== "object") return raw;
+  const o = raw as Record<string, unknown>;
+  if (Array.isArray(o.list)) return o.list;
+  if (Array.isArray(o.records)) return o.records;
+  if (Array.isArray(o.rows)) return o.rows;
+  if (o.data !== undefined && o.data !== null) {
+    const inner = o.data;
+    if (Array.isArray(inner)) return inner;
+    if (typeof inner === "object" && !Array.isArray(inner)) {
+      const obj = inner as Record<string, unknown>;
+      if (Array.isArray(obj.list)) return obj.list;
+      if (Array.isArray(obj.records)) return obj.records;
+    }
+    return inner;
+  }
+  return raw;
+}
+
+function isPlainObjectRow(x: unknown): x is Record<string, unknown> {
+  return x !== null && typeof x === "object" && !Array.isArray(x);
+}
+
+function buildDisplayRows(payload: unknown): Omit<ExamineDisplayRow, "_rowKey">[] {
+  if (payload === null || payload === undefined) return [];
+
+  if (Array.isArray(payload)) {
+    if (payload.length === 0) return [];
+    if (isPlainObjectRow(payload[0])) {
+      return (payload as Record<string, unknown>[]).map(normalizeRow);
+    }
+    return [
+      {
+        id: "—",
+        applymentNo: "—",
+        signUrl: "—",
+        applymentState: "—",
+        rejectReason: formatCell(payload)
+      }
+    ];
+  }
+
+  if (isPlainObjectRow(payload)) {
+    return [normalizeRow(payload)];
+  }
+
+  return [
+    {
+      id: "—",
+      applymentNo: "—",
+      signUrl: "—",
+      applymentState: "—",
+      rejectReason: formatCell(payload)
+    }
+  ];
+}
+
+function withRowKeys(rows: Omit<ExamineDisplayRow, "_rowKey">[]): ExamineDisplayRow[] {
+  return rows.map((r, i) => ({
+    ...r,
+    _rowKey: `zfb-examine-${i}-${r.id}-${r.applymentNo}`.replace(/\s/g, "")
+  }));
+}
+
+/**
+ * 与 ProTable 约定一致:返回 { data }。
+ */
+async function getExamineList(_params: unknown) {
+  loadError.value = "";
+  try {
+    const res = (await getAlipayExamine({ order: ALIPAY_EXAMINE_ORDER })) as { data?: unknown };
+    const payload = unwrapPayload(res?.data ?? res);
+    const list = withRowKeys(buildDisplayRows(payload));
+    return { data: list };
+  } catch (e: unknown) {
+    const msg = e && typeof e === "object" && "msg" in e ? String((e as { msg?: string }).msg) : "";
+    loadError.value = msg || "获取支付宝审核信息失败";
+    return { data: [] as ExamineDisplayRow[] };
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.zfb-examine-page {
+  padding: 24px 32px 40px;
+  background: #ffffff;
+}
+.page-title {
+  margin: 0 0 20px;
+  font-size: 20px;
+  font-weight: 600;
+  color: #303133;
+}
+.mb-16 {
+  margin-bottom: 16px;
+}
+</style>

+ 2458 - 0
src/views/businessInfo/zfbIndex.vue

@@ -0,0 +1,2458 @@
+<template>
+  <div class="zfb-step-page">
+    <header class="step-header">
+      <el-steps :active="zfbStepActive" align-center finish-status="process" class="zfb-steps">
+        <el-step title="第一步 完善商家信息" />
+        <el-step title="第二步 完善结算信息" />
+        <el-step title="第三步 提交审核" />
+      </el-steps>
+    </header>
+
+    <div class="page-layout">
+      <div class="main-column">
+        <el-form
+          ref="formRef"
+          class="zfb-form"
+          :model="form"
+          :rules="rules"
+          label-width="200px"
+          require-asterisk-position="left"
+          label-position="right"
+        >
+          <!-- 主体信息 -->
+          <section id="zfb-subject" class="form-block anchor-section">
+            <h2 class="section-head">
+              <span class="section-bar" aria-hidden="true" />
+              主体信息
+            </h2>
+
+            <el-form-item label="主体类型" prop="subjectType">
+              <el-radio-group v-model="form.subjectType" class="radio-stack" @change="onSubjectTypeChange">
+                <el-radio v-for="opt in subjectTypeOptions" :key="opt.value" :value="opt.value">
+                  {{ opt.label }}
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
+
+            <el-form-item prop="licenseUrl" v-if="form.subjectType === '01'">
+              <template #label>
+                <span class="label-with-icon"> 营业执照 </span>
+              </template>
+              <div class="license-upload-wrap">
+                <el-upload
+                  v-model:file-list="form.licenseFileList"
+                  list-type="picture-card"
+                  :limit="1"
+                  accept=".jpg,.jpeg,.png,.bmp,.gif,image/jpeg,image/png,image/bmp,image/gif"
+                  :before-upload="beforeImageUpload"
+                  :http-request="opt => handleSingleUpload(opt, 'license')"
+                  :on-remove="(_f, fl) => onSingleRemove(fl, 'license')"
+                >
+                  <el-icon><Plus /></el-icon>
+                </el-upload>
+              </div>
+              <div class="upload-rules">
+                <p>只支持.jpg、.png格式。</p>
+              </div>
+            </el-form-item>
+
+            <el-form-item label="营业执照号" prop="creditCode" v-if="form.subjectType === '01'">
+              <el-input
+                v-model="form.creditCode"
+                placeholder="请输入统一社会信用代码"
+                clearable
+                maxlength="32"
+                style="max-width: 480px"
+              />
+            </el-form-item>
+
+            <el-form-item prop="merchantShortName" v-if="form.subjectType === '01'">
+              <template #label>
+                <span class="label-with-icon"> 商户简称 </span>
+              </template>
+              <el-input v-model="form.merchantShortName" placeholder="请输入商户简称" clearable style="max-width: 480px" />
+            </el-form-item>
+            <el-form-item prop="businessCategory" v-if="form.subjectType === '01'">
+              <template #label>
+                <span class="label-with-icon"> 经营类目 </span>
+              </template>
+              <el-cascader
+                v-model="form.businessCategory"
+                :options="categoryCascaderOptions"
+                :props="categoryCascaderProps"
+                placeholder="请选择经营类目"
+                clearable
+                filterable
+                style="width: 480px"
+              />
+            </el-form-item>
+            <!-- 
+            <template v-if="form.subjectType === '02'">
+              <el-form-item prop="institutionCertUrl">
+                <template #label>事业单位法人证书</template>
+                <div class="license-upload-wrap">
+                  <el-upload
+                    v-model:file-list="form.institutionCertFileList"
+                    list-type="picture-card"
+                    :limit="1"
+                    accept=".jpg,.jpeg,.png,image/jpeg,image/png"
+                    :before-upload="beforeImageUploadInstJpgPng"
+                    :http-request="opt => handleSingleUpload(opt, 'institutionCert')"
+                    :on-remove="(_f, fl) => onSingleRemove(fl, 'institutionCert')"
+                  >
+                    <el-icon><Plus /></el-icon>
+                  </el-upload>
+                </div>
+                <div class="upload-rules">
+                  <p>仅支持 jpg、png 格式。</p>
+                </div>
+              </el-form-item>
+
+              <el-form-item label="事业单位法人证书编号" prop="institutionCertNumber">
+                <el-input
+                  v-model="form.institutionCertNumber"
+                  placeholder="请输入证书编号"
+                  clearable
+                  maxlength="64"
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+
+              <el-form-item prop="merchantShortName">
+                <template #label>
+                  <span class="label-with-icon">
+                    商户简称
+                    <el-tooltip placement="top" content="简称将展示给消费者,需与法人证书或品牌一致。">
+                      <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+                    </el-tooltip>
+                  </span>
+                </template>
+                <el-input
+                  v-model="form.merchantShortName"
+                  placeholder="请输入商户简称"
+                  clearable
+                  maxlength="64"
+                  show-word-limit
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+
+              <el-form-item label="经营类目" prop="businessCategory">
+                <el-cascader
+                  v-model="form.businessCategory"
+                  :options="categoryCascaderOptions"
+                  :props="categoryCascaderProps"
+                  placeholder="请选择经营类目"
+                  clearable
+                  filterable
+                  style="width: 480px"
+                />
+              </el-form-item>
+            </template> -->
+
+            <!-- <template v-if="form.subjectType === '03'">
+              <el-form-item prop="otherOrgCertUrl">
+                <template #label>民办非企业单位登记证书</template>
+                <div class="license-upload-wrap">
+                  <el-upload
+                    v-model:file-list="form.otherOrgCertFileList"
+                    list-type="picture-card"
+                    :limit="1"
+                    accept=".jpg,.jpeg,.png,image/jpeg,image/png"
+                    :before-upload="beforeImageUploadInstJpgPng"
+                    :http-request="opt => handleSingleUpload(opt, 'otherOrgCert')"
+                    :on-remove="(_f, fl) => onSingleRemove(fl, 'otherOrgCert')"
+                  >
+                    <el-icon><Plus /></el-icon>
+                  </el-upload>
+                </div>
+                <div class="upload-rules">
+                  <p>只支持 jpg、png 格式。</p>
+                </div>
+              </el-form-item>
+
+              <el-form-item label="民办非企业单位登记证书编号" prop="otherOrgCertNumber">
+                <el-input
+                  v-model="form.otherOrgCertNumber"
+                  placeholder="请输入证书编号"
+                  clearable
+                  maxlength="64"
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+
+              <el-form-item prop="merchantShortName">
+                <template #label>
+                  <span class="label-with-icon">
+                    商户简称
+                    <el-tooltip placement="top" content="简称将展示给消费者,需与登记证书或品牌一致。">
+                      <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+                    </el-tooltip>
+                  </span>
+                </template>
+                <el-input
+                  v-model="form.merchantShortName"
+                  placeholder="请输入商户简称"
+                  clearable
+                  maxlength="64"
+                  show-word-limit
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+
+              <el-form-item label="经营类目" prop="businessCategory">
+                <el-cascader
+                  v-model="form.businessCategory"
+                  :options="categoryCascaderOptions"
+                  :props="categoryCascaderProps"
+                  placeholder="请选择经营类目"
+                  clearable
+                  filterable
+                  style="width: 480px"
+                />
+              </el-form-item>
+            </template> -->
+
+            <!-- <template v-if="form.subjectType === '04'">
+              <el-form-item prop="socialCertUrl">
+                <template #label>社会团体法人登记证书</template>
+                <div class="license-upload-wrap">
+                  <el-upload
+                    v-model:file-list="form.socialCertFileList"
+                    list-type="picture-card"
+                    :limit="1"
+                    accept=".jpg,.jpeg,.png,image/jpeg,image/png"
+                    :before-upload="beforeImageUploadInstJpgPng"
+                    :http-request="opt => handleSingleUpload(opt, 'socialCert')"
+                    :on-remove="(_f, fl) => onSingleRemove(fl, 'socialCert')"
+                  >
+                    <el-icon><Plus /></el-icon>
+                  </el-upload>
+                </div>
+                <div class="upload-rules">
+                  <p>只支持 jpg、png 格式。</p>
+                </div>
+              </el-form-item>
+
+              <el-form-item label="社会团体法人登记证书编号" prop="socialCertNumber">
+                <el-input
+                  v-model="form.socialCertNumber"
+                  placeholder="请输入证书编号"
+                  clearable
+                  maxlength="64"
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+
+              <el-form-item prop="merchantShortName">
+                <template #label>
+                  <span class="label-with-icon">
+                    商户简称
+                    <el-tooltip placement="top" content="简称将展示给消费者,需与法人登记证书或品牌一致。">
+                      <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+                    </el-tooltip>
+                  </span>
+                </template>
+                <el-input
+                  v-model="form.merchantShortName"
+                  placeholder="请输入商户简称"
+                  clearable
+                  maxlength="64"
+                  show-word-limit
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+
+              <el-form-item label="经营类目" prop="businessCategory">
+                <el-cascader
+                  v-model="form.businessCategory"
+                  :options="categoryCascaderOptions"
+                  :props="categoryCascaderProps"
+                  placeholder="请选择经营类目"
+                  clearable
+                  filterable
+                  style="width: 480px"
+                />
+              </el-form-item>
+            </template> -->
+
+            <!-- <template v-if="form.subjectType === '05'">
+              <el-form-item prop="govCertUrl">
+                <template #label>
+                  <span class="label-wrap-multiline">党政机关批准设立文件/行政执法主体资格证</span>
+                </template>
+                <div class="license-upload-wrap">
+                  <el-upload
+                    v-model:file-list="form.govCertFileList"
+                    list-type="picture-card"
+                    :limit="1"
+                    accept=".jpg,.jpeg,.png,image/jpeg,image/png"
+                    :before-upload="beforeImageUploadInstJpgPng"
+                    :http-request="opt => handleSingleUpload(opt, 'govCert')"
+                    :on-remove="(_f, fl) => onSingleRemove(fl, 'govCert')"
+                  >
+                    <el-icon><Plus /></el-icon>
+                  </el-upload>
+                </div>
+                <div class="upload-rules">
+                  <p>只支持 jpg、png 格式。</p>
+                </div>
+              </el-form-item>
+
+              <el-form-item prop="govCertNumber">
+                <template #label>
+                  <span class="label-wrap-multiline">党政机关批准设立文件/行政执法主体资格证编号</span>
+                </template>
+                <el-input
+                  v-model="form.govCertNumber"
+                  placeholder="请输入编号"
+                  clearable
+                  maxlength="128"
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+
+              <el-form-item prop="merchantShortName">
+                <template #label>
+                  <span class="label-with-icon">
+                    商户简称
+                    <el-tooltip placement="top" content="简称将展示给消费者,需与批准文件或主体名称一致。">
+                      <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+                    </el-tooltip>
+                  </span>
+                </template>
+                <el-input
+                  v-model="form.merchantShortName"
+                  placeholder="请输入商户简称"
+                  clearable
+                  maxlength="64"
+                  show-word-limit
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+
+              <el-form-item label="经营类目" prop="businessCategory">
+                <el-cascader
+                  v-model="form.businessCategory"
+                  :options="categoryCascaderOptions"
+                  :props="categoryCascaderProps"
+                  placeholder="请选择经营类目"
+                  clearable
+                  filterable
+                  style="width: 480px"
+                />
+              </el-form-item>
+            </template> -->
+
+            <!-- <template v-if="form.subjectType === '06'">
+              <el-alert
+                class="individual-merchant-alert"
+                type="info"
+                :closable="false"
+                show-icon
+              >
+                使用当面付服务时,选择个人类型会有收款额度限制
+              </el-alert>
+
+              <el-form-item prop="idFrontUrl">
+                <template #label>个人身份证</template>
+                <div class="id-upload-row id-upload-row--four">
+                  <div class="id-upload-cell">
+                    <span class="id-side-label">上传人像面</span>
+                    <el-upload
+                      v-model:file-list="form.idFrontFileList"
+                      list-type="picture-card"
+                      :limit="1"
+                      accept=".jpg,.jpeg,.png,image/jpeg,image/png"
+                      :before-upload="beforeImageUploadInstJpgPng"
+                      :http-request="opt => handleSingleUpload(opt, 'idFront')"
+                      :on-remove="(_f, fl) => onSingleRemove(fl, 'idFront')"
+                    >
+                      <el-icon><Plus /></el-icon>
+                    </el-upload>
+                  </div>
+                  <div class="id-upload-cell">
+                    <span class="id-side-label">上传国徽面</span>
+                    <el-upload
+                      v-model:file-list="form.idBackFileList"
+                      list-type="picture-card"
+                      :limit="1"
+                      accept=".jpg,.jpeg,.png,image/jpeg,image/png"
+                      :before-upload="beforeImageUploadInstJpgPng"
+                      :http-request="opt => handleSingleUpload(opt, 'idBack')"
+                      :on-remove="(_f, fl) => onSingleRemove(fl, 'idBack')"
+                    >
+                      <el-icon><Plus /></el-icon>
+                    </el-upload>
+                  </div>
+                </div>
+                <div class="upload-rules">
+                  <p>
+                    说明:仅支持 jpg、png 格式。如果没有证件原件照片,可以上传证件照片复印件。
+                  </p>
+                </div>
+              </el-form-item>
+
+              <el-form-item label="个人身份证号码" prop="idNumber">
+                <el-input v-model="form.idNumber" placeholder="请输入身份证号码" clearable style="max-width: 480px" />
+              </el-form-item>
+
+              <el-form-item prop="merchantShortName">
+                <template #label>
+                  <span class="label-with-icon">
+                    商户简称
+                    <el-tooltip placement="top" content="简称将展示给消费者,需与身份证或品牌一致。">
+                      <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+                    </el-tooltip>
+                  </span>
+                </template>
+                <el-input
+                  v-model="form.merchantShortName"
+                  placeholder="请输入商户简称"
+                  clearable
+                  maxlength="64"
+                  show-word-limit
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+
+              <el-form-item label="经营类目" prop="businessCategory">
+                <el-cascader
+                  v-model="form.businessCategory"
+                  :options="categoryCascaderOptions"
+                  :props="categoryCascaderProps"
+                  placeholder="请选择经营类目"
+                  clearable
+                  filterable
+                  style="width: 480px"
+                />
+              </el-form-item>
+            </template> -->
+
+            <template v-if="form.subjectType === '07'">
+              <el-form-item prop="licenseUrl">
+                <template #label> 营业执照 </template>
+                <div class="license-upload-wrap">
+                  <el-upload
+                    v-model:file-list="form.licenseFileList"
+                    list-type="picture-card"
+                    :limit="1"
+                    accept=".jpg,.jpeg,.png,image/jpeg,image/png"
+                    :before-upload="beforeImageUploadInstJpgPng"
+                    :http-request="opt => handleSingleUpload(opt, 'license')"
+                    :on-remove="(_f, fl) => onSingleRemove(fl, 'license')"
+                  >
+                    <el-icon><Plus /></el-icon>
+                  </el-upload>
+                </div>
+                <div class="upload-rules">
+                  <p>只支持 jpg、png 格式。</p>
+                </div>
+              </el-form-item>
+
+              <el-form-item label="营业执照编号" prop="creditCode">
+                <el-input
+                  v-model="form.creditCode"
+                  placeholder="请输入营业执照编号"
+                  clearable
+                  maxlength="32"
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+
+              <el-form-item label="营业执照名称" prop="householdLicenseName">
+                <el-input
+                  v-model="form.householdLicenseName"
+                  placeholder="请输入营业执照名称"
+                  clearable
+                  maxlength="128"
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+
+              <el-form-item prop="merchantShortName">
+                <template #label>
+                  <span class="label-with-icon">
+                    商户简称
+                    <el-tooltip placement="top" content="简称将展示给消费者,需与营业执照或品牌一致。">
+                      <el-icon class="info-icon" :size="16"><InfoFilled /></el-icon>
+                    </el-tooltip>
+                  </span>
+                </template>
+                <el-input v-model="form.merchantShortName" placeholder="请输入商户简称" clearable style="max-width: 480px" />
+              </el-form-item>
+
+              <el-form-item label="经营类目" prop="businessCategory">
+                <el-cascader
+                  v-model="form.businessCategory"
+                  :options="categoryCascaderOptions"
+                  :props="categoryCascaderProps"
+                  placeholder="请选择经营类目"
+                  clearable
+                  filterable
+                  style="width: 480px"
+                />
+              </el-form-item>
+            </template>
+          </section>
+
+          <!-- 法人信息 -->
+          <section id="zfb-legal" class="form-block anchor-section" v-if="form.subjectType === '01' || form.subjectType === '07'">
+            <h2 class="section-head">
+              <span class="section-bar" aria-hidden="true" />
+              法人信息
+            </h2>
+
+            <el-form-item label="法定代表人/负责人证件类型" prop="legalIdType">
+              <el-select v-model="form.legalIdType" placeholder="请选择" clearable style="width: 260px">
+                <el-option label="居民身份证" value="id_card" />
+                <el-option label="护照" value="passport" />
+                <el-option label="港澳居民来往内地通行证" value="hk_macau_pass" />
+                <el-option label="台湾居民来往大陆通行证" value="taiwan_pass" />
+              </el-select>
+            </el-form-item>
+
+            <el-form-item prop="idFrontUrl">
+              <template #label> 上传证件照片 </template>
+              <div class="id-upload-row">
+                <div class="id-upload-cell">
+                  <div class="license-upload-wrap">
+                    <el-upload
+                      v-model:file-list="form.idFrontFileList"
+                      list-type="picture-card"
+                      :limit="1"
+                      accept=".jpg,.jpeg,.png,.bmp,.gif,image/jpeg,image/png,image/bmp,image/gif"
+                      :before-upload="beforeImageUpload"
+                      :http-request="opt => handleSingleUpload(opt, 'idFront')"
+                      :on-remove="(_f, fl) => onSingleRemove(fl, 'idFront')"
+                    >
+                      <div class="id-upload-trigger">
+                        <el-icon><Plus /></el-icon>
+                        <div class="id-side-label">上传证件正面</div>
+                      </div>
+                    </el-upload>
+                  </div>
+                </div>
+                <div class="id-upload-cell">
+                  <div class="license-upload-wrap">
+                    <el-upload
+                      v-model:file-list="form.idBackFileList"
+                      list-type="picture-card"
+                      :limit="1"
+                      accept=".jpg,.jpeg,.png,.bmp,.gif,image/jpeg,image/png,image/bmp,image/gif"
+                      :before-upload="beforeImageUpload"
+                      :http-request="opt => handleSingleUpload(opt, 'idBack')"
+                      :on-remove="(_f, fl) => onSingleRemove(fl, 'idBack')"
+                    >
+                      <div class="id-upload-trigger">
+                        <el-icon><Plus /></el-icon>
+                        <div class="id-side-label">上传证件反面</div>
+                      </div>
+                    </el-upload>
+                  </div>
+                </div>
+              </div>
+              <div class="upload-rules">
+                <p>说明:仅支持.jpg、.png格式,如果没有证件原件照片,可以上传证件照片复印件。</p>
+              </div>
+            </el-form-item>
+
+            <el-form-item label="证件号" prop="idNumber">
+              <el-input v-model="form.idNumber" placeholder="请输入证件号码" clearable style="max-width: 480px" />
+            </el-form-item>
+
+            <el-form-item label="法定代表人/负责人姓名" prop="legalName">
+              <el-input v-model="form.legalName" placeholder="请输入姓名" clearable style="max-width: 480px" />
+            </el-form-item>
+          </section>
+
+          <!-- 经营信息 -->
+          <section id="zfb-business" class="form-block anchor-section">
+            <h2 class="section-head">
+              <span class="section-bar" aria-hidden="true" />
+              经营信息
+            </h2>
+
+            <el-form-item label="接入服务类型" prop="serviceTypes">
+              <div class="field-stack">
+                <el-checkbox-group v-model="form.serviceTypes" class="service-checks">
+                  <el-checkbox v-for="s in serviceTypeOptions" :key="s.value" :label="s.value">
+                    {{ s.label }}
+                  </el-checkbox>
+                </el-checkbox-group>
+                <p class="field-tip">
+                  请勾选实际售卖商品/提供服务场景(至少一项),已便为你开通所需支付权限。建议只勾选目前必须的场景,以便尽快通过入驻审核,其他支付权限可在入驻后再根据需要发起申请
+                </p>
+              </div>
+            </el-form-item>
+
+            <el-form-item prop="storefrontUrl" v-if="form.serviceTypes.includes('当面付')">
+              <template #label> 上传门头照 </template>
+              <div class="license-upload-wrap">
+                <el-upload
+                  v-model:file-list="form.storefrontFileList"
+                  list-type="picture-card"
+                  :limit="1"
+                  accept=".jpg,.jpeg,.png,.bmp,.gif,image/jpeg,image/png,image/bmp,image/gif"
+                  :before-upload="beforeImageUpload"
+                  :http-request="opt => handleSingleUpload(opt, 'storefront')"
+                  :on-remove="(_f, fl) => onSingleRemove(fl, 'storefront')"
+                >
+                  <el-icon><Plus /></el-icon>
+                </el-upload>
+              </div>
+              <div class="upload-rules">
+                <p>说明:仅支持jpg、png格式,图片需清晰完整,最多上传3张。</p>
+              </div>
+            </el-form-item>
+
+            <el-form-item prop="interiorUrl" v-if="form.serviceTypes.includes('当面付')">
+              <template #label> 上传内景照 </template>
+              <div class="license-upload-wrap">
+                <el-upload
+                  v-model:file-list="form.interiorFileList"
+                  list-type="picture-card"
+                  :limit="1"
+                  accept=".jpg,.jpeg,.png,.bmp,.gif,image/jpeg,image/png,image/bmp,image/gif"
+                  :before-upload="beforeImageUpload"
+                  :http-request="opt => handleSingleUpload(opt, 'interior')"
+                  :on-remove="(_f, fl) => onSingleRemove(fl, 'interior')"
+                >
+                  <el-icon><Plus /></el-icon>
+                </el-upload>
+              </div>
+              <div class="upload-rules">
+                <p>说明:仅支持jpg、png格式,图片需清晰完整,最多上传3张。</p>
+              </div>
+            </el-form-item>
+
+            <el-form-item label="店铺地址" prop="region" v-if="form.serviceTypes.includes('当面付')">
+              <div class="address-row">
+                <el-cascader
+                  v-model="form.region"
+                  :options="regionCascaderOptions"
+                  placeholder="省 / 市"
+                  filterable
+                  clearable
+                  style="width: 320px"
+                />
+                <el-input
+                  v-model="form.detailAddress"
+                  class="address-detail"
+                  placeholder="街道、门牌号等"
+                  clearable
+                  maxlength="200"
+                />
+              </div>
+            </el-form-item>
+
+            <el-form-item label="APP名称" prop="appName" v-if="form.serviceTypes.includes('App支付')">
+              <el-input
+                v-model="form.appName"
+                placeholder="请输入APP名称"
+                clearable
+                maxlength="64"
+                show-word-limit
+                style="max-width: 480px"
+              />
+            </el-form-item>
+
+            <el-form-item label="联系人姓名" prop="contactName">
+              <el-input v-model="form.contactName" placeholder="请输入联系人姓名" clearable style="max-width: 480px" />
+            </el-form-item>
+
+            <el-form-item label="联系人手机号" prop="contactPhone">
+              <el-input
+                v-model="form.contactPhone"
+                placeholder="请输入手机号"
+                clearable
+                maxlength="11"
+                style="max-width: 480px"
+              />
+            </el-form-item>
+
+            <el-form-item label="联系人邮箱" prop="contactEmail">
+              <el-input v-model="form.contactEmail" placeholder="请输入邮箱" clearable style="max-width: 480px" />
+            </el-form-item>
+
+            <el-form-item label="客服电话" prop="servicePhone">
+              <el-input
+                v-model="form.servicePhone"
+                placeholder="请输入客服电话"
+                clearable
+                maxlength="20"
+                style="max-width: 480px"
+              />
+            </el-form-item>
+
+            <el-form-item prop="settlementAlipayAccount">
+              <template #label> 签约支付宝账号 </template>
+              <div class="field-stack">
+                <el-input
+                  v-model="form.settlementAlipayAccount"
+                  placeholder="请输入用于收款的支付宝账号"
+                  clearable
+                  style="max-width: 480px"
+                />
+                <p class="field-tip">如商家无支付宝账号,请引导商家至支付宝注册。</p>
+              </div>
+            </el-form-item>
+          </section>
+        </el-form>
+
+        <div class="footer-actions">
+          <el-button type="primary" class="btn-primary-zfb" :loading="nextLoading" @click="onNext"> 下一步 </el-button>
+        </div>
+      </div>
+
+      <aside class="anchor-column">
+        <el-affix :offset="88">
+          <div class="anchor-card">
+            <el-anchor container=".el-main" :offset="72" :bound="48" direction="vertical">
+              <el-anchor-link href="#zfb-subject" title="主体信息" />
+              <el-anchor-link href="#zfb-legal" title="法人信息" />
+              <el-anchor-link href="#zfb-business" title="经营信息" />
+            </el-anchor>
+          </div>
+        </el-affix>
+      </aside>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed, nextTick, onMounted, reactive, ref, watch } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
+import type { FormInstance, FormRules } from "element-plus";
+import type { UploadRequestOptions, UploadUserFile } from "element-plus";
+import { Plus, InfoFilled } from "@element-plus/icons-vue";
+import { getOcrRequestByBase64, uploadAlipayImage } from "@/api/modules/businessInfo";
+import { localGet, localSet } from "@/utils/index";
+import cityJson from "@/assets/json/city.json";
+import categoryJson from "@/views/businessInfo/category.json";
+
+const ALIPAY_JSON_KEY = "alipayJson";
+const GEEKER_USER_KEY = "geeker-user";
+
+/** 同时勾选当面付 + App 支付时,APP 名称默认与进件 sites[0].SiteName 一致 */
+const DEFAULT_ALIPAY_APP_SITE_NAME = "应用2.0签约2025092468860692";
+
+/** 进件 externalId:16 位随机数字(0–9) */
+function randomAlipayExternalId16(): string {
+  const buf = new Uint8Array(16);
+  crypto.getRandomValues(buf);
+  let s = "";
+  for (let i = 0; i < 16; i++) {
+    s += String(buf[i]! % 10);
+  }
+  return s;
+}
+
+const formRef = ref<FormInstance>();
+const nextLoading = ref(false);
+const router = useRouter();
+const route = useRoute();
+
+function resolveAlipayUploadStoreId(): string | number | null {
+  const q = route.query.storeId;
+  if (q !== undefined && q !== null && String(q).trim() !== "") {
+    return Array.isArray(q) ? q[0]! : q;
+  }
+  const geeker = localGet(GEEKER_USER_KEY) as { userInfo?: { storeId?: string | number | null } } | null | undefined;
+  const sid = geeker?.userInfo?.storeId ?? localGet("createdId");
+  if (sid === undefined || sid === null || sid === "") return null;
+  return sid;
+}
+/** 支付宝进件步骤:0 商家信息 / 1 结算信息 / 2 提交审核 */
+const zfbStepActive = ref(0);
+
+type CategoryJsonNode = {
+  code?: string;
+  name?: string;
+  parentCode?: string;
+  parentName?: string;
+  level?: number;
+  display?: boolean;
+  status?: string;
+  sortNum?: number;
+  childrenNodes?: CategoryJsonNode[];
+};
+
+type CategoryCascaderNode = { value: string; label: string; children?: CategoryCascaderNode[] };
+
+/**
+ * 二级经营类目:一级为 level=1(name/code),二级为其 childrenNodes 中 level=2 的 name/code
+ */
+function buildCategoryCascaderOptions(root: unknown): CategoryCascaderNode[] {
+  const list = (root as { data?: { childrenNodes?: CategoryJsonNode[] } })?.data?.childrenNodes;
+  if (!Array.isArray(list)) return [];
+  return list
+    .filter(n => n && typeof n === "object" && n.level === 1 && n.code && n.name && n.status === "VALID" && n.display !== false)
+    .sort((a, b) => (a.sortNum ?? 0) - (b.sortNum ?? 0))
+    .map(parent => {
+      const children = (parent.childrenNodes || [])
+        .filter(
+          ch =>
+            ch && typeof ch === "object" && ch.level === 2 && ch.code && ch.name && ch.status === "VALID" && ch.display !== false
+        )
+        .sort((a, b) => (a.sortNum ?? 0) - (b.sortNum ?? 0))
+        .map(ch => ({
+          value: String(ch.code),
+          label: String(ch.name)
+        }));
+      return {
+        value: String(parent.code),
+        label: String(parent.name),
+        children
+      };
+    })
+    .filter(p => p.children && p.children.length > 0);
+}
+
+const categoryCascaderOptions = buildCategoryCascaderOptions(categoryJson);
+
+const categoryCascaderProps = {
+  value: "value",
+  label: "label",
+  children: "children",
+  emitPath: true
+};
+
+const subjectTypeOptions = [
+  { label: "企业", value: "01" },
+  // { label: "事业单位", value: "02" },
+  // { label: "民办非企业组织", value: "03" },
+  // { label: "社会团体", value: "04" },
+  // { label: "党政及国家机关", value: "05" },
+  // { label: "个人商户", value: "06" },
+  { label: "个体工商户", value: "07" }
+];
+
+const serviceTypeOptions = [
+  { label: "当面付", value: "当面付" },
+  { label: "App支付", value: "App支付" }
+];
+
+type CityJsonEntry = { name: string; adCode: string; cityCode: string };
+type CityJsonRoot = { cityList: { letter: string; list: CityJsonEntry[] }[] };
+
+const PROVINCE_ROWS: [string, string][] = [
+  ["11", "北京市"],
+  ["12", "天津市"],
+  ["13", "河北省"],
+  ["14", "山西省"],
+  ["15", "内蒙古自治区"],
+  ["21", "辽宁省"],
+  ["22", "吉林省"],
+  ["23", "黑龙江省"],
+  ["31", "上海市"],
+  ["32", "江苏省"],
+  ["33", "浙江省"],
+  ["34", "安徽省"],
+  ["35", "福建省"],
+  ["36", "江西省"],
+  ["37", "山东省"],
+  ["41", "河南省"],
+  ["42", "湖北省"],
+  ["43", "湖南省"],
+  ["44", "广东省"],
+  ["45", "广西壮族自治区"],
+  ["46", "海南省"],
+  ["50", "重庆市"],
+  ["51", "四川省"],
+  ["52", "贵州省"],
+  ["53", "云南省"],
+  ["54", "西藏自治区"],
+  ["61", "陕西省"],
+  ["62", "甘肃省"],
+  ["63", "青海省"],
+  ["64", "宁夏回族自治区"],
+  ["65", "新疆维吾尔自治区"],
+  ["71", "台湾省"],
+  ["81", "香港特别行政区"],
+  ["82", "澳门特别行政区"]
+];
+const PROVINCE_BY_PREFIX = Object.fromEntries(PROVINCE_ROWS) as Record<string, string>;
+const PROVINCE_PREFIX_ORDER = PROVINCE_ROWS.map(([k]) => k);
+
+function buildProvinceCityOptions(): {
+  label: string;
+  value: string;
+  cities: { label: string; value: string }[];
+}[] {
+  const root = cityJson as CityJsonRoot;
+  const flat = root.cityList.flatMap(g => g.list);
+  const bucket = new Map<string, Map<string, CityJsonEntry>>();
+  for (const c of flat) {
+    const digits = String(c.adCode ?? "").replace(/\D/g, "");
+    const code = digits.length >= 6 ? digits.slice(-6) : digits.padStart(6, "0");
+    if (code.length !== 6) continue;
+    const prefix = code.slice(0, 2);
+    if (!PROVINCE_BY_PREFIX[prefix]) continue;
+    if (!bucket.has(prefix)) bucket.set(prefix, new Map());
+    bucket.get(prefix)!.set(c.adCode, c);
+  }
+  const out = [...bucket.entries()].map(([prefix, cityMap]) => ({
+    value: prefix,
+    label: PROVINCE_BY_PREFIX[prefix],
+    cities: [...cityMap.values()]
+      .sort((a, b) => a.name.localeCompare(b.name, "zh-CN"))
+      .map(ci => ({ label: ci.name, value: ci.adCode }))
+  }));
+  out.sort((a, b) => {
+    const ia = PROVINCE_PREFIX_ORDER.indexOf(a.value);
+    const ib = PROVINCE_PREFIX_ORDER.indexOf(b.value);
+    return (ia === -1 ? 999 : ia) - (ib === -1 ? 999 : ib);
+  });
+  return out;
+}
+
+const provinceCityOptions = buildProvinceCityOptions();
+
+const regionCascaderOptions = computed(() =>
+  provinceCityOptions.map(p => ({
+    value: p.value,
+    label: p.label,
+    children: p.cities.map(c => ({ value: c.value, label: c.label }))
+  }))
+);
+
+type UploadKind =
+  | "license"
+  | "idFront"
+  | "idBack"
+  | "storefront"
+  | "interior"
+  | "institutionCert"
+  | "otherOrgCert"
+  | "socialCert"
+  | "govCert";
+
+const form = reactive<{
+  subjectType: string;
+  licenseFileList: UploadUserFile[];
+  licenseUrl: string;
+  /** 营业执照上传接口返回的 image_id,供 alipayJson.certImage */
+  licenseImageId: string;
+  creditCode: string;
+  householdLicenseName: string;
+  merchantShortName: string;
+  businessTermRange: [string, string] | undefined;
+  institutionCertFileList: UploadUserFile[];
+  institutionCertUrl: string;
+  institutionCertNumber: string;
+  otherOrgCertFileList: UploadUserFile[];
+  otherOrgCertUrl: string;
+  otherOrgCertNumber: string;
+  socialCertFileList: UploadUserFile[];
+  socialCertUrl: string;
+  socialCertNumber: string;
+  govCertFileList: UploadUserFile[];
+  govCertUrl: string;
+  govCertNumber: string;
+  businessCategory: string[];
+  legalIdType: string;
+  idFrontFileList: UploadUserFile[];
+  idFrontUrl: string;
+  idBackFileList: UploadUserFile[];
+  idBackUrl: string;
+  idNumber: string;
+  legalName: string;
+  serviceTypes: string[];
+  storefrontFileList: UploadUserFile[];
+  storefrontUrl: string;
+  /** 上传接口返回的 image_id,供 alipayJson.outDoorImages */
+  storefrontImageId: string;
+  interiorFileList: UploadUserFile[];
+  interiorUrl: string;
+  /** 上传接口返回的 image_id,供 alipayJson.inDoorImages */
+  interiorImageId: string;
+  institutionStorefrontFileList: UploadUserFile[];
+  institutionStorefrontUrls: string[];
+  institutionInteriorFileList: UploadUserFile[];
+  institutionInteriorUrls: string[];
+  region: string[];
+  detailAddress: string;
+  appName: string;
+  contactName: string;
+  contactPhone: string;
+  contactEmail: string;
+  servicePhone: string;
+  settlementAlipayAccount: string;
+}>({
+  subjectType: "01",
+  licenseFileList: [],
+  licenseUrl: "",
+  licenseImageId: "",
+  creditCode: "",
+  householdLicenseName: "",
+  merchantShortName: "",
+  businessTermRange: undefined,
+  institutionCertFileList: [],
+  institutionCertUrl: "",
+  institutionCertNumber: "",
+  otherOrgCertFileList: [],
+  otherOrgCertUrl: "",
+  otherOrgCertNumber: "",
+  socialCertFileList: [],
+  socialCertUrl: "",
+  socialCertNumber: "",
+  govCertFileList: [],
+  govCertUrl: "",
+  govCertNumber: "",
+  businessCategory: [],
+  legalIdType: "",
+  idFrontFileList: [],
+  idFrontUrl: "",
+  idBackFileList: [],
+  idBackUrl: "",
+  idNumber: "",
+  legalName: "",
+  serviceTypes: [],
+  storefrontFileList: [],
+  storefrontUrl: "",
+  storefrontImageId: "",
+  interiorFileList: [],
+  interiorUrl: "",
+  interiorImageId: "",
+  institutionStorefrontFileList: [],
+  institutionStorefrontUrls: [],
+  institutionInteriorFileList: [],
+  institutionInteriorUrls: [],
+  region: [],
+  detailAddress: "",
+  appName: "",
+  contactName: "",
+  contactPhone: "",
+  contactEmail: "",
+  servicePhone: "",
+  settlementAlipayAccount: ""
+});
+
+watch(
+  () => form.serviceTypes.slice().sort().join("\0"),
+  () => {
+    const hasFace = form.serviceTypes.includes("当面付");
+    const hasApp = form.serviceTypes.includes("App支付");
+    if (hasFace && hasApp && !String(form.appName || "").trim()) {
+      form.appName = DEFAULT_ALIPAY_APP_SITE_NAME;
+    }
+  }
+);
+
+/** 用户切换到个体工商户时清空本页字段,避免企业侧已填数据带入个体户(与初始 form 一致,不改 subjectType) */
+function clearZfbFormExceptSubjectType() {
+  form.licenseFileList = [];
+  form.licenseUrl = "";
+  form.licenseImageId = "";
+  form.creditCode = "";
+  form.householdLicenseName = "";
+  form.merchantShortName = "";
+  form.businessTermRange = undefined;
+  form.institutionCertFileList = [];
+  form.institutionCertUrl = "";
+  form.institutionCertNumber = "";
+  form.otherOrgCertFileList = [];
+  form.otherOrgCertUrl = "";
+  form.otherOrgCertNumber = "";
+  form.socialCertFileList = [];
+  form.socialCertUrl = "";
+  form.socialCertNumber = "";
+  form.govCertFileList = [];
+  form.govCertUrl = "";
+  form.govCertNumber = "";
+  form.businessCategory = [];
+  form.legalIdType = "";
+  form.idFrontFileList = [];
+  form.idFrontUrl = "";
+  form.idBackFileList = [];
+  form.idBackUrl = "";
+  form.idNumber = "";
+  form.legalName = "";
+  form.serviceTypes = [];
+  form.storefrontFileList = [];
+  form.storefrontUrl = "";
+  form.storefrontImageId = "";
+  form.interiorFileList = [];
+  form.interiorUrl = "";
+  form.interiorImageId = "";
+  form.institutionStorefrontFileList = [];
+  form.institutionStorefrontUrls = [];
+  form.institutionInteriorFileList = [];
+  form.institutionInteriorUrls = [];
+  form.region = [];
+  form.detailAddress = "";
+  form.appName = "";
+  form.contactName = "";
+  form.contactPhone = "";
+  form.contactEmail = "";
+  form.servicePhone = "";
+  form.settlementAlipayAccount = "";
+}
+
+function onSubjectTypeChange(val: string | number | boolean | undefined) {
+  if (String(val ?? "") !== "07") return;
+  clearZfbFormExceptSubjectType();
+  nextTick(() => formRef.value?.clearValidate());
+}
+
+/** 支付宝图片上传接口:原始二进制最大 10MB(与接口文档一致) */
+const MAX_ALIPAY_IMAGE_BYTES = 10 * 1024 * 1024;
+
+/** 事业单位材料:仅 jpg / png(与页面说明一致) */
+function beforeImageUploadInstJpgPng(file: File) {
+  const name = file.name?.toLowerCase() || "";
+  const okExt = /\.(jpe?g|png)$/i.test(name);
+  const okMime = ["image/jpeg", "image/png"].includes(file.type);
+  if (!okExt && !okMime) {
+    ElMessage.error("仅支持 jpg、png 格式");
+    return false;
+  }
+  if (file.size > MAX_ALIPAY_IMAGE_BYTES) {
+    ElMessage.error("文件大小不能超过 10M");
+    return false;
+  }
+  return true;
+}
+
+function beforeImageUpload(file: File) {
+  const name = file.name?.toLowerCase() || "";
+  const okExt = /\.(jpe?g|png|bmp|gif)$/i.test(name);
+  const okMime = ["image/jpeg", "image/png", "image/bmp", "image/gif"].includes(file.type);
+  if (!okExt && !okMime) {
+    ElMessage.error("图片只支持 JPG、BMP、PNG、GIF 格式");
+    return false;
+  }
+  if (file.size > MAX_ALIPAY_IMAGE_BYTES) {
+    ElMessage.error("文件大小不能超过 10M");
+    return false;
+  }
+  return true;
+}
+
+/** 解析 image_type:扩展名 3~16 字符,jpeg 归一为 jpg */
+function resolveAlipayImageType(file: File): string | null {
+  const name = file.name || "";
+  const extMatch = /\.([a-zA-Z0-9]{1,16})$/i.exec(name);
+  let ext = extMatch ? extMatch[1].toLowerCase() : "";
+  if (ext === "jpeg") ext = "jpg";
+  if (ext && ext.length >= 3 && ext.length <= 16) return ext;
+  const mime = file.type;
+  if (mime === "image/jpeg") return "jpg";
+  if (mime === "image/png") return "png";
+  if (mime === "image/gif") return "gif";
+  if (mime === "image/bmp") return "bmp";
+  return null;
+}
+
+/** 解析支付宝/通用上传返回;兼容 data 为 JSON 字符串(直付通 ant_merchant_expand_indirect_image_upload_response) */
+function parseMediaUploadResult(res: any): { fileUrl: string; mediaId: string; errMsg: string } {
+  const errMsg = String(res?.msg ?? "").trim();
+  let payload = res?.data;
+  if (payload === undefined) payload = res;
+
+  if (typeof payload === "string") {
+    const s = payload.trim();
+    if (/^https?:\/\//i.test(s)) return { fileUrl: s, mediaId: "", errMsg };
+    if ((s.startsWith("{") || s.startsWith("[")) && s.length > 1) {
+      try {
+        payload = JSON.parse(s);
+      } catch {
+        if (s) return { fileUrl: "", mediaId: s, errMsg };
+        return { fileUrl: "", mediaId: "", errMsg };
+      }
+    } else if (s) {
+      return { fileUrl: "", mediaId: s, errMsg };
+    } else {
+      return { fileUrl: "", mediaId: "", errMsg };
+    }
+  }
+
+  if (!payload || typeof payload !== "object") {
+    return { fileUrl: "", mediaId: "", errMsg };
+  }
+
+  let body: any = payload;
+  if ("data" in payload && payload.data !== undefined) {
+    if (typeof payload.data === "string") {
+      const inner = payload.data.trim();
+      if (/^https?:\/\//i.test(inner)) return { fileUrl: inner, mediaId: "", errMsg };
+      if ((inner.startsWith("{") || inner.startsWith("[")) && inner.length > 1) {
+        try {
+          body = JSON.parse(inner);
+        } catch {
+          if (inner) return { fileUrl: "", mediaId: inner, errMsg };
+          body = payload;
+        }
+      } else if (inner) {
+        return { fileUrl: "", mediaId: inner, errMsg };
+      }
+    } else if (payload.data && typeof payload.data === "object") {
+      body = payload.data;
+    }
+  }
+
+  if (body && typeof body === "object" && "data" in body && body.data !== undefined) {
+    if (typeof body.data === "string") {
+      const inner = body.data.trim();
+      if (/^https?:\/\//i.test(inner)) return { fileUrl: inner, mediaId: "", errMsg };
+      if ((inner.startsWith("{") || inner.startsWith("[")) && inner.length > 1) {
+        try {
+          body = JSON.parse(inner);
+        } catch {
+          if (inner) return { fileUrl: "", mediaId: inner, errMsg };
+        }
+      } else if (inner) {
+        return { fileUrl: "", mediaId: inner, errMsg };
+      }
+    } else if (body.data && typeof body.data === "object") {
+      body = body.data;
+    }
+  }
+
+  const antUpload =
+    body?.ant_merchant_expand_indirect_image_upload_response ?? body?.antMerchantExpandIndirectImageUploadResponse;
+
+  const fileUrl = String(
+    body?.url ?? body?.fileUrl ?? body?.imageUrl ?? body?.image_url ?? body?.picUrl ?? body?.ossUrl ?? body?.file_path ?? ""
+  ).trim();
+  const mediaId = String(
+    antUpload?.image_id ??
+      antUpload?.imageId ??
+      body?.image_id ??
+      body?.imageId ??
+      body?.resource_id ??
+      body?.resourceId ??
+      body?.media_id ??
+      body?.mediaId ??
+      body?.outBizNo ??
+      body?.pictureId ??
+      ""
+  ).trim();
+  return { fileUrl, mediaId, errMsg };
+}
+
+/** 与支付宝上传返回常见的 object / 文件名一致 */
+const ALIPAY_UPLOAD_IMAGE_FILE_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.(jpe?g|png)$/i;
+
+function extractAlipayFilenameFromImageUrl(url: string): string {
+  const s = String(url || "").trim();
+  if (!s || !/^https?:\/\//i.test(s)) return "";
+  try {
+    const seg = decodeURIComponent(new URL(s).pathname.split("/").filter(Boolean).pop() || "");
+    if (ALIPAY_UPLOAD_IMAGE_FILE_RE.test(seg) || /\.(jpe?g|png)$/i.test(seg)) return seg;
+  } catch {
+    /* ignore */
+  }
+  return "";
+}
+
+/** 深度遍历响应,取 image_id 等字段(兼容多层 data / 字段名差异) */
+function deepPickAlipayImageId(node: any, depth = 0): string {
+  if (depth > 14 || node === null || node === undefined) return "";
+  if (typeof node === "string") {
+    const t = node.trim();
+    if (ALIPAY_UPLOAD_IMAGE_FILE_RE.test(t)) return t;
+    if (t.startsWith("{") && t.includes("image")) {
+      try {
+        return deepPickAlipayImageId(JSON.parse(t), depth + 1);
+      } catch {
+        return "";
+      }
+    }
+    return "";
+  }
+  if (typeof node !== "object") return "";
+  if (Array.isArray(node)) {
+    for (const x of node) {
+      const r = deepPickAlipayImageId(x, depth + 1);
+      if (r) return r;
+    }
+    return "";
+  }
+  const keys = ["image_id", "imageId", "ImageId", "fileName", "file_name", "objectName", "object_name", "key", "picName"];
+  for (const k of keys) {
+    if (!(k in node) || node[k] == null) continue;
+    const v = String(node[k]).trim();
+    if (!v) continue;
+    if (/^https?:\/\//i.test(v)) {
+      const fromUrl = extractAlipayFilenameFromImageUrl(v);
+      if (fromUrl) return fromUrl;
+    } else {
+      const base = v.split(/[/\\]/).pop() || v;
+      if (base) return base.trim();
+    }
+  }
+  for (const v of Object.values(node)) {
+    const r = deepPickAlipayImageId(v, depth + 1);
+    if (r) return r;
+  }
+  return "";
+}
+
+/** 上传成功后得到进件用图片名:扁平解析 → 深度查找 → 从返回的图片 URL 截取 */
+function resolveAlipayUploadImageId(res: any, fileUrl: string, mediaId: string): string {
+  let id = String(mediaId || "").trim();
+  if (id) return id.split(/[/\\]/).pop() || id;
+  id = deepPickAlipayImageId(res);
+  if (id) return id.split(/[/\\]/).pop() || id;
+  return extractAlipayFilenameFromImageUrl(fileUrl);
+}
+
+function isAlipayUploadHttpSuccess(res: any): boolean {
+  return res?.code === 200 || res?.code === "200";
+}
+
+/** 与 subjectInfo:营业执照 OCR 响应解析 */
+function pickBusinessLicenseOcrFields(res: any) {
+  const raw = res?.data ?? res;
+  let node: any = raw;
+  if (node && typeof node === "object" && "data" in node && node.data !== undefined) {
+    node = node.data;
+  }
+  const item = Array.isArray(node) ? node[0] : node;
+  if (!item || typeof item !== "object") {
+    return { creditCode: "", companyName: "", legalPerson: "" };
+  }
+  return {
+    creditCode: String(item.creditCode ?? item.credit_code ?? "").trim(),
+    companyName: String(item.companyName ?? item.company_name ?? "").trim(),
+    legalPerson: String(item.legalPerson ?? item.legal_person ?? "").trim()
+  };
+}
+
+/** 事业单位法人证书 OCR:证书编号、单位名称(回显商户简称) */
+function pickInstitutionCertOcrFields(res: any): { certNumber: string; orgName: string } {
+  const base = pickBusinessLicenseOcrFields(res);
+  const raw = res?.data ?? res;
+  let node: any = raw;
+  if (node && typeof node === "object" && "data" in node && node.data !== undefined) {
+    node = node.data;
+  }
+  const item = Array.isArray(node) ? node[0] : node;
+  let certNumber = base.creditCode;
+  let orgName = base.companyName;
+  if (item && typeof item === "object") {
+    if (!certNumber) {
+      certNumber = String(
+        item.certNumber ??
+          item.certificateNumber ??
+          item.cert_no ??
+          item.certificateNo ??
+          item.registrationNumber ??
+          item.registration_no ??
+          ""
+      ).trim();
+    }
+    if (!orgName) {
+      orgName = String(item.companyName ?? item.company_name ?? item.orgName ?? item.unitName ?? item.name ?? "").trim();
+    }
+  }
+  return { certNumber, orgName };
+}
+
+/** 身份证有效期 → YYYY-MM-DD(与 subjectInfo 一致) */
+function splitIdCardValidPeriod(raw: string): { begin: string; end: string } {
+  const s = (raw || "").trim();
+  if (!s) return { begin: "", end: "" };
+  if (/长期|长期有效/.test(s)) return { begin: "", end: "长期" };
+  const norm = s
+    .replace(/年|月|日/g, ".")
+    .replace(/\.+/g, ".")
+    .trim();
+  const parts = norm.split(/[-至~~]/);
+  const normOne = (p: string) => {
+    const m = p.trim().match(/(\d{4})\D*(\d{1,2})\D*(\d{1,2})/);
+    if (m) return `${m[1]}-${m[2].padStart(2, "0")}-${m[3].padStart(2, "0")}`;
+    return p.trim();
+  };
+  if (parts.length >= 2) {
+    return { begin: normOne(parts[0]), end: normOne(parts[1]) };
+  }
+  return { begin: "", end: "" };
+}
+
+/** 与 subjectInfo:身份证 OCR 响应解析 */
+function pickIdCardPortraitOcrFields(res: any): {
+  name: string;
+  idNumber: string;
+  idCardAddress: string;
+  cardPeriodBegin: string;
+  cardPeriodEnd: string;
+} {
+  const raw = res?.data ?? res;
+  let node: any = raw;
+  if (node && typeof node === "object" && "data" in node && node.data !== undefined) {
+    node = node.data;
+  }
+  const arr = Array.isArray(node) ? node : [node];
+  const item = arr[0];
+  const item2 = arr[1];
+  if (!item || typeof item !== "object") {
+    return { name: "", idNumber: "", idCardAddress: "", cardPeriodBegin: "", cardPeriodEnd: "" };
+  }
+  let name = String(item.name ?? item.userName ?? "").trim();
+  let idNumber = String(item.idNumber ?? item.id_number ?? item.idCard ?? item.id_card ?? "").trim();
+  const faceData = item.face?.data || item2?.face?.data;
+  const backData = item.back?.data || item2?.back?.data;
+  if (faceData && typeof faceData === "object") {
+    if (!name) name = String(faceData.name ?? "").trim();
+    if (!idNumber) idNumber = String(faceData.idNumber ?? faceData.id_number ?? "").trim();
+  }
+  let idCardAddress = "";
+  if (backData && typeof backData === "object") {
+    idCardAddress = String(backData.address ?? backData.registeredAddress ?? backData.issueAuthority ?? "").trim();
+  }
+  if (faceData && typeof faceData === "object" && !idCardAddress) {
+    idCardAddress = String(faceData.address ?? "").trim();
+  }
+  const faceKv = item.face?.prism_keyValueInfo || item2?.face?.prism_keyValueInfo;
+  if (Array.isArray(faceKv)) {
+    for (const row of faceKv) {
+      if (row?.key === "name" && row?.value && !name) name = String(row.value).trim();
+      if (row?.key === "idNumber" && row?.value && !idNumber) idNumber = String(row.value).trim();
+      if (row?.key === "address" && row?.value && !idCardAddress) {
+        idCardAddress = String(row.value).trim();
+      }
+    }
+  }
+  const backKv = item.back?.prism_keyValueInfo || item2?.back?.prism_keyValueInfo;
+  let validPeriodFromKv = "";
+  if (Array.isArray(backKv)) {
+    for (const row of backKv) {
+      if (row?.key === "address" && row?.value && !idCardAddress) {
+        idCardAddress = String(row.value).trim();
+      }
+      if (row?.value) {
+        const keyRaw = String(row.key || "");
+        if (/有效期限|有效期|失效日期|签发日期|validPeriod|validDate|valid_period/i.test(keyRaw)) {
+          const v = String(row.value).trim();
+          if (v && !validPeriodFromKv) validPeriodFromKv = v;
+        }
+      }
+    }
+  }
+  let vp = String(
+    (backData && (backData.validPeriod ?? backData.validDate)) ||
+      (faceData && (faceData.validPeriod ?? faceData.validDate)) ||
+      (item && (item.validPeriod ?? item.validDate)) ||
+      (item2 && (item2.validPeriod ?? item2.validDate)) ||
+      ""
+  ).trim();
+  if (!vp && validPeriodFromKv) vp = validPeriodFromKv;
+  const { begin: cardPeriodBegin, end: cardPeriodEnd } = splitIdCardValidPeriod(vp);
+  return { name, idNumber, idCardAddress, cardPeriodBegin, cardPeriodEnd };
+}
+
+function isOcrSuccess(res: any): boolean {
+  return res?.code === 200 || res?.code === "200";
+}
+
+/** 上传成功后按类型调用 OCR 并写入表单(与 subjectInfo 请求体一致:imageFile + ocrType) */
+async function runOcrAfterZfbUpload(kind: UploadKind, file: File) {
+  if (kind === "license") {
+    const formData = new FormData();
+    formData.append("imageFile", file, file.name || "license.jpg");
+    formData.append("ocrType", "BUSINESS_LICENSE");
+    const res: any = await getOcrRequestByBase64(formData);
+    if (isOcrSuccess(res)) {
+      const fields = pickBusinessLicenseOcrFields(res);
+      if (fields.creditCode) form.creditCode = fields.creditCode;
+      if (form.subjectType === "07") {
+        if (fields.companyName) {
+          form.householdLicenseName = fields.companyName;
+          form.merchantShortName = fields.companyName;
+        }
+      } else {
+        if (fields.companyName) form.merchantShortName = fields.companyName;
+        if (fields.legalPerson) form.legalName = fields.legalPerson;
+      }
+      ElMessage.success("营业执照识别成功");
+    } else {
+      ElMessage.warning(res?.msg || "营业执照识别未通过,请核对照片清晰度");
+    }
+    return;
+  }
+  if (kind === "institutionCert") {
+    const formData = new FormData();
+    formData.append("imageFile", file, file.name || "institution-cert.jpg");
+    formData.append("ocrType", "BUSINESS_LICENSE");
+    const res: any = await getOcrRequestByBase64(formData);
+    if (isOcrSuccess(res)) {
+      const f = pickInstitutionCertOcrFields(res);
+      if (f.certNumber) form.institutionCertNumber = f.certNumber;
+      if (f.orgName) form.merchantShortName = f.orgName;
+      ElMessage.success("事业单位法人证书识别成功");
+    } else {
+      ElMessage.warning(res?.msg || "事业单位法人证书识别未通过,请核对照片清晰度");
+    }
+    return;
+  }
+  if (kind === "idFront") {
+    const formData = new FormData();
+    formData.append("imageFile", file, file.name || "id-portrait.jpg");
+    formData.append("ocrType", "ID_CARD");
+    const res: any = await getOcrRequestByBase64(formData);
+    if (isOcrSuccess(res)) {
+      const f = pickIdCardPortraitOcrFields(res);
+      if (f.name) form.legalName = f.name;
+      if (f.idNumber) form.idNumber = f.idNumber;
+      if (f.cardPeriodBegin && f.cardPeriodEnd) {
+        form.businessTermRange = [f.cardPeriodBegin, f.cardPeriodEnd];
+      }
+      ElMessage.success("身份证人像面识别成功");
+    } else {
+      ElMessage.warning(res?.msg || "身份证人像面识别未通过,请核对照片清晰度");
+    }
+    return;
+  }
+  if (kind === "idBack") {
+    const formData = new FormData();
+    formData.append("imageFile", file, file.name || "id-emblem.jpg");
+    formData.append("ocrType", "ID_CARD");
+    const res: any = await getOcrRequestByBase64(formData);
+    if (isOcrSuccess(res)) {
+      const f = pickIdCardPortraitOcrFields(res);
+      if (f.cardPeriodBegin && f.cardPeriodEnd) {
+        form.businessTermRange = [f.cardPeriodBegin, f.cardPeriodEnd];
+      }
+      if (f.cardPeriodBegin || f.cardPeriodEnd) {
+        ElMessage.success("身份证国徽面识别成功");
+      } else {
+        ElMessage.warning("未识别到有效期限,请确认国徽面照片清晰完整");
+      }
+    } else {
+      ElMessage.warning(res?.msg || "身份证国徽面识别未通过,请核对照片清晰度");
+    }
+  }
+}
+
+function urlFieldFor(kind: UploadKind): keyof typeof form {
+  const map: Record<UploadKind, keyof typeof form> = {
+    license: "licenseUrl",
+    idFront: "idFrontUrl",
+    idBack: "idBackUrl",
+    storefront: "storefrontUrl",
+    interior: "interiorUrl",
+    institutionCert: "institutionCertUrl",
+    otherOrgCert: "otherOrgCertUrl",
+    socialCert: "socialCertUrl",
+    govCert: "govCertUrl"
+  };
+  return map[kind];
+}
+
+async function handleSingleUpload(options: UploadRequestOptions, kind: UploadKind) {
+  const uploadFileItem = options.file as UploadUserFile;
+  const raw = uploadFileItem.raw || uploadFileItem;
+  const file = raw instanceof File ? raw : null;
+  if (!file) return;
+
+  const field = urlFieldFor(kind);
+  uploadFileItem.status = "uploading";
+  try {
+    if (file.size > MAX_ALIPAY_IMAGE_BYTES) {
+      uploadFileItem.status = "fail";
+      ElMessage.error("文件大小不能超过 10M");
+      return;
+    }
+    const imageType = resolveAlipayImageType(file);
+    if (!imageType) {
+      uploadFileItem.status = "fail";
+      ElMessage.error("无法识别图片格式,请使用带扩展名的文件(如 .jpg、.png)");
+      return;
+    }
+    const storeId = resolveAlipayUploadStoreId();
+    // if (storeId === null) {
+    //   uploadFileItem.status = "fail";
+    //   ElMessage.error("未获取到门店 storeId,请重新登录或通过链接传入 storeId");
+    //   return;
+    // }
+    const res: any = await uploadAlipayImage({
+      storeId,
+      imageType,
+      imageContent: file
+    });
+    const { fileUrl, mediaId, errMsg } = parseMediaUploadResult(res);
+    const httpOk = isAlipayUploadHttpSuccess(res);
+    const hasMediaRef = !!(fileUrl || mediaId);
+    const resolvedImageId = resolveAlipayUploadImageId(res, fileUrl, mediaId);
+
+    if (hasMediaRef || httpOk) {
+      uploadFileItem.status = "success";
+      if (fileUrl) {
+        uploadFileItem.url = fileUrl;
+      } else {
+        uploadFileItem.url = URL.createObjectURL(file);
+      }
+      uploadFileItem.response = { media_id: resolvedImageId, url: fileUrl };
+      (form as any)[field] = fileUrl || mediaId || (httpOk ? uploadFileItem.url : "");
+      if (kind === "storefront") {
+        form.storefrontImageId = resolvedImageId;
+      }
+      if (kind === "interior") {
+        form.interiorImageId = resolvedImageId;
+      }
+      if (kind === "license") {
+        form.licenseImageId = resolvedImageId;
+      }
+
+      const needOcr = kind === "license" || kind === "idFront" || kind === "idBack" || kind === "institutionCert";
+      if (needOcr) {
+        try {
+          await runOcrAfterZfbUpload(kind, file);
+          nextTick(() => {
+            const f = formRef.value;
+            if (!f) return;
+            if (kind === "license") {
+              f.validateField("creditCode").catch(() => {});
+              f.validateField("merchantShortName").catch(() => {});
+              if (form.subjectType === "07") {
+                f.validateField("householdLicenseName").catch(() => {});
+              } else {
+                f.validateField("legalName").catch(() => {});
+              }
+            } else if (kind === "institutionCert") {
+              f.validateField("institutionCertNumber").catch(() => {});
+              f.validateField("merchantShortName").catch(() => {});
+            } else if (kind === "idFront") {
+              f.validateField("legalName").catch(() => {});
+              f.validateField("idNumber").catch(() => {});
+              f.validateField("businessTermRange").catch(() => {});
+            } else if (kind === "idBack") {
+              f.validateField("businessTermRange").catch(() => {});
+            }
+          });
+        } catch {
+          ElMessage.warning("识别服务暂时不可用,请稍后重试或手动填写");
+        }
+      }
+    } else {
+      uploadFileItem.status = "fail";
+      ElMessage.error(errMsg || res?.msg || "上传失败,未返回可用结果");
+    }
+  } catch {
+    uploadFileItem.status = "fail";
+    ElMessage.error("上传失败,请稍后重试");
+  }
+  formRef.value?.validateField(field as string).catch(() => {});
+}
+
+function onSingleRemove(fileList: UploadUserFile[], kind: UploadKind) {
+  const field = urlFieldFor(kind);
+  if (!fileList.length) {
+    (form as any)[field] = "";
+    if (kind === "storefront") form.storefrontImageId = "";
+    if (kind === "interior") form.interiorImageId = "";
+    if (kind === "license") form.licenseImageId = "";
+  } else {
+    const first = fileList[0] as UploadUserFile & {
+      url?: string;
+      response?: { url?: string; media_id?: string };
+    };
+    (form as any)[field] = first?.url || first?.response?.url || "";
+    if (kind === "storefront") {
+      form.storefrontImageId = String(first?.response?.media_id || "").trim();
+    }
+    if (kind === "interior") {
+      form.interiorImageId = String(first?.response?.media_id || "").trim();
+    }
+    if (kind === "license") {
+      form.licenseImageId = String(first?.response?.media_id || "").trim();
+    }
+  }
+  formRef.value?.validateField(field as string).catch(() => {});
+}
+
+/** alipayJson.service 仅传接入类型的 value(当面付 / App支付),不把 face_to_face、app 等内部码传给接口 */
+function serviceValuesForAlipayPayload(selected: string[]): string[] {
+  const codeToValue: Record<string, string> = {
+    face_to_face: "当面付",
+    app: "App支付"
+  };
+  const allowed = new Set(serviceTypeOptions.map(o => o.value));
+  const out: string[] = [];
+  const seen = new Set<string>();
+  for (const s of selected) {
+    const v = codeToValue[s] ?? (allowed.has(s) ? s : "");
+    if (v && !seen.has(v)) {
+      seen.add(v);
+      out.push(v);
+    }
+  }
+  return out;
+}
+
+/** 店铺地址写入 alipayJson;行政区划码由省前缀、市 adCode 推导(仅省/市二级时 DistrictCode 与 CityCode 相同) */
+function buildBusinessAddressForAlipayJson():
+  | {
+      address: string;
+      districtCode: string;
+      cityCode: string;
+      provinceCode: string;
+    }
+  | undefined {
+  const region = form.region;
+  if (!Array.isArray(region) || region.length < 2) return undefined;
+  const provPrefix = String(region[0] ?? "").replace(/\D/g, "");
+  const cityAd = String(region[1] ?? "").replace(/\D/g, "");
+  if (!provPrefix || cityAd.length < 6) return undefined;
+
+  const prov = provinceCityOptions.find(p => p.value === region[0]);
+  const provinceName = prov?.label ?? "";
+  const cityName = prov?.cities.find(c => c.value === region[1])?.label ?? "";
+  const detail = String(form.detailAddress || "").trim();
+  const address = `${provinceName}${cityName}${detail}`.trim();
+
+  const provinceCode = provPrefix.padEnd(6, "0").slice(0, 6);
+  const cityCode = cityAd.padStart(6, "0").slice(0, 6);
+  const districtCode = cityCode;
+
+  return { address, districtCode, cityCode, provinceCode };
+}
+
+/** 仅使用上传成功接口里保存的 image_id;且只认 .jpg / .jpeg / .png(不从 URL 等其它字段截取) */
+function alipayImageIdFromUploadOnly(imageIdField: string): string {
+  const s = String(imageIdField || "").trim();
+  if (!s) return "";
+  const lower = s.toLowerCase();
+  if (lower.endsWith(".jpg") || lower.endsWith(".jpeg") || lower.endsWith(".png")) return s;
+  return "";
+}
+
+/** 进件接口要求数组:有图为单元素数组,无图为 [] */
+function alipayImageIdArrayForPayload(imageIdField: string): string[] {
+  const id = alipayImageIdFromUploadOnly(imageIdField);
+  return id ? [id] : [];
+}
+
+/** 从 localStorage 读取的 alipayJson 可能是对象或历史字符串 */
+function normalizeAlipayJsonFromStorage(raw: unknown): Record<string, unknown> | null {
+  if (raw == null || raw === "") return null;
+  if (typeof raw === "string") {
+    try {
+      const o = JSON.parse(raw) as unknown;
+      return typeof o === "object" && o !== null && !Array.isArray(o) ? (o as Record<string, unknown>) : null;
+    } catch {
+      return null;
+    }
+  }
+  if (typeof raw === "object" && !Array.isArray(raw)) return raw as Record<string, unknown>;
+  return null;
+}
+
+function findCategoryPathByMcc(mcc: string): string[] | undefined {
+  const m = String(mcc || "").trim();
+  if (!m) return undefined;
+  for (const p of categoryCascaderOptions) {
+    const ch = p.children?.find(c => c.value === m);
+    if (ch) return [p.value, ch.value];
+  }
+  return undefined;
+}
+
+function firstImageIdFromAlipayField(val: unknown): string {
+  if (Array.isArray(val) && val.length > 0) return String(val[0] ?? "").trim();
+  if (typeof val === "string") return val.trim();
+  return "";
+}
+
+/** 将 businessAddress 反填为省市区 cascader + 详细地址(与 buildBusinessAddressForAlipayJson 对称) */
+function regionAndDetailFromBusinessAddress(ba: unknown): { region: string[]; detailAddress: string } | undefined {
+  if (!ba || typeof ba !== "object") return undefined;
+  const o = ba as Record<string, unknown>;
+  const provinceCode = String(o.provinceCode ?? "").replace(/\D/g, "");
+  const cityCode = String(o.cityCode ?? "").replace(/\D/g, "");
+  const address = String(o.address ?? "").trim();
+  if (provinceCode.length < 2 || cityCode.length < 6) return undefined;
+  const prefix = provinceCode.slice(0, 2);
+  const prov = provinceCityOptions.find(p => p.value === prefix);
+  if (!prov) return undefined;
+  const normCity = cityCode.padStart(6, "0").slice(0, 6);
+  const city = prov.cities.find(c => {
+    const ad = String(c.value ?? "").replace(/\D/g, "");
+    const tail = ad.length >= 6 ? ad.slice(-6) : ad;
+    return tail.padStart(6, "0") === normCity;
+  });
+  if (!city) return undefined;
+  let detail = address;
+  const prefixStr = `${prov.label}${city.label}`;
+  if (address.startsWith(prefixStr)) detail = address.slice(prefixStr.length).trim();
+  return { region: [prefix, city.value], detailAddress: detail };
+}
+
+/** alipayJson.service 为「当面付」「App支付」等;兼容旧内部码 */
+function serviceTypesFromAlipayService(val: unknown): string[] {
+  const allowed = new Set(serviceTypeOptions.map(o => o.value));
+  const legacy: Record<string, string> = {
+    face_to_face: "当面付",
+    app: "App支付"
+  };
+  const arr = Array.isArray(val) ? val : typeof val === "string" && val.trim() ? [val] : [];
+  const out: string[] = [];
+  const seen = new Set<string>();
+  for (const item of arr) {
+    let s = String(item ?? "").trim();
+    if (s.toLowerCase() === "app 支付") s = "App支付";
+    const mapped = legacy[s] ?? s;
+    if (mapped && allowed.has(mapped) && !seen.has(mapped)) {
+      seen.add(mapped);
+      out.push(mapped);
+    }
+  }
+  return out;
+}
+
+/** 进入本页时把缓存中的 alipayJson 写回第一步表单 */
+function applyAlipayJsonCacheToForm(data: Record<string, unknown>) {
+  const st = String(data.merchantType ?? "").trim();
+  if (st) form.subjectType = st;
+
+  const name = String(data.name ?? data.aliasName ?? "").trim();
+  if (name) form.merchantShortName = name;
+
+  const mcc = String(data.mcc ?? "").trim();
+  const path = findCategoryPathByMcc(mcc);
+  if (path) form.businessCategory = path;
+
+  const certNo = String(data.certNo ?? "").trim();
+  if (certNo) form.creditCode = certNo;
+
+  const certImage = String(data.certImage ?? "").trim();
+  if (certImage) form.licenseImageId = certImage;
+
+  const legalName = String(data.legalName ?? "").trim();
+  if (legalName) form.legalName = legalName;
+
+  const legalCertNo = String(data.legalCertNo ?? "").trim();
+  if (legalCertNo) form.idNumber = legalCertNo;
+
+  const certName = String(data.certName ?? "").trim();
+  if (certName && form.subjectType === "07") form.householdLicenseName = certName;
+
+  const alipayId = String(data.alipayLogonId ?? data.bindingAlipayLogonId ?? data.BindingAlipayLogonId ?? "").trim();
+  if (alipayId) form.settlementAlipayAccount = alipayId;
+
+  const ci = data.contactInfos;
+  if (Array.isArray(ci) && ci.length > 0) {
+    const c0 = ci[0] as Record<string, unknown>;
+    const cn = String(c0?.name ?? "").trim();
+    const cm = String(c0?.mobile ?? "").trim();
+    if (cn) form.contactName = cn;
+    if (cm) form.contactPhone = cm;
+  }
+
+  const svc = serviceTypesFromAlipayService(data.service);
+  if (svc.length) form.serviceTypes = svc;
+
+  const inId = firstImageIdFromAlipayField(data.inDoorImages);
+  if (inId) form.interiorImageId = inId;
+
+  const outId = firstImageIdFromAlipayField(data.outDoorImages);
+  if (outId) form.storefrontImageId = outId;
+
+  const ba = regionAndDetailFromBusinessAddress(data.businessAddress);
+  if (ba) {
+    form.region = ba.region;
+    form.detailAddress = ba.detailAddress;
+  }
+
+  const sites = data.sites;
+  if (Array.isArray(sites) && sites.length > 0) {
+    const s0 = sites[0] as Record<string, unknown>;
+    const sn = String(s0?.siteName ?? s0?.siteName ?? "").trim();
+    if (sn) form.appName = sn;
+  }
+}
+
+/** 下一步写入 localStorage,供后续支付宝进件等使用 */
+function buildAlipayJsonPayload() {
+  const mcc =
+    Array.isArray(form.businessCategory) && form.businessCategory.length >= 2
+      ? form.businessCategory[1]
+      : Array.isArray(form.businessCategory) && form.businessCategory.length === 1
+        ? form.businessCategory[0]
+        : "";
+  const businessAddress = buildBusinessAddressForAlipayJson();
+  const certName = form.subjectType === "07" ? String(form.householdLicenseName || "").trim() : "";
+  const alipayLogonIdVal = String(form.settlementAlipayAccount || "").trim();
+  const hasFaceToFace = form.serviceTypes.includes("当面付");
+  const hasAppPay = form.serviceTypes.includes("App支付");
+  const siteNameForPayload = String(form.appName || "").trim() || DEFAULT_ALIPAY_APP_SITE_NAME;
+  return {
+    type: 0,
+    externalId: randomAlipayExternalId16(),
+    name: form.merchantShortName,
+    aliasName: form.merchantShortName,
+    merchantType: form.subjectType,
+    mcc,
+    certNo: form.creditCode,
+    certType: 201,
+    certImage: alipayImageIdFromUploadOnly(form.licenseImageId),
+    legalName: form.legalName,
+    legalCertNo: form.idNumber,
+    certName,
+    alipayLogonId: alipayLogonIdVal,
+    contactInfos: [
+      {
+        name: String(form.contactName || "").trim(),
+        mobile: String(form.contactPhone || "").trim()
+      }
+    ],
+    service: serviceValuesForAlipayPayload(form.serviceTypes),
+    inDoorImages: alipayImageIdArrayForPayload(form.interiorImageId),
+    outDoorImages: alipayImageIdArrayForPayload(form.storefrontImageId),
+    ...(businessAddress ? { businessAddress } : {}),
+    ...(hasFaceToFace && hasAppPay
+      ? {
+          sites: [{ siteType: "02", siteName: siteNameForPayload }]
+        }
+      : {})
+  };
+}
+
+onMounted(async () => {
+  const cached = normalizeAlipayJsonFromStorage(localGet(ALIPAY_JSON_KEY));
+  if (cached) applyAlipayJsonCacheToForm(cached);
+  await nextTick();
+  formRef.value?.clearValidate();
+});
+
+const rules: FormRules = {
+  subjectType: [{ required: true, message: "请选择主体类型", trigger: "change" }],
+  serviceTypes: [
+    {
+      type: "array",
+      required: true,
+      min: 1,
+      message: "请选择接入服务类型",
+      trigger: "change"
+    }
+  ],
+  licenseUrl: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.subjectType !== "01" && form.subjectType !== "07") return cb();
+        if (!String(form.licenseUrl || "").trim()) cb(new Error("请上传营业执照"));
+        else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  creditCode: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.subjectType !== "01" && form.subjectType !== "07") return cb();
+        const v = String(form.creditCode || "").trim();
+        if (!v) {
+          cb(new Error(form.subjectType === "07" ? "请输入营业执照编号" : "请输入营业执照号"));
+        } else if (v.length < 15 || v.length > 32) cb(new Error("长度一般为 18 位统一社会信用代码"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  householdLicenseName: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.subjectType !== "07") return cb();
+        if (!String(form.householdLicenseName || "").trim()) cb(new Error("请输入营业执照名称"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  merchantShortName: [
+    {
+      validator: (_r, _v, cb) => {
+        if (!["01", "02", "03", "04", "05", "06", "07"].includes(form.subjectType)) return cb();
+        if (!String(form.merchantShortName || "").trim()) cb(new Error("请输入商户简称"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  institutionCertUrl: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.subjectType !== "institution") return cb();
+        if (!String(form.institutionCertUrl || "").trim()) cb(new Error("请上传事业单位法人证书"));
+        else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  institutionCertNumber: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.subjectType !== "institution") return cb();
+        if (!String(form.institutionCertNumber || "").trim()) cb(new Error("请输入事业单位法人证书编号"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  otherOrgCertUrl: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.subjectType !== "other_org") return cb();
+        if (!String(form.otherOrgCertUrl || "").trim()) cb(new Error("请上传民办非企业单位登记证书"));
+        else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  otherOrgCertNumber: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.subjectType !== "other_org") return cb();
+        if (!String(form.otherOrgCertNumber || "").trim()) cb(new Error("请输入民办非企业单位登记证书编号"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  socialCertUrl: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.subjectType !== "social") return cb();
+        if (!String(form.socialCertUrl || "").trim()) cb(new Error("请上传社会团体法人登记证书"));
+        else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  socialCertNumber: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.subjectType !== "social") return cb();
+        if (!String(form.socialCertNumber || "").trim()) cb(new Error("请输入社会团体法人登记证书编号"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  govCertUrl: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.subjectType !== "gov") return cb();
+        if (!String(form.govCertUrl || "").trim()) {
+          cb(new Error("请上传党政机关批准设立文件/行政执法主体资格证"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  govCertNumber: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.subjectType !== "gov") return cb();
+        if (!String(form.govCertNumber || "").trim()) {
+          cb(new Error("请输入党政机关批准设立文件/行政执法主体资格证编号"));
+        } else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  businessCategory: [
+    {
+      validator: (_r, _v, cb) => {
+        if (!["01", "02", "03", "04", "05", "06", "07"].includes(form.subjectType)) return cb();
+        const bc = form.businessCategory;
+        if (!Array.isArray(bc) || bc.length < 2 || !String(bc[0] || "").trim() || !String(bc[1] || "").trim()) {
+          cb(new Error("请选择经营类目(需选择到二级分类)"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  legalIdType: [
+    {
+      validator: (_r, _v, cb) => {
+        if (!["01", "institution", "other_org", "social"].includes(form.subjectType)) return cb();
+        if (!String(form.legalIdType || "").trim()) cb(new Error("请选择证件类型"));
+        else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  idFrontUrl: [
+    {
+      validator: (_r, _v, cb) => {
+        if (!["01", "institution", "other_org", "social", "individual_merchant"].includes(form.subjectType)) return cb();
+        if (!String(form.idFrontUrl || "").trim()) {
+          cb(new Error(form.subjectType === "individual_merchant" ? "请上传身份证人像面" : "请上传证件正面"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  idBackUrl: [
+    {
+      validator: (_r, _v, cb) => {
+        if (!["01", "institution", "other_org", "social", "individual_merchant"].includes(form.subjectType)) return cb();
+        if (!String(form.idBackUrl || "").trim()) {
+          cb(new Error(form.subjectType === "individual_merchant" ? "请上传身份证国徽面" : "请上传证件反面"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  idNumber: [
+    {
+      validator: (_r, _v, cb) => {
+        if (!["01", "institution", "other_org", "social", "individual_merchant"].includes(form.subjectType)) return cb();
+        if (!String(form.idNumber || "").trim()) {
+          cb(new Error(form.subjectType === "individual_merchant" ? "请输入个人身份证号码" : "请输入证件号"));
+        } else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  legalName: [
+    {
+      validator: (_r, _v, cb) => {
+        if (!["01", "institution", "other_org", "social"].includes(form.subjectType)) return cb();
+        if (!String(form.legalName || "").trim()) cb(new Error("请输入法定代表人/负责人姓名"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  storefrontUrl: [{ required: true, message: "请上传门头照", trigger: "change" }],
+  interiorUrl: [{ required: true, message: "请上传内景照", trigger: "change" }],
+  region: [{ type: "array", required: true, min: 2, message: "请选择省、市", trigger: "change" }],
+  detailAddress: [{ required: true, message: "请输入详细地址", trigger: "blur" }],
+  contactName: [{ required: true, message: "请输入联系人姓名", trigger: "blur" }],
+  contactPhone: [
+    { required: true, message: "请输入联系人手机号", trigger: "blur" },
+    { pattern: /^1\d{10}$/, message: "请输入有效手机号", trigger: "blur" }
+  ],
+  contactEmail: [
+    { required: true, message: "请输入联系人邮箱", trigger: "blur" },
+    { type: "email", message: "邮箱格式不正确", trigger: "blur" }
+  ],
+  servicePhone: [
+    { required: true, message: "请输入客服电话", trigger: "blur" },
+    { pattern: /^[\d\-+\s]{5,20}$/, message: "请输入有效电话号码", trigger: "blur" }
+  ],
+  settlementAlipayAccount: [{ required: true, message: "请输入签约支付宝账号", trigger: "blur" }]
+};
+
+async function onNext() {
+  if (!formRef.value) return;
+  nextLoading.value = true;
+  try {
+    localSet(ALIPAY_JSON_KEY, buildAlipayJsonPayload());
+    await router.push({ path: "/businessInfo/zfbIndexTwo", query: { ...route.query } });
+  } catch {
+    ElMessage.warning("请完善必填信息");
+  } finally {
+    nextLoading.value = false;
+  }
+}
+</script>
+
+<style scoped lang="scss">
+$zfb-blue: #1677ff;
+.zfb-step-page {
+  box-sizing: border-box;
+  min-height: 100%;
+  padding: 24px 24px 48px;
+  margin: 0 auto;
+  background: #ffffff;
+}
+.step-header {
+  margin-right: -24px;
+  margin-bottom: 28px;
+  margin-left: -24px;
+}
+.zfb-steps {
+  width: 100%;
+  margin: 0;
+}
+.step-header :deep(.zfb-steps.el-steps--horizontal) {
+  .el-step__icon {
+    width: 36px;
+    height: 36px;
+    font-size: 16px;
+    font-weight: 600;
+    background: #ffffff !important;
+  }
+  .el-step__head.is-process .el-step__icon {
+    color: #ffffff !important;
+    background: #1677ff !important;
+    border-color: $zfb-blue !important;
+  }
+  .el-step__head.is-wait .el-step__icon {
+    color: #c0c4cc !important;
+    background: #ffffff !important;
+    border: 2px solid #dcdfe6 !important;
+  }
+  .el-step__head.is-finish .el-step__icon {
+    color: #ffffff !important;
+    background: $zfb-blue !important;
+    border-color: $zfb-blue !important;
+  }
+  .el-step__line {
+    background-color: #e4e7ed !important;
+  }
+  .el-step__line-inner {
+    border-width: 1px !important;
+  }
+  .el-step__title {
+    font-size: 14px;
+    line-height: 36px;
+    color: #606266;
+  }
+  .el-step__head.is-process + .el-step__main .el-step__title {
+    font-weight: 600;
+    color: #303133;
+  }
+  .el-step__head.is-wait + .el-step__main .el-step__title {
+    color: #c0c4cc;
+  }
+  .el-step__head.is-finish + .el-step__main .el-step__title {
+    font-weight: 500;
+    color: #606266;
+  }
+}
+.page-layout {
+  display: flex;
+  gap: 32px;
+  align-items: flex-start;
+}
+.main-column {
+  flex: 1;
+  min-width: 0;
+
+  /* 滚到底时 max(scrollTop) 往往仍小于「经营信息」的锚点判定线,侧栏会一直停在前一节;底部留白增大可滚动距离 */
+  padding-bottom: clamp(140px, 22vh, 400px);
+}
+.anchor-column {
+  flex-shrink: 0;
+  width: 160px;
+}
+.anchor-card {
+  padding: 16px 12px;
+}
+:deep(.el-anchor__list) {
+  border-left: 1px solid #ebeef5;
+}
+.anchor-title {
+  margin-bottom: 12px;
+  font-size: 13px;
+  font-weight: 600;
+  color: #303133;
+}
+.zfb-form {
+  :deep(.el-form-item__label) {
+    font-weight: 500;
+    color: #606266;
+  }
+}
+.form-block {
+  padding-bottom: 8px;
+  margin-bottom: 28px;
+  scroll-margin-top: 72px;
+  border-bottom: 1px solid #ebeef5;
+  &:last-of-type {
+    border-bottom: none;
+  }
+}
+.section-head {
+  display: flex;
+  align-items: center;
+  margin: 0 0 16px;
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+}
+.section-bar {
+  display: inline-block;
+  flex-shrink: 0;
+  width: 4px;
+  height: 16px;
+  margin-right: 8px;
+  background: $zfb-blue;
+  border-radius: 2px;
+}
+.radio-stack {
+  display: flex;
+  gap: 10px;
+  align-items: flex-start;
+}
+.label-with-icon {
+  display: inline-flex;
+  gap: 4px;
+  align-items: center;
+}
+.label-wrap-multiline {
+  display: inline-block;
+  max-width: 196px;
+  line-height: 1.45;
+  white-space: normal;
+  vertical-align: middle;
+}
+.individual-merchant-alert {
+  max-width: 410px;
+  margin-bottom: 20px;
+  margin-left: 200px;
+}
+.info-icon {
+  color: #909399;
+  cursor: help;
+}
+.license-upload-wrap {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 16px;
+  align-items: flex-start;
+}
+.license-example {
+  display: flex;
+  flex-direction: column;
+  gap: 6px;
+}
+.license-example-label {
+  font-size: 12px;
+  color: #909399;
+}
+.license-example-thumb {
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 148px;
+  height: 148px;
+  overflow: hidden;
+  background: #f5f7fa;
+  border: 1px dashed #dcdfe6;
+  border-radius: 6px;
+}
+.license-example-placeholder {
+  font-size: 12px;
+  color: #c0c4cc;
+}
+.id-example-thumb {
+  position: relative;
+}
+.license-example-badge {
+  position: absolute;
+  top: 6px;
+  right: 6px;
+  padding: 2px 6px;
+  font-size: 11px;
+  color: #ffffff;
+  background: rgb(0 0 0 / 45%);
+  border-radius: 4px;
+}
+.id-upload-row {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 24px;
+}
+.id-upload-cell {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+.id-upload-trigger {
+  display: flex;
+  flex-direction: column;
+  gap: 6px;
+  align-items: center;
+  justify-content: center;
+  line-height: 1.2;
+}
+.id-side-label {
+  margin-top: 10px;
+  font-size: 13px;
+  color: #606266;
+}
+.id-upload-trigger .id-side-label {
+  font-size: 12px;
+  line-height: 1.3;
+  text-align: center;
+}
+.upload-rules {
+  margin-top: 12px;
+  font-size: 12px;
+  line-height: 1.65;
+  color: #909399;
+  p {
+    margin: 0;
+  }
+}
+.field-stack {
+  width: 100%;
+}
+.field-tip {
+  margin: 8px 0 0;
+  font-size: 12px;
+  line-height: 1.65;
+  color: #909399;
+}
+.service-checks {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px 20px;
+}
+.address-row {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px;
+  align-items: center;
+  width: 100%;
+  max-width: 720px;
+}
+.address-detail {
+  flex: 1;
+  min-width: 200px;
+}
+.footer-actions {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 16px;
+  align-items: center;
+  justify-content: center;
+  padding-top: 24px;
+  margin-top: 8px;
+  border-top: 1px solid #ebeef5;
+}
+.btn-primary-zfb {
+  min-width: 120px;
+  background: $zfb-blue;
+  border-color: $zfb-blue;
+  &:hover {
+    background: #4096ff;
+    border-color: #4096ff;
+  }
+}
+:deep(.el-upload--picture-card) {
+  --el-upload-picture-card-size: 148px;
+}
+:deep(.el-upload-list--picture-card .el-upload-list__item) {
+  width: 148px;
+  height: 148px;
+}
+:deep(.el-form-item__content) {
+  display: block;
+}
+:deep(.anchor-card .el-anchor) {
+  /* 实际滚动在 layout 的 el-main 上,不设 container 时监听 window,高亮不会随滚动更新 */
+  --el-anchor-color: #606266;
+  --el-anchor-active-color: #{$zfb-blue};
+  --el-anchor-marker-bg-color: #{$zfb-blue};
+
+  background: transparent;
+}
+:deep(.anchor-card .el-anchor__link) {
+  padding: 6px 0;
+  font-size: 13px;
+}
+:deep(.anchor-card .el-anchor__link.is-active) {
+  font-weight: 600;
+}
+</style>

+ 928 - 0
src/views/businessInfo/zfbIndexTwo.vue

@@ -0,0 +1,928 @@
+<template>
+  <div class="zfb-step-page">
+    <header class="step-header">
+      <el-steps :active="zfbStepActive" align-center finish-status="success" class="zfb-steps">
+        <el-step title="第一步 完善商家信息" />
+        <el-step title="第二步 完善结算信息" />
+        <el-step title="第三步 提交审核" />
+      </el-steps>
+    </header>
+
+    <div class="page-layout">
+      <div class="main-column">
+        <el-form
+          ref="formRef"
+          class="zfb-form"
+          :model="form"
+          :rules="rules"
+          label-width="200px"
+          require-asterisk-position="right"
+          label-position="right"
+        >
+          <section id="zfb-settlement" class="form-block anchor-section">
+            <h2 class="section-head">
+              <span class="section-bar" aria-hidden="true" />
+              结算信息
+            </h2>
+
+            <el-form-item label="请选择结算方式" prop="settlementMethod">
+              <el-radio-group v-model="form.settlementMethod" class="radio-stack">
+                <el-radio value="alipay"> 结算到支付宝 </el-radio>
+                <el-radio value="bank"> 结算到银行卡 </el-radio>
+              </el-radio-group>
+            </el-form-item>
+
+            <template v-if="form.settlementMethod === 'alipay'">
+              <el-form-item label="支付宝账号" prop="alipayAccount">
+                <el-input v-model="form.alipayAccount" placeholder="请输入支付宝账号" clearable style="max-width: 480px" />
+                <el-alert class="settlement-tip-alert" type="info" :closable="false" show-icon>
+                  注:账号主体名称需与营业执照同名
+                </el-alert>
+              </el-form-item>
+            </template>
+
+            <template v-if="form.settlementMethod === 'bank'">
+              <el-form-item label="开户名称" prop="bankAccountName" required>
+                <el-input v-model="form.bankAccountName" clearable maxlength="64" style="max-width: 480px" />
+              </el-form-item>
+              <el-form-item label="银行卡号" prop="bankCardNo" required>
+                <el-input
+                  v-model="form.bankCardNo"
+                  placeholder="暂时只支持借记卡"
+                  clearable
+                  maxlength="24"
+                  style="max-width: 480px"
+                />
+              </el-form-item>
+              <el-form-item label="联行号" prop="cnapsCode">
+                <el-input v-model="form.cnapsCode" placeholder="非必填" clearable maxlength="32" style="max-width: 480px" />
+              </el-form-item>
+              <el-form-item prop="bankBranch">
+                <template #label>
+                  <span class="bank-branch-required-label">开户银行</span>
+                </template>
+                <div class="bank-select-row">
+                  <el-select
+                    v-model="form.depositBankCode"
+                    placeholder="请选择开户银行"
+                    clearable
+                    filterable
+                    class="bank-select-cell"
+                    @change="onDepositBankChange"
+                  >
+                    <el-option v-for="b in depositBankOptions" :key="b.value" :label="b.label" :value="b.value" />
+                  </el-select>
+                  <el-cascader
+                    v-model="form.branchRegion"
+                    :options="invoiceRegionCascaderOptions"
+                    :props="{ emitPath: true }"
+                    placeholder="请选择省 / 市"
+                    clearable
+                    filterable
+                    class="bank-select-cell bank-region-cascader"
+                    @change="onBranchRegionChange"
+                  />
+                  <el-input
+                    v-model="form.branchName"
+                    placeholder="请输入支行名称"
+                    clearable
+                    maxlength="80"
+                    class="bank-select-cell bank-branch-input"
+                    :disabled="!branchRegionCitySelected"
+                    @blur="touchBankBranchValidate"
+                    @clear="touchBankBranchValidate"
+                  />
+                </div>
+              </el-form-item>
+              <el-form-item label="账号使用类型" prop="accountUsageType" required>
+                <el-radio-group v-model="form.accountUsageType" class="radio-stack" disabled>
+                  <el-radio value="public"> 对公 </el-radio>
+                  <el-radio value="private"> 对私 </el-radio>
+                </el-radio-group>
+              </el-form-item>
+            </template>
+
+            <!-- <el-form-item label="是否开票" prop="needInvoicing">
+              <el-radio-group v-model="form.needInvoicing" class="radio-stack">
+                <el-radio value="yes">是</el-radio>
+                <el-radio value="no">否</el-radio>
+              </el-radio-group>
+            </el-form-item> -->
+
+            <!-- <template v-if="form.needInvoicing === 'yes'">
+              <div id="zfb-invoice" class="invoice-extra-wrap anchor-section">
+                <div class="invoice-section-divider" />
+
+                <el-form-item label="纳税人种类" prop="taxpayerType" required>
+                  <el-radio-group v-model="form.taxpayerType" class="radio-stack">
+                    <el-radio value="general">一般纳税人</el-radio>
+                    <el-radio value="small_scale">小规模纳税人</el-radio>
+                  </el-radio-group>
+                </el-form-item>
+
+                <div class="invoice-section-divider" />
+                <h3 class="invoice-subsection-title">开票信息</h3>
+
+                <el-form-item label="发票抬头" prop="invoiceTitle" required>
+                  <el-input v-model="form.invoiceTitle" clearable maxlength="128" style="max-width: 480px" />
+                </el-form-item>
+                <el-form-item label="纳税人识别号" prop="taxpayerIdNo" required>
+                  <el-input v-model="form.taxpayerIdNo" clearable maxlength="32" style="max-width: 480px" />
+                </el-form-item>
+                <el-form-item label="纳税人资格开始时间" prop="qualificationStartDate" required>
+                  <el-date-picker
+                    v-model="form.qualificationStartDate"
+                    type="date"
+                    placeholder="请选择日期"
+                    value-format="YYYY-MM-DD"
+                    style="width: 320px; max-width: 100%"
+                    clearable
+                    @change="touchQualificationDateValidate"
+                  />
+                </el-form-item>
+                <template v-if="form.taxpayerType === 'general'">
+                  <el-form-item label="开票地址" prop="invoiceAddress" required>
+                    <el-input v-model="form.invoiceAddress" clearable maxlength="200" style="max-width: 480px" />
+                  </el-form-item>
+                  <el-form-item label="开票电话" prop="invoicePhone" required>
+                    <el-input v-model="form.invoicePhone" clearable maxlength="20" style="max-width: 480px" />
+                  </el-form-item>
+                  <el-form-item label="银行卡号" prop="invoiceBankCardNo" required>
+                    <el-input v-model="form.invoiceBankCardNo" clearable maxlength="24" style="max-width: 480px" />
+                  </el-form-item>
+                  <el-form-item label="开户银行" prop="invoiceOpeningBank" required>
+                    <el-input v-model="form.invoiceOpeningBank" clearable maxlength="64" style="max-width: 480px" />
+                  </el-form-item>
+                </template>
+
+                <div id="zfb-invoice-mail" class="invoice-section-divider" />
+                <h3 class="invoice-subsection-title">发票寄送信息</h3>
+
+                <el-form-item label="发票寄送地址" prop="invoiceMailSuite" required>
+                  <div class="mail-address-stack">
+                    <el-cascader
+                      v-model="form.invoiceMailRegion"
+                      :options="invoiceRegionCascaderOptions"
+                      :placeholder="
+                        form.taxpayerType === 'small_scale' ? '请输入具体门牌号等' : '请选择省 / 市'
+                      "
+                      filterable
+                      clearable
+                      class="mail-cascader"
+                      @change="touchInvoiceMailSuiteValidate"
+                    />
+                    <el-input
+                      v-model="form.invoiceMailAddressDetail"
+                      placeholder="请输入具体门牌号等"
+                      clearable
+                      maxlength="200"
+                      class="mail-detail-input"
+                      @blur="touchInvoiceMailSuiteValidate"
+                    />
+                  </div>
+                </el-form-item>
+                <el-form-item label="收件人姓名" prop="invoiceRecipientName" required>
+                  <el-input v-model="form.invoiceRecipientName" clearable maxlength="32" style="max-width: 480px" />
+                </el-form-item>
+                <el-form-item label="收件人手机号" prop="invoiceRecipientPhone" required>
+                  <el-input v-model="form.invoiceRecipientPhone" clearable maxlength="11" style="max-width: 480px" />
+                </el-form-item>
+              </div>
+            </template> -->
+          </section>
+        </el-form>
+
+        <div class="footer-actions">
+          <el-button type="primary" class="btn-primary-zfb" :loading="submitLoading" @click="onConfirmSubmit">
+            确认提交
+          </el-button>
+        </div>
+      </div>
+
+      <aside class="anchor-column">
+        <el-affix :offset="88">
+          <div class="anchor-card">
+            <el-anchor :offset="72" direction="vertical">
+              <el-anchor-link href="#zfb-settlement" title="结算信息" />
+              <el-anchor-link v-if="form.needInvoicing === 'yes'" href="#zfb-invoice" title="开票信息" />
+              <el-anchor-link v-if="form.needInvoicing === 'yes'" href="#zfb-invoice-mail" title="发票寄送" />
+            </el-anchor>
+          </div>
+        </el-affix>
+      </aside>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed, nextTick, onMounted, reactive, ref, watch } from "vue";
+import { ElMessage } from "element-plus";
+import type { FormInstance, FormRules } from "element-plus";
+import { localGet, localSet } from "@/utils/index";
+import { getAlipayZftCreate } from "@/api/modules/businessInfo";
+import cityJson from "@/assets/json/city.json";
+
+type CityJsonEntry = { name: string; adCode: string; cityCode: string };
+type CityJsonRoot = { cityList: { letter: string; list: CityJsonEntry[] }[] };
+
+const PROVINCE_ROWS: [string, string][] = [
+  ["11", "北京市"],
+  ["12", "天津市"],
+  ["13", "河北省"],
+  ["14", "山西省"],
+  ["15", "内蒙古自治区"],
+  ["21", "辽宁省"],
+  ["22", "吉林省"],
+  ["23", "黑龙江省"],
+  ["31", "上海市"],
+  ["32", "江苏省"],
+  ["33", "浙江省"],
+  ["34", "安徽省"],
+  ["35", "福建省"],
+  ["36", "江西省"],
+  ["37", "山东省"],
+  ["41", "河南省"],
+  ["42", "湖北省"],
+  ["43", "湖南省"],
+  ["44", "广东省"],
+  ["45", "广西壮族自治区"],
+  ["46", "海南省"],
+  ["50", "重庆市"],
+  ["51", "四川省"],
+  ["52", "贵州省"],
+  ["53", "云南省"],
+  ["54", "西藏自治区"],
+  ["61", "陕西省"],
+  ["62", "甘肃省"],
+  ["63", "青海省"],
+  ["64", "宁夏回族自治区"],
+  ["65", "新疆维吾尔自治区"],
+  ["71", "台湾省"],
+  ["81", "香港特别行政区"],
+  ["82", "澳门特别行政区"]
+];
+const PROVINCE_BY_PREFIX = Object.fromEntries(PROVINCE_ROWS) as Record<string, string>;
+const PROVINCE_PREFIX_ORDER = PROVINCE_ROWS.map(([k]) => k);
+
+function buildProvinceCityOptions(): {
+  label: string;
+  value: string;
+  cities: { label: string; value: string }[];
+}[] {
+  const root = cityJson as CityJsonRoot;
+  const flat = root.cityList.flatMap(g => g.list);
+  const bucket = new Map<string, Map<string, CityJsonEntry>>();
+  for (const c of flat) {
+    const digits = String(c.adCode ?? "").replace(/\D/g, "");
+    const code = digits.length >= 6 ? digits.slice(-6) : digits.padStart(6, "0");
+    if (code.length !== 6) continue;
+    const prefix = code.slice(0, 2);
+    if (!PROVINCE_BY_PREFIX[prefix]) continue;
+    if (!bucket.has(prefix)) bucket.set(prefix, new Map());
+    bucket.get(prefix)!.set(c.adCode, c);
+  }
+  const out = [...bucket.entries()].map(([prefix, cityMap]) => ({
+    value: prefix,
+    label: PROVINCE_BY_PREFIX[prefix],
+    cities: [...cityMap.values()]
+      .sort((a, b) => a.name.localeCompare(b.name, "zh-CN"))
+      .map(ci => ({ label: ci.name, value: ci.adCode }))
+  }));
+  out.sort((a, b) => {
+    const ia = PROVINCE_PREFIX_ORDER.indexOf(a.value);
+    const ib = PROVINCE_PREFIX_ORDER.indexOf(b.value);
+    return (ia === -1 ? 999 : ia) - (ib === -1 ? 999 : ib);
+  });
+  return out;
+}
+
+const provinceCityOptions = buildProvinceCityOptions();
+
+const invoiceRegionCascaderOptions = computed(() =>
+  provinceCityOptions.map(p => ({
+    value: p.value,
+    label: p.label,
+    children: p.cities.map(c => ({ value: c.value, label: c.label }))
+  }))
+);
+
+const depositBankOptions = [
+  { label: "工商银行", value: "ICBC" },
+  { label: "农业银行", value: "ABC" },
+  { label: "中国银行", value: "BOC" },
+  { label: "建设银行", value: "CCB" },
+  { label: "交通银行", value: "COMM" },
+  { label: "邮储银行", value: "PSBC" },
+  { label: "招商银行", value: "CMB" },
+  { label: "浦发银行", value: "SPDB" },
+  { label: "兴业银行", value: "CIB" },
+  { label: "民生银行", value: "CMBC" },
+  { label: "华夏银行", value: "HXB" },
+  { label: "广发银行", value: "GDB" },
+  { label: "平安银行", value: "PAB" },
+  { label: "中信银行", value: "CITIC" },
+  { label: "光大银行", value: "CEB" },
+  { label: "上海银行", value: "BOSH" },
+  { label: "北京银行", value: "BRCB" },
+  { label: "其他银行", value: "OTHER" }
+];
+
+const formRef = ref<FormInstance>();
+const submitLoading = ref(false);
+
+/** 第二步:索引为 1 */
+const zfbStepActive = ref(1);
+
+const form = reactive({
+  settlementMethod: "alipay" as "alipay" | "bank",
+  alipayAccount: "",
+  bankAccountName: "",
+  bankCardNo: "",
+  cnapsCode: "",
+  /** 联表校验占位,不绑定输入 */
+  bankBranch: "",
+  depositBankCode: "",
+  /** 支行地区 [省前缀, 市 adCode],与第一步店铺地址级联一致 */
+  branchRegion: [] as string[],
+  branchName: "",
+  accountUsageType: "public" as "public" | "private",
+  needInvoicing: "no" as "yes" | "no",
+  taxpayerType: "general" as "general" | "small_scale",
+  invoiceTitle: "",
+  taxpayerIdNo: "",
+  qualificationStartDate: "" as string,
+  invoiceAddress: "",
+  invoicePhone: "",
+  invoiceBankCardNo: "",
+  invoiceOpeningBank: "",
+  /** 级联 [省前缀, 市 adCode] */
+  invoiceMailRegion: [] as string[],
+  invoiceMailAddressDetail: "",
+  /** 发票寄送地址联校占位 */
+  invoiceMailSuite: "",
+  invoiceRecipientName: "",
+  invoiceRecipientPhone: ""
+});
+
+/** 已选省、市后可填写支行名称 */
+const branchRegionCitySelected = computed(
+  () => Array.isArray(form.branchRegion) && form.branchRegion.length >= 2 && !!String(form.branchRegion[1] || "").trim()
+);
+
+function touchBankBranchValidate() {
+  nextTick(() => formRef.value?.validateField("bankBranch"));
+}
+
+function onDepositBankChange() {
+  form.branchRegion = [];
+  form.branchName = "";
+  touchBankBranchValidate();
+}
+
+function onBranchRegionChange() {
+  form.branchName = "";
+  touchBankBranchValidate();
+}
+
+function touchInvoiceMailSuiteValidate() {
+  nextTick(() => formRef.value?.validateField("invoiceMailSuite"));
+}
+
+function touchQualificationDateValidate() {
+  nextTick(() => formRef.value?.validateField("qualificationStartDate"));
+}
+
+const rules: FormRules = {
+  settlementMethod: [{ required: true, message: "请选择结算方式", trigger: "change" }],
+  alipayAccount: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.settlementMethod !== "alipay") return cb();
+        if (!String(form.alipayAccount || "").trim()) cb(new Error("请输入支付宝账号"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  bankAccountName: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.settlementMethod !== "bank") return cb();
+        if (!String(form.bankAccountName || "").trim()) cb(new Error("请输入开户名称"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  bankCardNo: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.settlementMethod !== "bank") return cb();
+        const v = String(form.bankCardNo || "")
+          .replace(/\s+/g, "")
+          .trim();
+        if (!v) cb(new Error("请输入银行卡号"));
+        else if (!/^\d{16,24}$/.test(v)) cb(new Error("请输入正确的借记卡卡号(16~24 位数字)"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  cnapsCode: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.settlementMethod !== "bank") return cb();
+        const v = String(form.cnapsCode || "").trim();
+        if (!v) return cb();
+        if (!/^\d{8,14}$/.test(v)) cb(new Error("联行号格式不正确"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  bankBranch: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.settlementMethod !== "bank") return cb();
+        if (!form.depositBankCode) cb(new Error("请选择开户银行"));
+        else if (!Array.isArray(form.branchRegion) || form.branchRegion.length < 2) {
+          cb(new Error("请选择支行地区(省、市)"));
+        } else if (!String(form.branchName || "").trim()) cb(new Error("请输入支行名称"));
+        else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  accountUsageType: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.settlementMethod !== "bank") return cb();
+        if (form.accountUsageType !== "public" && form.accountUsageType !== "private") {
+          cb(new Error("请选择账号使用类型"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  needInvoicing: [{ required: true, message: "请选择是否开票", trigger: "change" }],
+  taxpayerType: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.needInvoicing !== "yes") return cb();
+        if (form.taxpayerType !== "general" && form.taxpayerType !== "small_scale") {
+          cb(new Error("请选择纳税人种类"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  invoiceTitle: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.needInvoicing !== "yes") return cb();
+        if (!String(form.invoiceTitle || "").trim()) cb(new Error("请输入发票抬头"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  taxpayerIdNo: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.needInvoicing !== "yes") return cb();
+        const v = String(form.taxpayerIdNo || "")
+          .trim()
+          .toUpperCase();
+        if (!v) cb(new Error("请输入纳税人识别号"));
+        else if (v.length < 15 || v.length > 20) cb(new Error("纳税人识别号长度应为 15~20 位"));
+        else if (!/^[0-9A-Z]+$/.test(v)) cb(new Error("纳税人识别号仅含数字与字母"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  qualificationStartDate: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.needInvoicing !== "yes") return cb();
+        if (!String(form.qualificationStartDate || "").trim()) cb(new Error("请选择纳税人资格开始时间"));
+        else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  invoiceAddress: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.needInvoicing !== "yes" || form.taxpayerType !== "general") return cb();
+        if (!String(form.invoiceAddress || "").trim()) cb(new Error("请输入开票地址"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  invoicePhone: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.needInvoicing !== "yes" || form.taxpayerType !== "general") return cb();
+        const v = String(form.invoicePhone || "").trim();
+        if (!v) cb(new Error("请输入开票电话"));
+        else if (!/^[\d\-+\s]{5,20}$/.test(v)) cb(new Error("请输入有效的开票电话"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  invoiceBankCardNo: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.needInvoicing !== "yes" || form.taxpayerType !== "general") return cb();
+        const v = String(form.invoiceBankCardNo || "")
+          .replace(/\s+/g, "")
+          .trim();
+        if (!v) cb(new Error("请输入银行卡号"));
+        else if (!/^\d{16,24}$/.test(v)) cb(new Error("请输入正确的银行卡号(16~24 位数字)"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  invoiceOpeningBank: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.needInvoicing !== "yes" || form.taxpayerType !== "general") return cb();
+        if (!String(form.invoiceOpeningBank || "").trim()) cb(new Error("请输入开户银行"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  invoiceMailSuite: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.needInvoicing !== "yes") return cb();
+        const reg = form.invoiceMailRegion;
+        if (!Array.isArray(reg) || reg.length < 2 || !String(reg[0] || "").trim() || !String(reg[1] || "").trim()) {
+          cb(new Error("请选择发票寄送省/市"));
+        } else if (!String(form.invoiceMailAddressDetail || "").trim()) {
+          cb(new Error("请输入具体门牌号等"));
+        } else cb();
+      },
+      trigger: "change"
+    }
+  ],
+  invoiceRecipientName: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.needInvoicing !== "yes") return cb();
+        if (!String(form.invoiceRecipientName || "").trim()) cb(new Error("请输入收件人姓名"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ],
+  invoiceRecipientPhone: [
+    {
+      validator: (_r, _v, cb) => {
+        if (form.needInvoicing !== "yes") return cb();
+        const v = String(form.invoiceRecipientPhone || "").trim();
+        if (!v) cb(new Error("请输入收件人手机号"));
+        else if (!/^1\d{10}$/.test(v)) cb(new Error("请输入正确的手机号"));
+        else cb();
+      },
+      trigger: "blur"
+    }
+  ]
+};
+
+const ALIPAY_JSON_KEY = "alipayJson";
+
+/** 结算到银行卡时写入 alipayJson.bizCards[](与直付通字段约定一致) */
+type AlipayBizCardPayload = {
+  accountHolderName: string;
+  accountNo: string;
+  accountInstProvince: string;
+  accountInstCity: string;
+  accountBranchName: string;
+  /** 对公 01,对私 02 */
+  usageType: string;
+  accountType: "DC";
+  accountInstName: string;
+  /** 开户行缩写,与 depositBankCode 一致(如 ICBC) */
+  accountInstId: string;
+};
+
+/** 由支行地区级联 [省前缀, 市 adCode] 解析省名、市名 */
+function resolveBranchRegionProvinceCity(): { province: string; city: string } {
+  const reg = form.branchRegion;
+  if (!Array.isArray(reg) || reg.length < 2) return { province: "", city: "" };
+  const prov = provinceCityOptions.find(p => p.value === reg[0]);
+  const cityAd = String(reg[1] || "").trim();
+  const city = prov?.cities.find(c => c.value === cityAd);
+  return {
+    province: prov?.label ?? "",
+    city: city?.label ?? ""
+  };
+}
+
+function buildBizCardsForPayload(): AlipayBizCardPayload[] {
+  if (form.settlementMethod !== "bank") return [];
+  const bankMeta = depositBankOptions.find(b => b.value === form.depositBankCode);
+  const { province, city } = resolveBranchRegionProvinceCity();
+  const usageType = form.accountUsageType === "public" ? "01" : "02";
+  return [
+    {
+      accountHolderName: String(form.bankAccountName || "").trim(),
+      accountNo: String(form.bankCardNo || "")
+        .replace(/\s+/g, "")
+        .trim(),
+      accountInstProvince: province,
+      accountInstCity: city,
+      accountBranchName: String(form.branchName || "").trim(),
+      usageType,
+      accountType: "DC",
+      accountInstName: bankMeta?.label ?? "",
+      accountInstId: String(form.depositBankCode || "").trim()
+    }
+  ];
+}
+
+async function onConfirmSubmit() {
+  if (!formRef.value) return;
+  submitLoading.value = true;
+  try {
+    await formRef.value.validate();
+  } catch {
+    ElMessage.warning("请完善必填信息");
+    submitLoading.value = false;
+    return;
+  }
+  try {
+    const alipayJson = localGet(ALIPAY_JSON_KEY) as Record<string, unknown> | null | undefined;
+    if (!alipayJson || typeof alipayJson !== "object" || Array.isArray(alipayJson)) {
+      ElMessage.warning("缺少步骤一提交数据,请先完成主体信息并点击下一步");
+      return;
+    }
+    const payload: Record<string, unknown> = { ...alipayJson };
+    const alipayLogonId =
+      form.settlementMethod === "alipay" ? String(form.alipayAccount || "").trim() : String(payload.alipayLogonId ?? "").trim();
+    payload.alipayLogonId = alipayLogonId;
+
+    if (form.settlementMethod === "bank") {
+      payload.bizCards = buildBizCardsForPayload();
+    } else {
+      delete payload.bizCards;
+    }
+
+    localSet(ALIPAY_JSON_KEY, payload);
+    await getAlipayZftCreate(payload);
+    ElMessage.success("提交成功");
+  } catch {
+    ElMessage.error("提交失败,请稍后重试");
+  } finally {
+    submitLoading.value = false;
+  }
+}
+
+const invoiceFieldProps = [
+  "taxpayerType",
+  "invoiceTitle",
+  "taxpayerIdNo",
+  "qualificationStartDate",
+  "invoiceAddress",
+  "invoicePhone",
+  "invoiceBankCardNo",
+  "invoiceOpeningBank",
+  "invoiceMailSuite",
+  "invoiceRecipientName",
+  "invoiceRecipientPhone"
+] as const;
+
+watch(
+  () => form.settlementMethod,
+  v => {
+    if (v === "bank") form.accountUsageType = "public";
+    nextTick(() => {
+      formRef.value?.clearValidate([
+        "alipayAccount",
+        "bankAccountName",
+        "bankCardNo",
+        "cnapsCode",
+        "bankBranch",
+        "accountUsageType"
+      ]);
+    });
+  }
+);
+
+watch(
+  () => form.needInvoicing,
+  v => {
+    nextTick(() => {
+      if (v !== "yes") {
+        formRef.value?.clearValidate([...invoiceFieldProps]);
+      }
+    });
+  }
+);
+
+const generalTaxpayerInvoiceExtraProps = ["invoiceAddress", "invoicePhone", "invoiceBankCardNo", "invoiceOpeningBank"] as const;
+
+watch(
+  () => form.taxpayerType,
+  () => {
+    if (form.needInvoicing !== "yes") return;
+    nextTick(() => {
+      formRef.value?.clearValidate([...generalTaxpayerInvoiceExtraProps]);
+    });
+  }
+);
+
+onMounted(() => {
+  formRef.value?.clearValidate();
+});
+</script>
+
+<style scoped lang="scss">
+$zfb-blue: #1677ff;
+.zfb-step-page {
+  box-sizing: border-box;
+  min-height: 100%;
+  padding: 24px 32px 48px;
+  background: #ffffff;
+}
+.step-header {
+  max-width: 960px;
+  margin: 0 auto 32px;
+}
+.zfb-steps {
+  :deep(.el-step__head.is-process) {
+    color: $zfb-blue;
+    border-color: $zfb-blue;
+  }
+  :deep(.el-step__head.is-finish) {
+    color: $zfb-blue;
+    border-color: $zfb-blue;
+  }
+  :deep(.el-step__title.is-process) {
+    font-weight: 600;
+    color: $zfb-blue;
+  }
+  :deep(.el-step__title.is-finish) {
+    font-weight: 500;
+    color: #606266;
+  }
+  :deep(.el-step__title.is-wait) {
+    color: #c0c4cc;
+  }
+}
+.page-layout {
+  display: flex;
+  gap: 32px;
+  align-items: flex-start;
+  max-width: 1100px;
+  margin: 0 auto;
+}
+.main-column {
+  flex: 1;
+  min-width: 0;
+}
+.anchor-column {
+  flex-shrink: 0;
+  width: 160px;
+}
+.anchor-card {
+  padding: 16px 12px;
+}
+.anchor-title {
+  margin-bottom: 12px;
+  font-size: 13px;
+  font-weight: 600;
+  color: #303133;
+}
+.zfb-form {
+  :deep(.el-form-item__label) {
+    font-weight: 500;
+    color: #606266;
+  }
+}
+
+/* 开户银行 prop 为联校占位 bankBranch,不能用 el-form-item required,否则恒校验失败 */
+.bank-branch-required-label::after {
+  margin-left: 4px;
+  color: var(--el-color-danger);
+  content: "*";
+}
+.form-block {
+  padding-bottom: 8px;
+  margin-bottom: 8px;
+  scroll-margin-top: 72px;
+}
+.section-head {
+  display: flex;
+  align-items: center;
+  margin: 0 0 20px;
+  font-size: 16px;
+  font-weight: 600;
+  color: #303133;
+}
+.section-bar {
+  display: inline-block;
+  flex-shrink: 0;
+  width: 4px;
+  height: 16px;
+  margin-right: 8px;
+  background: $zfb-blue;
+  border-radius: 2px;
+}
+.radio-stack {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px 20px;
+  align-items: flex-start;
+}
+.settlement-tip-alert {
+  max-width: 480px;
+  margin-top: 12px;
+  color: #1677ff;
+  background: rgb(22 119 255 / 10%);
+  border: 1px solid #1677ff;
+}
+:deep(.el-alert__description) {
+  color: #333333 !important;
+}
+.bank-select-row {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px;
+  align-items: center;
+  max-width: 100%;
+}
+.bank-select-cell {
+  width: 200px;
+  min-width: 160px;
+}
+.bank-region-cascader {
+  width: 260px;
+  min-width: 220px;
+}
+.bank-branch-input {
+  width: 280px;
+  min-width: 200px;
+}
+.invoice-extra-wrap {
+  padding-top: 8px;
+  margin-top: 8px;
+}
+.invoice-section-divider {
+  height: 1px;
+  margin: 24px 0 20px;
+  background: #ebeef5;
+}
+.invoice-subsection-title {
+  margin: 0 0 16px;
+  font-size: 15px;
+  font-weight: 600;
+  color: #303133;
+}
+.mail-address-stack {
+  display: flex;
+  flex-direction: column;
+  gap: 12px;
+  width: 100%;
+  max-width: 480px;
+}
+.mail-cascader {
+  width: 100%;
+}
+.mail-detail-input {
+  width: 100%;
+}
+.footer-actions {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 16px;
+  align-items: center;
+  justify-content: center;
+  padding-top: 24px;
+  margin-top: 16px;
+  border-top: 1px solid #ebeef5;
+}
+.btn-primary-zfb {
+  min-width: 120px;
+  background: $zfb-blue;
+  border-color: $zfb-blue;
+  &:hover {
+    background: #4096ff;
+    border-color: #4096ff;
+  }
+}
+:deep(.anchor-card .el-anchor) {
+  background: transparent;
+  border-left: 1px solid #ebeef5;
+}
+:deep(.anchor-card .el-anchor__link) {
+  padding: 6px 0;
+  font-size: 13px;
+}
+</style>

+ 30 - 26
src/views/dynamicManagement/index.vue

@@ -156,7 +156,7 @@
                 </div>
                 </div>
               </div>
               </div>
             </div>
             </div>
-            <div style=" padding-bottom: 10px;color: #ffffff">
+            <div style="padding-bottom: 10px; color: #ffffff">
               {{ currentDetail.title }}
               {{ currentDetail.title }}
             </div>
             </div>
             <div class="detail-description">
             <div class="detail-description">
@@ -283,7 +283,7 @@
         <div v-if="commentListData.length > 0" class="comment-list">
         <div v-if="commentListData.length > 0" class="comment-list">
           <div v-for="comment in commentListData" :key="comment.id" class="comment-item">
           <div v-for="comment in commentListData" :key="comment.id" class="comment-item">
             <div class="comment-avatar">
             <div class="comment-avatar">
-              <img v-if="comment.userAvatar" :src="comment.userAvatar" :alt="comment.userName" />
+              <img v-if="comment.userImage" :src="comment.userImage" :alt="comment.userName" />
               <el-icon v-else :size="32">
               <el-icon v-else :size="32">
                 <Avatar />
                 <Avatar />
               </el-icon>
               </el-icon>
@@ -522,6 +522,7 @@ import {
   uploadImg,
   uploadImg,
   saveComment,
   saveComment,
   commentList,
   commentList,
+  type CommentListParams,
   getMutualAttention,
   getMutualAttention,
   addTransferCount,
   addTransferCount,
   deleteDynamicsById,
   deleteDynamicsById,
@@ -533,6 +534,7 @@ import {
 } from "@/api/modules/newLoginApi";
 } from "@/api/modules/newLoginApi";
 
 
 // import { uploadImg } from "@/api/modules/upload";
 // import { uploadImg } from "@/api/modules/upload";
+import { normalizeCommonCommentListResponse, countTopAndNestedComments } from "@/utils/commonCommentList";
 import { useUserStore } from "@/stores/modules/user";
 import { useUserStore } from "@/stores/modules/user";
 import { useWebSocketStore } from "@/stores/modules/websocket";
 import { useWebSocketStore } from "@/stores/modules/websocket";
 
 
@@ -646,7 +648,6 @@ const handleVideoPlay = (currentIndex: number) => {
     }
     }
   });
   });
 };
 };
-
 // 举报对话框相关
 // 举报对话框相关
 const reportDialogVisible = ref(false);
 const reportDialogVisible = ref(false);
 const reportSubmitting = ref(false);
 const reportSubmitting = ref(false);
@@ -1014,6 +1015,10 @@ const handleShowComments = () => {
   if (!currentDetail.value) return;
   if (!currentDetail.value) return;
   commentDrawerVisible.value = true;
   commentDrawerVisible.value = true;
   currentCommentDynamicId.value = currentDetail.value.id;
   currentCommentDynamicId.value = currentDetail.value.id;
+  // 清空评论输入框
+  commentInput.value = "";
+  // 清空回复评论
+  replyingComment.value = null;
 };
 };
 
 
 // 加载评论列表
 // 加载评论列表
@@ -1021,31 +1026,31 @@ const loadCommentList = async () => {
   if (!currentDetail.value) return;
   if (!currentDetail.value) return;
 
 
   try {
   try {
-    let params = {
-      businessId: String(currentDetail.value.id),
-      businessType: "2",
-      replyStatus: 0,
+    const params: CommentListParams = {
       pageNum: 1,
       pageNum: 1,
-      pageSize: 10,
-      commentType: 0,
-      days: "",
-      phoneId: `store_${userStore.userInfo?.phone}`
+      pageSize: 100,
+      sourceId: currentDetail.value.id,
+      sourceType: 2
     };
     };
+    const uid = userStore.userInfo?.userId ?? userStore.userInfo?.id;
+    if (uid !== undefined && uid !== null && uid !== "") {
+      const n = Number(uid);
+      if (Number.isFinite(n)) params.userId = Math.trunc(n);
+    }
     const res: any = await commentList(params);
     const res: any = await commentList(params);
     if (res.code === 200) {
     if (res.code === 200) {
-      commentListData.value = res.data.records || [];
-      // 更新评论总数(包括回复数)
+      const list = normalizeCommonCommentListResponse(res.data);
+      commentListData.value = list;
       if (currentDetail.value) {
       if (currentDetail.value) {
-        const baseCommentCount = res.data.total || 0;
-        // 计算所有回复的总数
-        const replyCount = commentListData.value.reduce((total, comment) => {
-          return total + (comment.storeComment?.length || 0);
-        }, 0);
-        // 评论总数 = 评论数 + 回复数
-        currentDetail.value.commentCount = baseCommentCount + replyCount;
+        const raw = res.data;
+        const pageTotal =
+          raw && typeof raw === "object" && !Array.isArray(raw) && typeof (raw as { total?: number }).total === "number"
+            ? (raw as { total: number }).total
+            : undefined;
+        currentDetail.value.commentCount =
+          pageTotal !== undefined && pageTotal >= 0 ? pageTotal : countTopAndNestedComments(list);
       }
       }
       console.log("评论列表:", commentListData.value);
       console.log("评论列表:", commentListData.value);
-      console.log("评论总数:", res.data.total);
     }
     }
   } catch (error) {
   } catch (error) {
     console.error("加载评论列表失败:", error);
     console.error("加载评论列表失败:", error);
@@ -1423,11 +1428,11 @@ const handleReportUpload = async (options: any) => {
 
 
     const response: any = await uploadImg(uploadFormData);
     const response: any = await uploadImg(uploadFormData);
 
 
-    // 处理返回格式:{ code, success, data: string[], msg }
-    if (response && response.code === 200 && response.data && Array.isArray(response.data) && response.data.length > 0) {
-      // 上传成功,返回图片URL(取数组第一个元素)
+    const url =
+      response?.data && (Array.isArray(response.data) && response.data.length > 0 ? response.data[0] : response.data.fileUrl);
+    if (response && response.code === 200 && url) {
       onSuccess({
       onSuccess({
-        url: response.data[0]
+        url
       });
       });
     } else {
     } else {
       ElMessage.error(response?.msg || "图片上传失败");
       ElMessage.error(response?.msg || "图片上传失败");
@@ -1552,7 +1557,6 @@ watch(
     }
     }
   }
   }
 );
 );
-
 // 拉黑用户(点击菜单项)
 // 拉黑用户(点击菜单项)
 const handleBlockUserClick = () => {
 const handleBlockUserClick = () => {
   handleBlockUser(false);
   handleBlockUser(false);

+ 23 - 24
src/views/dynamicManagement/myDynamic.vue

@@ -740,6 +740,7 @@ import {
   getDianZanList,
   getDianZanList,
   saveComment,
   saveComment,
   commentList,
   commentList,
+  type CommentListParams,
   getMutualAttention,
   getMutualAttention,
   getMyFollowed,
   getMyFollowed,
   addTransferCount,
   addTransferCount,
@@ -756,6 +757,7 @@ import {} from "@/api/modules/dynamicManagement";
 import { useUserStore } from "@/stores/modules/user";
 import { useUserStore } from "@/stores/modules/user";
 import FriendCoupon from "./friendCoupon.vue";
 import FriendCoupon from "./friendCoupon.vue";
 import { localGet } from "@/utils";
 import { localGet } from "@/utils";
+import { normalizeCommonCommentListResponse, countTopAndNestedComments } from "@/utils/commonCommentList";
 const router = useRouter();
 const router = useRouter();
 const userStore = useUserStore();
 const userStore = useUserStore();
 
 
@@ -1273,34 +1275,31 @@ const loadCommentList = async () => {
   if (!currentDetail.value) return;
   if (!currentDetail.value) return;
 
 
   try {
   try {
-    const phone = userStore.userInfo?.phone || "";
-    const phoneId = phone.startsWith("store_") ? phone : `store_${phone}`;
-
-    let params = {
-      businessId: String(currentDetail.value.id),
-      businessType: "2",
-      replyStatus: 0,
+    const params: CommentListParams = {
       pageNum: 1,
       pageNum: 1,
       pageSize: 100,
       pageSize: 100,
-      commentType: 0,
-      days: "",
-      phoneId: phoneId
+      sourceId: currentDetail.value.id,
+      sourceType: 2
     };
     };
+    const uid = userStore.userInfo?.userId ?? userStore.userInfo?.id;
+    if (uid !== undefined && uid !== null && uid !== "") {
+      const n = Number(uid);
+      if (Number.isFinite(n)) params.userId = Math.trunc(n);
+    }
     const res: any = await commentList(params);
     const res: any = await commentList(params);
     if (res.code === 200) {
     if (res.code === 200) {
-      commentListData.value = res.data.records || [];
-      // 更新评论总数(包括回复数)
+      const list = normalizeCommonCommentListResponse(res.data);
+      commentListData.value = list;
       if (currentDetail.value) {
       if (currentDetail.value) {
-        const baseCommentCount = res.data.total || 0;
-        // 计算所有回复的总数
-        const replyCount = commentListData.value.reduce((total, comment) => {
-          return total + (comment.storeComment?.length || 0);
-        }, 0);
-        // 评论总数 = 评论数 + 回复数
-        currentDetail.value.commentCount = baseCommentCount + replyCount;
+        const raw = res.data;
+        const pageTotal =
+          raw && typeof raw === "object" && !Array.isArray(raw) && typeof (raw as { total?: number }).total === "number"
+            ? (raw as { total: number }).total
+            : undefined;
+        currentDetail.value.commentCount =
+          pageTotal !== undefined && pageTotal >= 0 ? pageTotal : countTopAndNestedComments(list);
       }
       }
       console.log("评论列表:", commentListData.value);
       console.log("评论列表:", commentListData.value);
-      console.log("评论总数:", res.data.total);
     }
     }
   } catch (error) {
   } catch (error) {
     console.error("加载评论列表失败:", error);
     console.error("加载评论列表失败:", error);
@@ -1382,12 +1381,12 @@ const handleSubmitComment = async () => {
     const isReply = !!replyingComment.value;
     const isReply = !!replyingComment.value;
 
 
     const params: any = {
     const params: any = {
-      replyId: isReply ? replyingComment.value.id : "", // 回复评论时传评论ID,否则为空
+      replyId: isReply ? replyingComment.value.id : "", // 回复评论时传 parentId,否则为 0
       commentContent: commentInput.value,
       commentContent: commentInput.value,
       businessType: "2",
       businessType: "2",
-      businessId: String(currentDetail.value.id),
-      storeId: userStore.userInfo?.storeId || userStore.userInfo?.createdId,
-      commentStar: "",
+      businessId: String(currentDetail.value.id), // 对应请求体 sourceId(动态 id)
+      storeId: userStore.userInfo?.storeId || userStore.userInfo?.createdId, // 对应 merchantId
+      userId: userStore.userInfo?.userId ?? userStore.userInfo?.id ?? "",
       phoneId: phoneId
       phoneId: phoneId
     };
     };
 
 

+ 1 - 1
src/views/dynamicManagement/reviewAppeal.vue

@@ -22,7 +22,7 @@
           </div>
           </div>
         </div>
         </div>
         <div class="stat-card">
         <div class="stat-card">
-          <div class="stat-label">差评中评数</div>
+          <div class="stat-label">新增中评数</div>
           <div class="stat-value">
           <div class="stat-value">
             {{ statistics.neutralReviews }}
             {{ statistics.neutralReviews }}
           </div>
           </div>

+ 23 - 22
src/views/dynamicManagement/userDynamic.vue

@@ -598,6 +598,7 @@ import {
   setFriendCoupon,
   setFriendCoupon,
   saveComment,
   saveComment,
   commentList,
   commentList,
+  type CommentListParams,
   getUserByPhone,
   getUserByPhone,
   reportUserViolation,
   reportUserViolation,
   uploadImg,
   uploadImg,
@@ -607,6 +608,7 @@ import {
 } from "@/api/modules/newLoginApi";
 } from "@/api/modules/newLoginApi";
 import { useUserStore } from "@/stores/modules/user";
 import { useUserStore } from "@/stores/modules/user";
 import { localGet } from "@/utils";
 import { localGet } from "@/utils";
+import { normalizeCommonCommentListResponse, countTopAndNestedComments } from "@/utils/commonCommentList";
 
 
 const route = useRoute();
 const route = useRoute();
 const router = useRouter();
 const router = useRouter();
@@ -872,34 +874,31 @@ const loadCommentList = async () => {
   if (!currentDetail.value) return;
   if (!currentDetail.value) return;
 
 
   try {
   try {
-    const phone = userStore.userInfo?.phone || "";
-    const phoneId = phone.startsWith("store_") ? phone : `store_${phone}`;
-
-    let params = {
-      businessId: String(currentDetail.value.id),
-      businessType: "2",
-      replyStatus: 0,
+    const params: CommentListParams = {
       pageNum: 1,
       pageNum: 1,
       pageSize: 100,
       pageSize: 100,
-      commentType: 0,
-      days: "",
-      phoneId: phoneId
+      sourceId: currentDetail.value.id,
+      sourceType: 2
     };
     };
+    const uid = userStore.userInfo?.userId ?? userStore.userInfo?.id;
+    if (uid !== undefined && uid !== null && uid !== "") {
+      const n = Number(uid);
+      if (Number.isFinite(n)) params.userId = Math.trunc(n);
+    }
     const res: any = await commentList(params);
     const res: any = await commentList(params);
     if (res.code === 200) {
     if (res.code === 200) {
-      commentListData.value = res.data.records || [];
-      // 更新评论总数(包括回复数)
+      const list = normalizeCommonCommentListResponse(res.data);
+      commentListData.value = list;
       if (currentDetail.value) {
       if (currentDetail.value) {
-        const baseCommentCount = res.data.total || 0;
-        // 计算所有回复的总数
-        const replyCount = commentListData.value.reduce((total, comment) => {
-          return total + (comment.storeComment?.length || 0);
-        }, 0);
-        // 评论总数 = 评论数 + 回复数
-        currentDetail.value.commentCount = baseCommentCount + replyCount;
+        const raw = res.data;
+        const pageTotal =
+          raw && typeof raw === "object" && !Array.isArray(raw) && typeof (raw as { total?: number }).total === "number"
+            ? (raw as { total: number }).total
+            : undefined;
+        currentDetail.value.commentCount =
+          pageTotal !== undefined && pageTotal >= 0 ? pageTotal : countTopAndNestedComments(list);
       }
       }
       console.log("评论列表:", commentListData.value);
       console.log("评论列表:", commentListData.value);
-      console.log("评论总数:", res.data.total);
     }
     }
   } catch (error) {
   } catch (error) {
     console.error("加载评论列表失败:", error);
     console.error("加载评论列表失败:", error);
@@ -1490,9 +1489,11 @@ const handleReportUpload = async (options: any) => {
 
 
     const response: any = await uploadImg(uploadFormData);
     const response: any = await uploadImg(uploadFormData);
 
 
-    if (response && response.code === 200 && response.data && Array.isArray(response.data) && response.data.length > 0) {
+    const url =
+      response?.data && (Array.isArray(response.data) && response.data.length > 0 ? response.data[0] : response.data.fileUrl);
+    if (response && response.code === 200 && url) {
       onSuccess({
       onSuccess({
-        url: response.data[0]
+        url
       });
       });
     } else {
     } else {
       ElMessage.error(response?.msg || "图片上传失败");
       ElMessage.error(response?.msg || "图片上传失败");

+ 220 - 3
src/views/home/components/go-flow.vue

@@ -264,6 +264,13 @@
                   </template>
                   </template>
                 </el-upload>
                 </el-upload>
               </el-form-item>
               </el-form-item>
+              <el-form-item label="设置收款账号" @click="handleSetPayAccount" style="cursor: pointer">
+                <div class="pay-account-trigger">
+                  <el-icon color="#666" class="pay-account-trigger__arrow">
+                    <ArrowRightBold />
+                  </el-icon>
+                </div>
+              </el-form-item>
             </div>
             </div>
           </div>
           </div>
         </el-form>
         </el-form>
@@ -282,6 +289,41 @@
     @success="hasBusinessHoursConfig = true"
     @success="hasBusinessHoursConfig = true"
     @has-config="(v: boolean) => (hasBusinessHoursConfig = v)"
     @has-config="(v: boolean) => (hasBusinessHoursConfig = v)"
   />
   />
+
+  <el-dialog
+    v-model="payAccountDialogVisible"
+    width="420px"
+    align-center
+    append-to-body
+    destroy-on-close
+    class="pay-account-setup-dialog"
+    :show-close="true"
+    @open="onPayAccountDialogOpen"
+  >
+    <template #header>
+      <div class="pay-account-setup-dialog__title">设置收款账号</div>
+    </template>
+    <div class="pay-account-option-list">
+      <button
+        v-for="opt in payAccountOptions"
+        :key="opt.value"
+        type="button"
+        class="pay-account-option"
+        :class="{ 'is-active': payAccountTemp === opt.value }"
+        @click="payAccountTemp = opt.value"
+      >
+        <span class="pay-account-option__icon" :class="`pay-account-option__icon--${opt.value}`" aria-hidden="true" />
+        <span class="pay-account-option__label">{{ opt.label }}</span>
+        <span class="pay-account-option__radio" :class="{ 'is-checked': payAccountTemp === opt.value }">
+          <el-icon v-if="payAccountTemp === opt.value" class="pay-account-option__check"><Check /></el-icon>
+        </span>
+      </button>
+    </div>
+    <template #footer>
+      <el-button type="primary" class="pay-account-setup-dialog__confirm" @click="confirmPayAccount"> 确定 </el-button>
+    </template>
+  </el-dialog>
+
   <!-- 图片预览 -->
   <!-- 图片预览 -->
   <el-image-viewer
   <el-image-viewer
     v-if="imageViewerVisible"
     v-if="imageViewerVisible"
@@ -294,15 +336,17 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { ref, reactive, watch, onMounted, computed, toRaw } from "vue";
 import { ref, reactive, watch, onMounted, computed, toRaw } from "vue";
 import { ElMessage, ElMessageBox, type FormInstance, type FormRules, UploadUserFile, UploadRequestOptions } from "element-plus";
 import { ElMessage, ElMessageBox, type FormInstance, type FormRules, UploadUserFile, UploadRequestOptions } from "element-plus";
-import { Plus } from "@element-plus/icons-vue";
+import { Plus, ArrowRightBold, Check } from "@element-plus/icons-vue";
 
 
 import { applyStore, getMerchantByPhone, getThirdLevelList, verifyIdInfo } from "@/api/modules/homeEntry";
 import { applyStore, getMerchantByPhone, getThirdLevelList, verifyIdInfo } from "@/api/modules/homeEntry";
 import { getInputPrompt, getDistrict, uploadImg, ocrRequestUrl, getAiapprovestoreInfo } from "@/api/modules/newLoginApi";
 import { getInputPrompt, getDistrict, uploadImg, ocrRequestUrl, getAiapprovestoreInfo } from "@/api/modules/newLoginApi";
 import GoBusinessHours from "./go-businessHours.vue";
 import GoBusinessHours from "./go-businessHours.vue";
 import { localGet, localSet } from "@/utils/index";
 import { localGet, localSet } from "@/utils/index";
 import { useAuthStore } from "@/stores/modules/auth";
 import { useAuthStore } from "@/stores/modules/auth";
+import { useRouter } from "vue-router";
 
 
 const authStore = useAuthStore();
 const authStore = useAuthStore();
+const router = useRouter();
 const userInfo = localGet("geeker-user")?.userInfo || {};
 const userInfo = localGet("geeker-user")?.userInfo || {};
 const latShow = ref(false);
 const latShow = ref(false);
 const showDisportLicence = ref(false);
 const showDisportLicence = ref(false);
@@ -316,6 +360,16 @@ const hasBusinessHoursConfig = ref(false);
 const openBusinessHours = () => {
 const openBusinessHours = () => {
   businessHoursDialogVisible.value = true;
   businessHoursDialogVisible.value = true;
 };
 };
+
+/** 收款方式:与弹窗选项一致,默认支付宝(与设计稿一致) */
+type ReceivePayType = "alipay" | "wechat" | "bank";
+const payAccountOptions: { value: ReceivePayType; label: string }[] = [
+  { value: "alipay", label: "支付宝支付" },
+  { value: "wechat", label: "微信支付" }
+];
+const payAccountDialogVisible = ref(false);
+const payAccountTemp = ref<ReceivePayType>("alipay");
+
 const entryList = ref([
 const entryList = ref([
   {
   {
     title: "个人实名"
     title: "个人实名"
@@ -668,9 +722,34 @@ const step2Form = reactive({
   // 经营类目
   // 经营类目
   businessCategoryName: "",
   businessCategoryName: "",
   // 店铺评价(三项,与 prop="storePj" 对应,校验规则会检查此数组)
   // 店铺评价(三项,与 prop="storePj" 对应,校验规则会检查此数组)
-  storePj: ["", "", ""] as string[]
+  storePj: ["", "", ""] as string[],
+  /** 设置收款账号(弹窗选择,提交时带给 saveStoreInfo,后端可按需接收) */
+  receivePayType: "alipay" as ReceivePayType
 });
 });
 
 
+const payAccountLabel = computed(() => {
+  const v = step2Form.receivePayType;
+  return payAccountOptions.find(o => o.value === v)?.label ?? "支付宝支付";
+});
+
+const handleSetPayAccount = () => {
+  payAccountDialogVisible.value = true;
+};
+
+const onPayAccountDialogOpen = () => {
+  payAccountTemp.value = step2Form.receivePayType;
+};
+
+const confirmPayAccount = () => {
+  step2Form.receivePayType = payAccountTemp.value;
+  payAccountDialogVisible.value = false;
+  if (payAccountTemp.value === "alipay") {
+    router.push({ path: "/businessInfo/zfbIndex" });
+  } else if (payAccountTemp.value === "wechat") {
+    router.push({ path: "/businessInfo/weChartIndex" });
+  }
+};
+
 // 返回按钮
 // 返回按钮
 const handleBack = () => {
 const handleBack = () => {
   if (currentStep.value === 1) {
   if (currentStep.value === 1) {
@@ -1304,7 +1383,8 @@ const handleSubmit = async () => {
         foodLicenceUrl: foodLicenceUrls.join(","),
         foodLicenceUrl: foodLicenceUrls.join(","),
         mealsFlag: step2Form.businessSecondMeal === 1 ? 1 : 0,
         mealsFlag: step2Form.businessSecondMeal === 1 ? 1 : 0,
         createdUserId: userInfo.id || "",
         createdUserId: userInfo.id || "",
-        storeBusinessTime: storeBusinessTime.length > 0 ? storeBusinessTime : undefined
+        storeBusinessTime: storeBusinessTime.length > 0 ? storeBusinessTime : undefined,
+        receivePayType: step2Form.receivePayType
       };
       };
 
 
       ElMessageBox.confirm("确认提交入驻申请吗?", "提示", {
       ElMessageBox.confirm("确认提交入驻申请吗?", "提示", {
@@ -1553,5 +1633,142 @@ const handleExceed = () => {
       outline: none;
       outline: none;
     }
     }
   }
   }
+  .pay-account-trigger {
+    display: inline-flex;
+    gap: 10px;
+    align-items: center;
+    &__text {
+      font-size: 14px;
+      color: #303133;
+    }
+    &__arrow {
+      cursor: pointer;
+    }
+  }
+}
+</style>
+
+<style lang="scss">
+/* 弹窗挂到 body,需非 scoped;并抵消本页全局 .el-dialog__body { height: 600px } */
+.pay-account-setup-dialog.el-dialog {
+  padding: 0;
+  overflow: hidden;
+  border-radius: 12px;
+  box-shadow: 0 8px 32px rgb(0 0 0 / 12%);
+}
+.pay-account-setup-dialog .el-dialog__header {
+  padding: 20px 24px 12px;
+  margin: 0;
+}
+.pay-account-setup-dialog .el-dialog__headerbtn {
+  top: 16px;
+  right: 16px;
+  font-size: 18px;
+}
+.pay-account-setup-dialog .el-dialog__body {
+  height: auto !important;
+  max-height: none !important;
+  padding: 4px 24px 8px !important;
+  overflow: visible !important;
+}
+.pay-account-setup-dialog .el-dialog__footer {
+  padding: 16px 24px 24px;
+}
+.pay-account-setup-dialog__title {
+  width: 100%;
+  font-size: 17px;
+  font-weight: 600;
+  color: #303133;
+  text-align: center;
+}
+.pay-account-option-list {
+  display: flex;
+  flex-direction: column;
+}
+.pay-account-option {
+  display: flex;
+  gap: 14px;
+  align-items: center;
+  width: 100%;
+  padding: 16px 0;
+  margin: 0;
+  font: inherit;
+  text-align: left;
+  cursor: pointer;
+  background: transparent;
+  border: none;
+  border-bottom: 1px solid #ebeef5;
+  outline: none;
+}
+.pay-account-option:last-of-type {
+  border-bottom: none;
+}
+.pay-account-option__icon {
+  flex-shrink: 0;
+  width: 36px;
+  height: 36px;
+  border-radius: 8px;
+}
+.pay-account-option__icon--alipay {
+  background: #1677ff;
+  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M8.5 7.2h2.2v1.9H8.5V7.2zm0 3.1h2.2v5.4H8.5v-5.4zm3.8-3.1h4.6c1.4 0 2.4 1 2.4 2.3 0 1.1-.7 2-1.7 2.3l1.9 3.8h-2.5l-1.6-3.2h-1.4v3.2h-2.2V7.2zm2.2 3.6h2.1c.6 0 1-.4 1-.9 0-.5-.4-.9-1-.9h-2.1v1.8z'/%3E%3C/svg%3E");
+  background-repeat: no-repeat;
+  background-position: center;
+  background-size: 26px 26px;
+}
+.pay-account-option__icon--wechat {
+  background: #07c160;
+  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M8.5 10.5c-.8 0-1.5-.7-1.5-1.5S7.7 7.5 8.5 7.5 10 8.2 10 9s-.7 1.5-1.5 1.5zm7 0c-.8 0-1.5-.7-1.5-1.5S14.7 7.5 15.5 7.5 17 8.2 17 9s-.7 1.5-1.5 1.5z'/%3E%3Cpath fill='%23fff' d='M9 14.5c-2.5 0-4.5-1.6-4.5-3.5 0-1 .5-1.9 1.3-2.6-.1-.3-.2-.7-.2-1C5.6 5.8 8.9 4 13 4s7.4 1.8 7.4 4c0 .4-.1.8-.2 1 .8.7 1.3 1.6 1.3 2.6 0 1.9-2 3.5-4.5 3.5-.6 0-1.2-.1-1.8-.3l-2 1.1.5-1.8c-.9-.5-1.6-1.2-2-2z'/%3E%3C/svg%3E");
+  background-repeat: no-repeat;
+  background-position: center;
+  background-size: 24px 24px;
+}
+.pay-account-option__icon--bank {
+  background-color: #3b7cff;
+  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='3' y='7' width='18' height='11' rx='2' fill='%23fff' opacity='.95'/%3E%3Crect x='3' y='10' width='18' height='2' fill='%233b7cff'/%3E%3C/svg%3E");
+  background-repeat: no-repeat;
+  background-position: center;
+  background-size: 28px 22px;
+}
+.pay-account-option__label {
+  flex: 1;
+  font-size: 15px;
+  color: #303133;
+}
+.pay-account-option__radio {
+  display: flex;
+  flex-shrink: 0;
+  align-items: center;
+  justify-content: center;
+  width: 22px;
+  height: 22px;
+  border: 2px solid #dcdfe6;
+  border-radius: 50%;
+  transition:
+    border-color 0.2s,
+    background 0.2s;
+}
+.pay-account-option__radio.is-checked {
+  background: #7395ff;
+  border-color: #7395ff;
+}
+.pay-account-option__check {
+  font-size: 14px;
+  font-weight: 700;
+  color: #ffffff;
+}
+.pay-account-setup-dialog__confirm {
+  width: 100%;
+  height: 44px;
+  font-size: 16px;
+  font-weight: 500;
+  color: #ffffff;
+  background: #7395ff !important;
+  border-color: #7395ff !important;
+  border-radius: 8px;
+}
+.pay-account-setup-dialog__confirm:hover {
+  background: #5f82f0 !important;
+  border-color: #5f82f0 !important;
 }
 }
 </style>
 </style>

+ 14 - 14
src/views/operationManagement/activityList.vue

@@ -323,20 +323,20 @@ const columns = reactive<ColumnProps<any>[]>([
       return activityType == "MARKETING" ? "营销活动" : "评论有礼";
       return activityType == "MARKETING" ? "营销活动" : "评论有礼";
     }
     }
   },
   },
-  {
-    prop: "signupStartTime",
-    label: "报名开始时间/结束时间",
-    width: 300,
-    render: (scope: any) => {
-      const formatDate = (dateStr: string) => {
-        if (!dateStr) return "--";
-        // 只取日期部分(去掉时分秒)
-        const datePart = dateStr.split(" ")[0];
-        return datePart?.replace(/-/g, "/") || "--";
-      };
-      return `${formatDate(scope.row.signupStartTime)} - ${formatDate(scope.row.signupEndTime)}`;
-    }
-  },
+  // {
+  //   prop: "signupStartTime",
+  //   label: "报名开始时间/结束时间",
+  //   width: 300,
+  //   render: (scope: any) => {
+  //     const formatDate = (dateStr: string) => {
+  //       if (!dateStr) return "--";
+  //       // 只取日期部分(去掉时分秒)
+  //       const datePart = dateStr.split(" ")[0];
+  //       return datePart?.replace(/-/g, "/") || "--";
+  //     };
+  //     return `${formatDate(scope.row.signupStartTime)} - ${formatDate(scope.row.signupEndTime)}`;
+  //   }
+  // },
   {
   {
     prop: "startTime",
     prop: "startTime",
     label: "活动开始时间/结束时间",
     label: "活动开始时间/结束时间",

+ 52 - 16
src/views/operationManagement/newActivity.vue

@@ -81,8 +81,8 @@
           </div>
           </div>
         </div>
         </div>
 
 
-        <!-- 4. 活动详情图 -->
-        <div class="form-item-card">
+        <!-- 4. 活动详情图(仅营销活动需要) -->
+        <div v-if="activityModel.activityType === 'MARKETING'" class="form-item-card">
           <div class="form-item card-item">
           <div class="form-item card-item">
             <div class="form-label form-label-col">活动详情图 <span class="required">*</span></div>
             <div class="form-label form-label-col">活动详情图 <span class="required">*</span></div>
             <div class="detail-upload-wrapper upload-slot-dashed">
             <div class="detail-upload-wrapper upload-slot-dashed">
@@ -401,10 +401,11 @@ const imageViewerInitialIndex = ref(0);
 
 
 // 是否有未上传的图片
 // 是否有未上传的图片
 const hasUnuploadedImages = computed(() => {
 const hasUnuploadedImages = computed(() => {
-  return (
-    titleFileList.value.some(file => file.status === "ready" || file.status === "uploading") ||
-    detailFileList.value.some(file => file.status === "ready" || file.status === "uploading")
-  );
+  const titlePending = titleFileList.value.some(file => file.status === "ready" || file.status === "uploading");
+  const detailPending =
+    activityModel.value.activityType === "MARKETING" &&
+    detailFileList.value.some(file => file.status === "ready" || file.status === "uploading");
+  return titlePending || detailPending;
 });
 });
 
 
 // ==================== 表单验证规则 ====================
 // ==================== 表单验证规则 ====================
@@ -646,6 +647,10 @@ const rules = reactive({
     {
     {
       required: true,
       required: true,
       validator: (_rule: any, _value: any, callback: any) => {
       validator: (_rule: any, _value: any, callback: any) => {
+        if (activityModel.value.activityType !== "MARKETING") {
+          callback();
+          return;
+        }
         const successFiles = detailFileList.value.filter((f: any) => f.status === "success" && f.url);
         const successFiles = detailFileList.value.filter((f: any) => f.status === "success" && f.url);
         if (successFiles.length === 0) {
         if (successFiles.length === 0) {
           callback(new Error("请上传活动详情图"));
           callback(new Error("请上传活动详情图"));
@@ -1204,9 +1209,10 @@ const handlegetTime = (val: string) => {
   return val || "";
   return val || "";
 };
 };
 
 
-/** 将 AI 接口返回写入 banner / 详情图 */
+/** 将 AI 接口返回写入 banner / 详情图(评价有礼仅写入 banner) */
 const applyPromotionImagesFromResponse = (data: any) => {
 const applyPromotionImagesFromResponse = (data: any) => {
   if (!data || typeof data !== "object") return;
   if (!data || typeof data !== "object") return;
+  const isMarketing = activityModel.value.activityType === "MARKETING";
 
 
   const titleObj = data.activityTitleImg;
   const titleObj = data.activityTitleImg;
   if (titleObj && titleObj.imgUrl) {
   if (titleObj && titleObj.imgUrl) {
@@ -1231,6 +1237,13 @@ const applyPromotionImagesFromResponse = (data: any) => {
     }
     }
   }
   }
 
 
+  if (!isMarketing) {
+    nextTick(() => {
+      ruleFormRef.value?.validateField(["activityTitleImage"]);
+    });
+    return;
+  }
+
   const detailObj = data.activityDetailImg;
   const detailObj = data.activityDetailImg;
   if (detailObj) {
   if (detailObj) {
     let urls: string[] = [];
     let urls: string[] = [];
@@ -1282,7 +1295,11 @@ const handleAiGenerate = async () => {
     if (res && res.code == 200) {
     if (res && res.code == 200) {
       applyPromotionImagesFromResponse(res.data);
       applyPromotionImagesFromResponse(res.data);
       nextTick(() => {
       nextTick(() => {
-        ruleFormRef.value?.validateField(["activityTitleImage", "activityDetailImage"]);
+        const fields: string[] =
+          activityModel.value.activityType === "MARKETING"
+            ? ["activityTitleImage", "activityDetailImage"]
+            : ["activityTitleImage"];
+        ruleFormRef.value?.validateField(fields);
       });
       });
       ElMessage.success(res.msg || "图片生成成功");
       ElMessage.success(res.msg || "图片生成成功");
     } else {
     } else {
@@ -1340,13 +1357,22 @@ watch(
           "voucherQuantity"
           "voucherQuantity"
         ]);
         ]);
       } else if (typeValue === "COMMENT") {
       } else if (typeValue === "COMMENT") {
-        // 切换到评论有礼:清除营销活动相关字段
+        // 切换到评论有礼:清除营销活动相关字段(含活动详情图,评价有礼不需要)
         activityModel.value.signupTimeRange = [];
         activityModel.value.signupTimeRange = [];
         activityModel.value.activityLimitPeople = "";
         activityModel.value.activityLimitPeople = "";
         activityModel.value.activityDetails = "";
         activityModel.value.activityDetails = "";
+        const detailUids = new Set(detailFileList.value.map((f: any) => f.uid));
+        detailFileList.value.forEach((f: any) => {
+          if (f?.url && String(f.url).startsWith("blob:")) URL.revokeObjectURL(f.url);
+        });
+        detailFileList.value = [];
+        detailImageUrl.value = "";
+        activityModel.value.activityDetailImg = null;
+        activityModel.value.activityDetailImage = "";
+        pendingUploadFiles.value = pendingUploadFiles.value.filter((f: any) => !detailUids.has(f.uid));
         activityModel.value.discountCouponType = activityModel.value.rewardType === "VOUCHER" ? 1 : 2;
         activityModel.value.discountCouponType = activityModel.value.rewardType === "VOUCHER" ? 1 : 2;
         // 清除营销活动字段的验证状态
         // 清除营销活动字段的验证状态
-        ruleFormRef.value?.clearValidate(["signupTimeRange", "activityLimitPeople", "activityDetails"]);
+        ruleFormRef.value?.clearValidate(["signupTimeRange", "activityLimitPeople", "activityDetails", "activityDetailImage"]);
         // 加载优惠券列表
         // 加载优惠券列表
         loadCouponList();
         loadCouponList();
       }
       }
@@ -1579,10 +1605,9 @@ onMounted(async () => {
             titleFileList.value = [titleFile];
             titleFileList.value = [titleFile];
           }
           }
         }
         }
-        // 如果有详情图片,添加到文件列表(支持多张图片,可能是字符串或数组
-        if (res.data.activityDetailImgUrl) {
+        // 营销活动:加载详情图(评价有礼不需要
+        if (activityModel.value.activityType === "MARKETING" && res.data.activityDetailImgUrl) {
           let detailImgUrls: string[] = [];
           let detailImgUrls: string[] = [];
-          // 如果是字符串,可能是逗号分隔的多张图片
           if (typeof res.data.activityDetailImgUrl === "string") {
           if (typeof res.data.activityDetailImgUrl === "string") {
             detailImgUrls = res.data.activityDetailImgUrl.split(",").filter((url: string) => url.trim());
             detailImgUrls = res.data.activityDetailImgUrl.split(",").filter((url: string) => url.trim());
           } else if (Array.isArray(res.data.activityDetailImgUrl)) {
           } else if (Array.isArray(res.data.activityDetailImgUrl)) {
@@ -1593,9 +1618,13 @@ onMounted(async () => {
             detailImageUrl.value = detailImgUrls.join(",");
             detailImageUrl.value = detailImgUrls.join(",");
             activityModel.value.activityDetailImg = res.data.activityDetailImgUrl;
             activityModel.value.activityDetailImg = res.data.activityDetailImgUrl;
             activityModel.value.activityDetailImage = detailImgUrls.join(",");
             activityModel.value.activityDetailImage = detailImgUrls.join(",");
-            // 将多张图片添加到文件列表
             detailFileList.value = detailImgUrls.map((url: string) => handleImageParam(url));
             detailFileList.value = detailImgUrls.map((url: string) => handleImageParam(url));
           }
           }
+        } else if (activityModel.value.activityType === "COMMENT") {
+          detailFileList.value = [];
+          detailImageUrl.value = "";
+          activityModel.value.activityDetailImg = null;
+          activityModel.value.activityDetailImage = "";
         }
         }
       }
       }
     } catch (error) {
     } catch (error) {
@@ -1650,11 +1679,18 @@ const handleSubmit = async () => {
       // 活动时间:开始日期传当天 00:00:00,结束日期传当天 23:59:59
       // 活动时间:开始日期传当天 00:00:00,结束日期传当天 23:59:59
       const startTime = activityStartDate ? `${activityStartDate} 00:00:00` : "";
       const startTime = activityStartDate ? `${activityStartDate} 00:00:00` : "";
       const endTime = activityEndDate ? `${activityEndDate} 23:59:59` : "";
       const endTime = activityEndDate ? `${activityEndDate} 23:59:59` : "";
+      const detailUrls =
+        activityModel.value.activityType === "MARKETING" && detailImageUrl.value
+          ? detailImageUrl.value
+              .split(",")
+              .map((s: string) => s.trim())
+              .filter(Boolean)
+          : [];
       const auditParam = {
       const auditParam = {
         text: activityModel.value.imgDescribe?.trim()
         text: activityModel.value.imgDescribe?.trim()
           ? `${activityModel.value.activityName},${activityModel.value.imgDescribe.trim()}`
           ? `${activityModel.value.activityName},${activityModel.value.imgDescribe.trim()}`
           : activityModel.value.activityName,
           : activityModel.value.activityName,
-        image_urls: [titleImageUrl.value, ...(detailImageUrl.value ? detailImageUrl.value.split(",") : [])].filter(Boolean)
+        image_urls: [titleImageUrl.value, ...detailUrls].filter(Boolean)
       };
       };
       const params: any = {
       const params: any = {
         activityType: activityModel.value.activityType,
         activityType: activityModel.value.activityType,
@@ -1696,7 +1732,7 @@ const handleSubmit = async () => {
         storeId: localGet("createdId")
         storeId: localGet("createdId")
       };
       };
       params.activityDetailImg = {
       params.activityDetailImg = {
-        imgUrl: detailImageUrl.value,
+        imgUrl: activityModel.value.activityType === "MARKETING" ? detailImageUrl.value : "",
         imgSort: 0,
         imgSort: 0,
         storeId: localGet("createdId")
         storeId: localGet("createdId")
       };
       };

+ 11 - 1
src/views/storeDecoration/basicStoreInformation/index.vue

@@ -200,6 +200,12 @@
           <el-form-item label="经营类目" prop="businessCategoryName">
           <el-form-item label="经营类目" prop="businessCategoryName">
             <el-input v-model="formData.businessCategoryName" placeholder="请输入经营类目" clearable maxlength="50" />
             <el-input v-model="formData.businessCategoryName" placeholder="请输入经营类目" clearable maxlength="50" />
           </el-form-item>
           </el-form-item>
+          <el-form-item label="预定服务" prop="bookingService">
+            <el-radio-group v-model="formData.bookingService">
+              <el-radio :value="1"> 提供 </el-radio>
+              <el-radio :value="0"> 不提供 </el-radio>
+            </el-radio-group>
+          </el-form-item>
           <el-form-item label="营业时间">
           <el-form-item label="营业时间">
             <div style="color: #6c8ff8; cursor: pointer" @click="handleViewBusinessHours">查看</div>
             <div style="color: #6c8ff8; cursor: pointer" @click="handleViewBusinessHours">查看</div>
           </el-form-item>
           </el-form-item>
@@ -857,7 +863,9 @@ const formData = reactive({
   storePositionLongitude: "",
   storePositionLongitude: "",
   storePositionLatitude: "",
   storePositionLatitude: "",
   isChain: 0,
   isChain: 0,
-  storeTickets: "" as number | ""
+  storeTickets: "" as number | "",
+  /** 预定服务:1 提供 / 0 不提供(与 go-flow 入驻 bookingService 一致) */
+  bookingService: 0 as 0 | 1
 });
 });
 
 
 // 经纬度查询
 // 经纬度查询
@@ -1171,6 +1179,7 @@ const handleSubmit = async () => {
         businessSectionName: selectedSection ? selectedSection.dictDetail : "",
         businessSectionName: selectedSection ? selectedSection.dictDetail : "",
         businessTypeName: formData.businessTypeName,
         businessTypeName: formData.businessTypeName,
         businessCategoryName: formData.businessCategoryName,
         businessCategoryName: formData.businessCategoryName,
+        bookingService: formData.bookingService,
         // 标签选择(仅当经营板块为生活服务时)
         // 标签选择(仅当经营板块为生活服务时)
         storeTickets:
         storeTickets:
           formData.businessSection === 3 ? (formData.storeTickets !== "" ? formData.storeTickets : undefined) : undefined
           formData.businessSection === 3 ? (formData.storeTickets !== "" ? formData.storeTickets : undefined) : undefined
@@ -1280,6 +1289,7 @@ const getStoreDetailData = async () => {
       // 如果 businessCategoryName 是 0,转换为空字符串
       // 如果 businessCategoryName 是 0,转换为空字符串
       const categoryName = storeData.businessCategoryName;
       const categoryName = storeData.businessCategoryName;
       formData.businessCategoryName = categoryName === 0 || categoryName === "0" ? "" : categoryName || "";
       formData.businessCategoryName = categoryName === 0 || categoryName === "0" ? "" : categoryName || "";
+      formData.bookingService = storeData.bookingService === 1 || storeData.bookingService === "1" ? 1 : 0;
     }
     }
   } catch (error) {
   } catch (error) {
     console.error("获取店铺详情失败:", error);
     console.error("获取店铺详情失败:", error);

+ 0 - 1
src/views/storeDecoration/businessHours/index.vue

@@ -232,7 +232,6 @@ function getListTitle(item: NormalHoursItem | SpecialHoursItem, type: 1 | 2) {
   if (type === 1) {
   if (type === 1) {
     const n = item as NormalHoursItem;
     const n = item as NormalHoursItem;
     const sorted = [...n.days].sort((a, b) => a - b);
     const sorted = [...n.days].sort((a, b) => a - b);
-    if (sorted.length === 7) return "周一至周日";
     return sorted
     return sorted
       .map(d => weekDays.find(w => w.value === d)?.label)
       .map(d => weekDays.find(w => w.value === d)?.label)
       .filter(Boolean)
       .filter(Boolean)

+ 37 - 24
src/views/storeDecoration/officialPhotoAlbum/index.vue

@@ -3,8 +3,8 @@
     <!-- 头部:环境/视频/相册 Tab和新建按钮 -->
     <!-- 头部:环境/视频/相册 Tab和新建按钮 -->
     <div class="header-section">
     <div class="header-section">
       <el-tabs v-model="activeTab" @tab-click="handleTabClick">
       <el-tabs v-model="activeTab" @tab-click="handleTabClick">
-        <el-tab-pane label="环境" name="environment" />
-        <el-tab-pane label="视频" name="video" />
+        <!-- <el-tab-pane label="环境" name="environment" />
+        <el-tab-pane label="视频" name="video" /> -->
         <el-tab-pane v-for="album in albumList" :key="album.id" :label="album.name" :name="String(album.id)">
         <el-tab-pane v-for="album in albumList" :key="album.id" :label="album.name" :name="String(album.id)">
           <template #label>
           <template #label>
             <span class="album-tab-label">
             <span class="album-tab-label">
@@ -187,12 +187,22 @@ import {
 } from "@/api/modules/storeDecoration";
 } from "@/api/modules/storeDecoration";
 import { uploadFilesToOss } from "@/api/upload.js";
 import { uploadFilesToOss } from "@/api/upload.js";
 
 
+/** 普通官方相册图 */
+const OFFICIAL_IMG_TYPE_ALBUM = 2;
+/** 环境 Tab 及约定走环境图类型的相册 Tab(如 id=182) */
+const OFFICIAL_IMG_TYPE_ENV_OR_SPECIAL_ALBUM = 4;
+
+/** 相册 Tab 的 name 为相册 id 字符串;列入此集合的 Tab 拉列表、保存时 imgType 均为 4 */
+const albumTabNamesWithImgType4 = new Set<string>(["182"]);
+
+const isAlbumTabImgType4 = (tabKey: string) => albumTabNamesWithImgType4.has(String(tabKey));
+
 // 扩展图片类型
 // 扩展图片类型
 interface AlbumImage extends UploadUserFile {
 interface AlbumImage extends UploadUserFile {
   isCover?: boolean;
   isCover?: boolean;
   businessId?: number; // 相册ID
   businessId?: number; // 相册ID
   imgSort?: number; // 排序
   imgSort?: number; // 排序
-  imgType?: number; // 图片类型,固定为2
+  imgType?: number; // 相册默认 2;环境 / 特殊相册 Tab 为 4
   imgId?: number; // 图片ID(从服务器返回)
   imgId?: number; // 图片ID(从服务器返回)
 }
 }
 
 
@@ -217,7 +227,8 @@ interface Album {
 
 
 const createDialogVisible = ref(false);
 const createDialogVisible = ref(false);
 const createFormRef = ref<FormInstance>();
 const createFormRef = ref<FormInstance>();
-const activeTab = ref("environment"); // 当前选中的tab:environment、video 或 相册ID
+// 环境 / 视频 / 相册 id(字符串);初始为空,相册列表加载后默认选中第一项
+const activeTab = ref("");
 const previewVisible = ref(false);
 const previewVisible = ref(false);
 const previewImageUrl = ref("");
 const previewImageUrl = ref("");
 const previewVideoUrl = ref("");
 const previewVideoUrl = ref("");
@@ -538,11 +549,16 @@ const saveImageToServer = async (imgUrl: string) => {
 
 
     const imgSort = currentImages.filter((img: AlbumImage) => img.imgId).length + 1; // 排序为已保存图片数量+1
     const imgSort = currentImages.filter((img: AlbumImage) => img.imgId).length + 1; // 排序为已保存图片数量+1
 
 
+    const imgType =
+      activeTab.value === "environment" || isAlbumTabImgType4(activeTab.value)
+        ? OFFICIAL_IMG_TYPE_ENV_OR_SPECIAL_ALBUM
+        : OFFICIAL_IMG_TYPE_ALBUM;
+
     const params = [
     const params = [
       {
       {
         businessId: businessId,
         businessId: businessId,
         imgSort: imgSort,
         imgSort: imgSort,
-        imgType: 2, // 图片类型为2
+        imgType,
         imgUrl: imgUrl,
         imgUrl: imgUrl,
         storeId: Number(storeId)
         storeId: Number(storeId)
       }
       }
@@ -755,14 +771,8 @@ const handleDeleteAlbum = async () => {
       createDialogVisible.value = false;
       createDialogVisible.value = false;
       resetCreateForm();
       resetCreateForm();
 
 
-      // 重新获取相册列表
+      // 重新获取相册列表(当前 tab 若已不存在会自动选中第一项或清空)
       await getAlbumList();
       await getAlbumList();
-
-      // 如果删除的是当前选中的相册,切换到环境tab
-      if (String(editId.value) === activeTab.value) {
-        activeTab.value = "environment";
-        await loadEnvironmentImages();
-      }
     } else {
     } else {
       ElMessage.error(res?.msg || "删除相册失败");
       ElMessage.error(res?.msg || "删除相册失败");
     }
     }
@@ -1076,10 +1086,17 @@ const getAlbumList = async () => {
         videos: reactive<AlbumVideo[]>([]),
         videos: reactive<AlbumVideo[]>([]),
         coverImageId: album.coverImageId
         coverImageId: album.coverImageId
       }));
       }));
-      // 默认选中"环境"tab
-      if (!activeTab.value || activeTab.value === "") {
-        activeTab.value = "environment";
-        await loadEnvironmentImages();
+      // 默认选中第一个相册;若当前 tab 仍有效则保留(如刷新列表、新建后切到最后一个)
+      const prev = activeTab.value;
+      const idSet = new Set(albumList.value.map(a => String(a.id)));
+      if (albumList.value.length > 0) {
+        const keepSpecial = prev === "environment" || prev === "video";
+        const keepAlbum = Boolean(prev && idSet.has(String(prev)));
+        if (!keepSpecial && !keepAlbum) {
+          activeTab.value = String(albumList.value[0].id);
+        }
+      } else if (prev !== "environment" && prev !== "video") {
+        activeTab.value = "";
       }
       }
     }
     }
   } catch (error) {
   } catch (error) {
@@ -1100,7 +1117,7 @@ const loadEnvironmentImages = async () => {
     // 环境图片:使用 storeId 作为 businessId(需要根据实际API调整)
     // 环境图片:使用 storeId 作为 businessId(需要根据实际API调整)
     // 或者如果环境图片不需要 businessId,可能需要使用其他API
     // 或者如果环境图片不需要 businessId,可能需要使用其他API
     // 这里先使用 storeId 作为 businessId
     // 这里先使用 storeId 作为 businessId
-    const imageRes: any = await getOfficialImgList(Number(storeId), Number(storeId), 2);
+    const imageRes: any = await getOfficialImgList(Number(storeId), Number(storeId), OFFICIAL_IMG_TYPE_ENV_OR_SPECIAL_ALBUM);
 
 
     if (imageRes && (imageRes.code === 200 || imageRes.code === "200") && imageRes.data) {
     if (imageRes && (imageRes.code === 200 || imageRes.code === "200") && imageRes.data) {
       const imageList = Array.isArray(imageRes.data) ? imageRes.data : [];
       const imageList = Array.isArray(imageRes.data) ? imageRes.data : [];
@@ -1194,8 +1211,8 @@ const loadAlbumImages = async (albumId: string) => {
       return;
       return;
     }
     }
 
 
-    // 加载图片(imgType = 2)
-    const imageRes: any = await getOfficialImgList(Number(albumId), Number(storeId), 2);
+    const listImgType = isAlbumTabImgType4(albumId) ? OFFICIAL_IMG_TYPE_ENV_OR_SPECIAL_ALBUM : OFFICIAL_IMG_TYPE_ALBUM;
+    const imageRes: any = await getOfficialImgList(Number(albumId), Number(storeId), listImgType);
 
 
     const current = albumList.value.find(album => String(album.id) === albumId);
     const current = albumList.value.find(album => String(album.id) === albumId);
     if (!current) {
     if (!current) {
@@ -1253,13 +1270,9 @@ const loadAlbumImages = async (albumId: string) => {
   }
   }
 };
 };
 
 
-// 页面初始化
+// 页面初始化:拉相册列表后默认第一项,图片由 watch(activeTab) 加载
 onMounted(async () => {
 onMounted(async () => {
   await getAlbumList();
   await getAlbumList();
-  // 默认加载环境图片
-  if (activeTab.value === "environment") {
-    await loadEnvironmentImages();
-  }
 });
 });
 </script>
 </script>
 
 

+ 45 - 22
src/views/storeDecoration/personnelConfig/index.vue

@@ -416,6 +416,23 @@ const approvalStatusEnum = [
   { label: "已驳回", value: 2 }
   { label: "已驳回", value: 2 }
 ];
 ];
 
 
+/** 列表/详情:统一为 YYYY-MM-DD HH:mm:ss */
+const formatTime = (time: string | null | undefined) => {
+  if (!time) return "";
+  try {
+    const date = new Date(time);
+    const y = date.getFullYear();
+    const m = String(date.getMonth() + 1).padStart(2, "0");
+    const d = String(date.getDate()).padStart(2, "0");
+    const h = String(date.getHours()).padStart(2, "0");
+    const min = String(date.getMinutes()).padStart(2, "0");
+    const s = String(date.getSeconds()).padStart(2, "0");
+    return `${y}-${m}-${d} ${h}:${min}:${s}`;
+  } catch {
+    return time;
+  }
+};
+
 // 表格配置项
 // 表格配置项
 const columns = reactive<ColumnProps<any>[]>([
 const columns = reactive<ColumnProps<any>[]>([
   {
   {
@@ -496,7 +513,24 @@ const columns = reactive<ColumnProps<any>[]>([
   {
   {
     prop: "createdTime",
     prop: "createdTime",
     label: "提交时间",
     label: "提交时间",
-    width: 180
+    width: 190,
+    render: (scope: any) => {
+      const t = scope.row.submissionTime || scope.row.createdTime;
+      return t ? formatTime(t) : "—";
+    },
+    search: {
+      el: "date-picker",
+      props: {
+        type: "datetimerange",
+        "range-separator": "至",
+        "start-placeholder": "开始时间",
+        "end-placeholder": "结束时间",
+        format: "YYYY-MM-DD HH:mm:ss",
+        "value-format": "YYYY-MM-DD HH:mm:ss"
+      },
+      order: 5,
+      span: 2
+    }
   },
   },
   { prop: "operation", label: "操作", fixed: "right", minWidth: 350 }
   { prop: "operation", label: "操作", fixed: "right", minWidth: 350 }
 ]);
 ]);
@@ -586,10 +620,16 @@ const getTableList = (params: any) => {
   if (params.approvalStatus !== undefined && params.approvalStatus !== null && params.approvalStatus !== "") {
   if (params.approvalStatus !== undefined && params.approvalStatus !== null && params.approvalStatus !== "") {
     newParams.status = params.approvalStatus; // 审核状态 -> status
     newParams.status = params.approvalStatus; // 审核状态 -> status
   }
   }
-  // 处理日期范围 - 使用 startCreatedTime 和 endCreatedTime
-  if (params.dateRange && Array.isArray(params.dateRange) && params.dateRange.length === 2) {
-    newParams.startCreatedTime = params.dateRange[0];
-    newParams.endCreatedTime = params.dateRange[1];
+  // 提交时间:ProTable 搜索项 prop 为 createdTime,值为 [start, end]
+  const submissionRange =
+    params.createdTime && Array.isArray(params.createdTime) && params.createdTime.length === 2
+      ? params.createdTime
+      : params.dateRange && Array.isArray(params.dateRange) && params.dateRange.length === 2
+        ? params.dateRange
+        : null;
+  if (submissionRange) {
+    newParams.startCreatedTime = submissionRange[0];
+    newParams.endCreatedTime = submissionRange[1];
   }
   }
 
 
   // 使用新的搜索接口
   // 使用新的搜索接口
@@ -600,7 +640,6 @@ const getTableList = (params: any) => {
   });
   });
 };
 };
 
 
-// 格式化时间
 // 获取背景图片/视频列表
 // 获取背景图片/视频列表
 const getBackgroundImageList = (backgroundUrl: string | null | undefined): string[] => {
 const getBackgroundImageList = (backgroundUrl: string | null | undefined): string[] => {
   if (!backgroundUrl) return [];
   if (!backgroundUrl) return [];
@@ -630,22 +669,6 @@ const handleVideoPreviewInForm = (url: string) => {
   previewVideoVisible.value = true;
   previewVideoVisible.value = true;
 };
 };
 
 
-const formatTime = (time: string | null | undefined) => {
-  if (!time) return "";
-  try {
-    const date = new Date(time);
-    const y = date.getFullYear();
-    const m = String(date.getMonth() + 1).padStart(2, "0");
-    const d = String(date.getDate()).padStart(2, "0");
-    const h = String(date.getHours()).padStart(2, "0");
-    const min = String(date.getMinutes()).padStart(2, "0");
-    const s = String(date.getSeconds()).padStart(2, "0");
-    return `${y}-${m}-${d} ${h}:${min}:${s}`;
-  } catch {
-    return time;
-  }
-};
-
 // 弹窗标题
 // 弹窗标题
 const dialogTitle = computed(() => (editId.value !== null ? "编辑" : "新建"));
 const dialogTitle = computed(() => (editId.value !== null ? "编辑" : "新建"));
 
 

+ 70 - 43
src/views/storeDecoration/storeHeadMap/index.vue

@@ -5,12 +5,21 @@
       <div class="mode-preview-section">
       <div class="mode-preview-section">
         <div class="preview-box">
         <div class="preview-box">
           <div class="preview-card">
           <div class="preview-card">
-            <div class="preview-images-multiple">
-              <div v-for="(img, index) in displayImages" :key="index" class="preview-image-small">
-                <img v-if="img" :src="img" alt="头图" />
-                <div v-else class="preview-placeholder">示例图</div>
-              </div>
-              <div v-if="displayImages.length < 3" class="preview-image-small">
+            <div class="preview-images-carousel">
+              <el-carousel
+                v-if="carouselPreviewImages.length > 0"
+                height="250px"
+                :autoplay="carouselPreviewImages.length > 1"
+                :interval="4000"
+                indicator-position="none"
+                :arrow="carouselPreviewImages.length > 1 ? 'hover' : 'never'"
+                class="head-preview-carousel"
+              >
+                <el-carousel-item v-for="(url, index) in carouselPreviewImages" :key="index">
+                  <img :src="url" alt="头图" class="carousel-preview-img" />
+                </el-carousel-item>
+              </el-carousel>
+              <div v-else class="carousel-preview-empty">
                 <div class="preview-placeholder">示例图</div>
                 <div class="preview-placeholder">示例图</div>
               </div>
               </div>
               <div class="overlay-button">
               <div class="overlay-button">
@@ -63,9 +72,7 @@
                 :show-success-notification="false"
                 :show-success-notification="false"
               >
               >
                 <template #tip>
                 <template #tip>
-                  <div class="upload-tip">
-                    上传图片{{ formData.multipleImages.length }} ({{ formData.multipleImages.length }}/6)
-                  </div>
+                  <div class="upload-tip">上传图片({{ formData.multipleImages.length }}/6)</div>
                 </template>
                 </template>
               </UploadImgs>
               </UploadImgs>
             </div>
             </div>
@@ -86,6 +93,9 @@ import { ref, reactive, computed, onMounted, watch, nextTick } from "vue";
 import { ElMessage, ElNotification } from "element-plus";
 import { ElMessage, ElNotification } from "element-plus";
 import type { FormInstance, FormRules } from "element-plus";
 import type { FormInstance, FormRules } from "element-plus";
 import type { UploadUserFile } from "element-plus";
 import type { UploadUserFile } from "element-plus";
+
+/** 服务端图片主键,用于 saveOrUpdateImg 区分更新与新增 */
+type HeadMapUploadFile = UploadUserFile & { serverImgId?: number | string };
 import { ArrowRight } from "@element-plus/icons-vue";
 import { ArrowRight } from "@element-plus/icons-vue";
 import Sortable from "sortablejs";
 import Sortable from "sortablejs";
 import UploadImgs from "@/components/Upload/Imgs.vue";
 import UploadImgs from "@/components/Upload/Imgs.vue";
@@ -147,7 +157,7 @@ const handleStoreOcr = async (params: { imageUrl: string }) => {
 };
 };
 
 
 const formData = reactive({
 const formData = reactive({
-  multipleImages: [] as UploadUserFile[]
+  multipleImages: [] as HeadMapUploadFile[]
 });
 });
 
 
 const previewData = reactive({
 const previewData = reactive({
@@ -155,8 +165,9 @@ const previewData = reactive({
   reviews: 1853
   reviews: 1853
 });
 });
 
 
-const displayImages = computed(() => {
-  return formData.multipleImages.slice(0, 3).map(item => item.url || "");
+/** 预览轮播:展示已上传头图,一次一张 */
+const carouselPreviewImages = computed(() => {
+  return formData.multipleImages.map(item => item.url || "").filter((url): url is string => Boolean(url));
 });
 });
 
 
 /**
 /**
@@ -234,16 +245,17 @@ const getStoreHeadImgData = async () => {
       return;
       return;
     }
     }
 
 
-    const res: any = await getStoreHeadImg(storeId, 21);
+    const res: any = await getStoreHeadImg(storeId, 20);
     if (res && (res.code === 200 || res.code === "200") && res.data) {
     if (res && (res.code === 200 || res.code === "200") && res.data) {
       const dataAny = res.data as any;
       const dataAny = res.data as any;
       const imgList = Array.isArray(dataAny) ? dataAny : dataAny.storeImgList || [];
       const imgList = Array.isArray(dataAny) ? dataAny : dataAny.storeImgList || [];
       if (imgList.length > 0) {
       if (imgList.length > 0) {
         formData.multipleImages = imgList.map((item: any, index: number) => ({
         formData.multipleImages = imgList.map((item: any, index: number) => ({
-          uid: item.id || index,
+          uid: item.id != null ? item.id : `loaded-${index}-${Date.now()}`,
           name: `image-${index + 1}`,
           name: `image-${index + 1}`,
           url: item.imgUrl,
           url: item.imgUrl,
-          status: "success"
+          status: "success",
+          serverImgId: item.id != null ? item.id : undefined
         }));
         }));
         nextTick(() => {
         nextTick(() => {
           initDragSort();
           initDragSort();
@@ -279,12 +291,6 @@ onMounted(async () => {
 
 
 const handleSave = async () => {
 const handleSave = async () => {
   if (!multipleFormRef.value) return;
   if (!multipleFormRef.value) return;
-  try {
-    await multipleFormRef.value.validate();
-  } catch {
-    ElMessage.warning("至少上传3张图片");
-    return;
-  }
 
 
   const userInfo: any = localGet("geeker-user")?.userInfo || {};
   const userInfo: any = localGet("geeker-user")?.userInfo || {};
   const storeId = userInfo.storeId;
   const storeId = userInfo.storeId;
@@ -295,16 +301,23 @@ const handleSave = async () => {
 
 
   loading.value = true;
   loading.value = true;
   try {
   try {
-    const storeImgList = formData.multipleImages.map((item, index) => ({
-      imgType: 21,
-      imgUrl: item.url || "",
-      imgSort: index + 1,
-      storeId: Number(storeId)
-    }));
+    const storeImgList = formData.multipleImages.map((item, index) => {
+      const row: Record<string, unknown> = {
+        imgType: 20,
+        imgUrl: item.url || "",
+        imgSort: index + 1,
+        storeId: Number(storeId)
+      };
+      const sid = (item as HeadMapUploadFile).serverImgId;
+      if (sid != null && sid !== "") {
+        row.id = typeof sid === "string" ? Number(sid) || sid : sid;
+      }
+      return row;
+    });
 
 
     const params = {
     const params = {
       imgMode: 1,
       imgMode: 1,
-      imgType: 21,
+      imgType: 20,
       storeId: Number(storeId),
       storeId: Number(storeId),
       storeImgList
       storeImgList
     };
     };
@@ -350,30 +363,42 @@ const handleSave = async () => {
         border-radius: 8px;
         border-radius: 8px;
         box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
         box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
         transition: all 0.3s;
         transition: all 0.3s;
-        .preview-images-multiple {
+        .preview-images-carousel {
           position: relative;
           position: relative;
-          display: flex;
-          gap: 4px;
           width: 100%;
           width: 100%;
-          height: 200px;
           margin-bottom: 16px;
           margin-bottom: 16px;
-          overflow: hidden;
+          overflow: visible;
           background-color: #f0f0f0;
           background-color: #f0f0f0;
           border-radius: 8px;
           border-radius: 8px;
-          .preview-image-small {
+          .head-preview-carousel {
+            width: 100%;
+            :deep(.el-carousel__container) {
+              height: 200px;
+              border-radius: 8px;
+            }
+            :deep(.el-carousel__item) {
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              overflow: hidden;
+              background-color: #e4e7ed;
+            }
+            :deep(.el-carousel__arrow) {
+              background-color: rgb(0 0 0 / 35%);
+            }
+          }
+          .carousel-preview-img {
+            width: 100%;
+            height: 100%;
+            object-fit: cover;
+          }
+          .carousel-preview-empty {
             display: flex;
             display: flex;
-            flex: 1;
             align-items: center;
             align-items: center;
             justify-content: center;
             justify-content: center;
-            height: 100%;
-            overflow: hidden;
+            height: 200px;
             background-color: #e4e7ed;
             background-color: #e4e7ed;
-            border-radius: 4px;
-            img {
-              width: 100%;
-              height: 100%;
-              object-fit: cover;
-            }
+            border-radius: 8px;
             .preview-placeholder {
             .preview-placeholder {
               font-size: 12px;
               font-size: 12px;
               color: #909399;
               color: #909399;
@@ -383,12 +408,14 @@ const handleSave = async () => {
             position: absolute;
             position: absolute;
             right: 12px;
             right: 12px;
             bottom: 12px;
             bottom: 12px;
+            z-index: 2;
             display: flex;
             display: flex;
             gap: 4px;
             gap: 4px;
             align-items: center;
             align-items: center;
             padding: 6px 12px;
             padding: 6px 12px;
             font-size: 12px;
             font-size: 12px;
             color: white;
             color: white;
+            pointer-events: none;
             background-color: rgb(0 0 0 / 60%);
             background-color: rgb(0 0 0 / 60%);
             border-radius: 4px;
             border-radius: 4px;
           }
           }

+ 80 - 46
src/views/storeDecoration/storeLabel/index.vue

@@ -252,7 +252,7 @@ import { ref, reactive, computed, onMounted } from "vue";
 import { ElMessage } from "element-plus";
 import { ElMessage } from "element-plus";
 import type { FormInstance, FormRules } from "element-plus";
 import type { FormInstance, FormRules } from "element-plus";
 import { localGet } from "@/utils";
 import { localGet } from "@/utils";
-import { getAllTagType, getAllTag, saveTag } from "@/api/modules/storeDecoration";
+import { getTagList, getAllTag, saveTag } from "@/api/modules/storeDecoration";
 
 
 const loading = ref(false);
 const loading = ref(false);
 const formRef = ref<FormInstance>();
 const formRef = ref<FormInstance>();
@@ -359,7 +359,72 @@ const handleSave = async () => {
   }
   }
 };
 };
 
 
-// 初始化表单数据(从接口获取已保存的数据)
+/** 解析 getTagList 记录里的 labelButtonOptionOne / Two(JSON 字符串) */
+function parseLabelButtonOptions(jsonStr: unknown): Array<{ name: string; value: string | number }> {
+  if (jsonStr == null || jsonStr === "") return [];
+  if (typeof jsonStr !== "string") return [];
+  try {
+    const arr = JSON.parse(jsonStr);
+    if (!Array.isArray(arr)) return [];
+    return arr.map((o: any) => ({
+      name: o?.name ?? "",
+      value: o?.value ?? ""
+    }));
+  } catch {
+    return [];
+  }
+}
+
+const FORM_BUTTON_TYPES = ["radioDouble", "radio", "radios", "checkbox"] as const;
+
+/** 将 getTagList 单条 record 转为模板使用的 list 项 */
+function mapTagListRecordToItem(raw: Record<string, any>) {
+  const bt = raw.labelButtonType;
+  const labelButtonType = (FORM_BUTTON_TYPES as readonly string[]).includes(bt) ? bt : "radio";
+  const opt2 = parseLabelButtonOptions(raw.labelButtonOptionTwo);
+  const item: {
+    label: string;
+    labelButtonType: (typeof FORM_BUTTON_TYPES)[number];
+    field_1: string;
+    field_2?: string;
+    field_5?: string;
+    field_7?: string;
+    field_11?: string;
+    tips?: string;
+    labelButtonOption_1: Array<{ name: string; value: string | number }>;
+    labelButtonOption_2?: Array<{ name: string; value: string | number }>;
+  } = {
+    label: raw.label ?? "",
+    labelButtonType: labelButtonType as (typeof FORM_BUTTON_TYPES)[number],
+    field_1: raw.field_1 ?? "",
+    tips: raw.labelDescribe || "",
+    labelButtonOption_1: parseLabelButtonOptions(raw.labelButtonOptionOne)
+  };
+  if (raw.field_2) item.field_2 = raw.field_2;
+  if (opt2.length) item.labelButtonOption_2 = opt2;
+  return item;
+}
+
+/** 根据 getTagList 分页 data 构建 tagGroups(左:基础设施 / 右:门店介绍) */
+function buildTagGroupsFromListPageData(data: Record<string, any> | null | undefined) {
+  const records = Array.isArray(data?.records) ? [...data!.records] : [];
+  records.sort((a: any, b: any) => (Number(a?.tagSort) || 0) - (Number(b?.tagSort) || 0));
+  const infraList: ReturnType<typeof mapTagListRecordToItem>[] = [];
+  const introList: ReturnType<typeof mapTagListRecordToItem>[] = [];
+  for (const r of records) {
+    if (!r || typeof r !== "object") continue;
+    const item = mapTagListRecordToItem(r as Record<string, any>);
+    const lt = (r as Record<string, any>).labelType;
+    if (lt === "infrastructure") infraList.push(item);
+    else if (lt === "storeIntroduction") introList.push(item);
+  }
+  const groups: typeof tagGroups.value = [];
+  if (infraList.length) groups.push({ labelName: "基础设施", list: infraList });
+  if (introList.length) groups.push({ labelName: "门店介绍", list: introList });
+  return groups;
+}
+
+// 初始化表单数据(门店已选值:与标签定义分离,仍走原门店关系接口)
 const initFormData = async () => {
 const initFormData = async () => {
   try {
   try {
     const userInfo: any = localGet("geeker-user")?.userInfo || {};
     const userInfo: any = localGet("geeker-user")?.userInfo || {};
@@ -369,12 +434,9 @@ const initFormData = async () => {
       return;
       return;
     }
     }
 
 
-    // 调用获取门店标签数据接口 getAllTag API
     const res: any = await getAllTag({ storeId: Number(storeId) });
     const res: any = await getAllTag({ storeId: Number(storeId) });
     if (res && (res.code === 200 || res.code === "200") && res.data) {
     if (res && (res.code === 200 || res.code === "200") && res.data) {
-      // 将接口返回的数据合并到formData中
       Object.assign(formData, res.data);
       Object.assign(formData, res.data);
-      // 处理checkbox类型的数据(如果是字符串,需要转换为数组)
       tagGroups.value.forEach(group => {
       tagGroups.value.forEach(group => {
         group.list.forEach(item => {
         group.list.forEach(item => {
           if (item.labelButtonType === "checkbox" && item.field_1) {
           if (item.labelButtonType === "checkbox" && item.field_1) {
@@ -383,11 +445,9 @@ const initFormData = async () => {
             if (value && typeof value === "string") {
             if (value && typeof value === "string") {
               formData[fieldName] = value.split(",").filter(Boolean);
               formData[fieldName] = value.split(",").filter(Boolean);
             } else if (!value) {
             } else if (!value) {
-              // 如果字段不存在,初始化为空数组
               formData[fieldName] = [];
               formData[fieldName] = [];
             }
             }
           } else if (item.field_1 && formData[item.field_1] === undefined) {
           } else if (item.field_1 && formData[item.field_1] === undefined) {
-            // 其他类型字段如果不存在,初始化为空值
             formData[item.field_1] = "";
             formData[item.field_1] = "";
           }
           }
         });
         });
@@ -398,50 +458,24 @@ const initFormData = async () => {
   }
   }
 };
 };
 
 
-// 初始化标签选项(从接口获取标签列表)
+// 初始化标签结构(渲染用):来自 getTagList 的 records
 const initTagOptions = async () => {
 const initTagOptions = async () => {
   try {
   try {
-    // 从userInfo中获取businessSection
-    const userInfo: any = localGet("geeker-user")?.userInfo || {};
-    const businessSection = userInfo.businessSection || localGet("businessSection") || "";
-
-    if (!businessSection) {
-      console.warn("未找到businessSection参数");
+    const first: any = await getTagList({ pageNum: 1, pageSize: 1 });
+    if (!(first && (first.code === 200 || first.code === "200") && first.data)) {
       return;
       return;
     }
     }
-
-    // 调用获取标签列表接口 getAllTagType API
-    const res: any = await getAllTagType({ businessSection });
-    if (res && (res.code === 200 || res.code === "200") && res.data) {
-      const dataList = Array.isArray(res.data) ? res.data : [];
-
-      // 处理checkbox类型的已选状态
-      dataList.forEach((item: any) => {
-        if (item.labelButtonType === "checkbox") {
-          item.labelButtonOption_1.forEach((option: any) => {
-            if (formData[item.field_1] && formData[item.field_1].indexOf(option.value) !== -1) {
-              option.isChecked = true;
-            }
-          });
-        }
-      });
-
-      // 按labelName分组
-      const grouped = dataList.reduce((acc: any[], current: any) => {
-        const existing = acc.find(item => item.labelName === current.labelName);
-        if (existing) {
-          existing.list.push(current);
-        } else {
-          acc.push({
-            labelName: current.labelName,
-            list: [current]
-          });
-        }
-        return acc;
-      }, []);
-
-      tagGroups.value = grouped;
+    const recLen = first.data.records?.length ?? 0;
+    const apiTotal = Number(first.data.total);
+    const targetSize = Number.isFinite(apiTotal) && apiTotal > 0 ? Math.min(apiTotal, 500) : Math.min(Math.max(recLen, 1), 500);
+    let pageData = first.data;
+    if (targetSize > recLen) {
+      const full: any = await getTagList({ pageNum: 1, pageSize: targetSize });
+      if (full && (full.code === 200 || full.code === "200") && full.data) {
+        pageData = full.data;
+      }
     }
     }
+    tagGroups.value = buildTagGroupsFromListPageData(pageData);
   } catch (error) {
   } catch (error) {
     console.error("获取标签列表失败:", error);
     console.error("获取标签列表失败:", error);
   }
   }

+ 4 - 4
src/views/ticketManagement/index.vue

@@ -240,10 +240,10 @@ const voucherColumns = reactive<ColumnProps<any>[]>([
     }
     }
   },
   },
   {
   {
-    prop: "endDate",
+    prop: "validDate",
     label: "结束时间",
     label: "结束时间",
     render: (scope: any) => {
     render: (scope: any) => {
-      return scope.row.endDate?.replace(/-/g, "/") || "--";
+      return scope.row.validDate?.replace(/-/g, "/") || "--";
     }
     }
   },
   },
   {
   {
@@ -279,10 +279,10 @@ const couponColumns = reactive<ColumnProps<any>[]>([
     }
     }
   },
   },
   {
   {
-    prop: "endGetDate",
+    prop: "validDate",
     label: "结束时间",
     label: "结束时间",
     render: (scope: any) => {
     render: (scope: any) => {
-      return scope.row.endGetDate?.replace(/-/g, "/") || "--";
+      return scope.row.validDate?.replace(/-/g, "/") || "--";
     }
     }
   },
   },
   {
   {