Răsfoiți Sursa

页面建立

congxuesong 1 lună în urmă
părinte
comite
ace0785124

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

@@ -44,7 +44,22 @@
           }
         },
         {
-          "path": "/groupPackageManagementDetail",
+          "path": "/groupPackageManagement/newGroup",
+          "name": "groupPackageManagementNewGroup",
+          "component": "/groupPackageManagement/newGroup",
+          "meta": {
+            "icon": "Menu",
+            "title": "新建团购",
+            "activeMenu": "/groupPackageManagement",
+            "isLink": "",
+            "isHide": true,
+            "isFull": false,
+            "isAffix": false,
+            "isKeepAlive": false
+          }
+        },
+        {
+          "path": "/groupPackageManagement/detail",
           "name": "groupPackageManagementDetail",
           "component": "/groupPackageManagement/detail",
           "meta": {

+ 181 - 92
src/views/groupPackageManagement/index.vue

@@ -3,32 +3,56 @@
     <ProTable ref="proTable" :columns="columns" :request-api="getTableList" :init-param="initParam" :data-callback="dataCallback">
       <!-- 表格 header 按钮 -->
       <template #tableHeader="scope">
-        <el-button type="primary" :icon="Download" @click="exportInfoExcel(scope)"> 导出 </el-button>
+        <div class="table-header-btn">
+          <el-button :icon="Plus" class="button" type="primary" @click="newGroupBuying"> 新建团购 </el-button>
+          <el-tabs v-model="activeName" class="tabs" @tab-click="handleClick">
+            <el-tab-pane v-for="tab in tabOptions" :key="tab.name" :label="tab.label" :name="tab.name" />
+          </el-tabs>
+        </div>
+      </template>
+      <template #Information="scope">
+        <div>
+          <el-image :src="scope.row.homeImage" />
+          <div>
+            <p>团购名称:{{ scope.row.goodsName }}</p>
+            <p>团购编号:{{ scope.row.goodsDesc }}</p>
+            <p>结束时间:{{ scope.row.goodsDesc }}</p>
+          </div>
+        </div>
       </template>
-      <template #expand="scope">
-        {{ scope.row }}
+      <template #status="scope">
+        <p>团购状态:{{ scope.row.status }}</p>
+        <p>审核状态:{{ scope.row.status }}</p>
       </template>
       <!-- 表格操作 -->
       <template #operation="scope">
         <!-- 审批通过和拒绝按钮仅在状态为0时显示 -->
         <template v-if="scope.row.status === '0'">
-          <el-button type="primary" link @click="changeTypes(scope.row, 'pass')"> 审核通过 </el-button>
-          <el-button type="primary" link @click="changeTypes(scope.row, '')"> 审核拒绝 </el-button>
+          <el-button link type="primary" @click="changeTypes(scope.row, 'on')"> 上架 </el-button>
+          <el-button link type="primary" @click="changeTypes(scope.row, 'off')"> 下架 </el-button>
+          <el-button link type="primary" @click="changeInventory(scope.row)"> 修改库存 </el-button>
         </template>
         <el-button type="primary" link @click="toDetail(scope.row)"> 查看详情 </el-button>
+        <el-button link type="primary" @click="editRow(scope.row)"> 编辑 </el-button>
+        <el-button link type="primary" @click="deleteRow(scope.row)"> 删除 </el-button>
       </template>
     </ProTable>
-
-    <el-dialog v-model="dialogFormVisible" title="审核拒绝" width="500">
-      <el-form :model="form">
-        <el-form-item label="" label-width="0">
-          <el-input v-model="form.comment" autocomplete="off" type="textarea" maxlength="200" />
+    <el-dialog v-model="dialogFormVisible" title="修改库存" width="500">
+      <el-form ref="ruleFormRef" :model="formInventory" :rules="rules" @submit.prevent>
+        <el-form-item label="套餐名">
+          {{ formInventory.packageName }}
+        </el-form-item>
+        <el-form-item label="剩余库存">
+          {{ formInventory.remainingInventory }}
+        </el-form-item>
+        <el-form-item label="修改库存" prop="newInventory">
+          <el-input v-model="formInventory.newInventory" placeholder="请输入" />
         </el-form-item>
       </el-form>
       <template #footer>
         <div class="dialog-footer">
           <el-button @click="closeDialog"> 取消 </el-button>
-          <el-button type="primary" @click="handleSubmit"> 驳回 </el-button>
+          <el-button type="primary" @click="handleSubmit"> 确定 </el-button>
         </div>
       </template>
     </el-dialog>
@@ -36,42 +60,129 @@
 </template>
 
 <script setup lang="tsx" name="groupPackageManagement">
-import { ref, reactive, onMounted, onActivated } from "vue";
+import { onActivated, onMounted, reactive, ref } from "vue";
 import { useRouter } from "vue-router";
+import type { FormInstance, FormRules } from "element-plus";
 import { ElMessage } from "element-plus";
 import ProTable from "@/components/ProTable/index.vue";
-import { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
-import { Download } from "@element-plus/icons-vue";
-import { audit, exportExcelStaffConfig, getStaffConfigList } from "@/api/modules/staffConfig";
+import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface";
+import { Plus } from "@element-plus/icons-vue";
+import { audit, getStaffConfigList } from "@/api/modules/staffConfig";
 
 const router = useRouter();
 const dialogFormVisible = ref(false);
-const form = reactive({
-  comment: ""
+const formInventory: any = ref({
+  id: "",
+  packageName: "",
+  remainingInventory: "",
+  newInventory: ""
 });
-
 const rowData = ref<any>();
+const activeName = ref("0");
 
+const ruleFormRef = ref<FormInstance>();
+const rules = reactive<FormRules<RuleForm>>({
+  newInventory: [
+    { required: true, message: "请输入库存数量", trigger: "blur" },
+    {
+      pattern: /^(0|[1-9][0-9]*)$/,
+      message: "请输入整数,不允许输入小数,负数",
+      trigger: "blur"
+    }
+  ]
+});
 const statusEnum = [
   { value: "0", label: "待审核" },
   { value: "1", label: "审核通过" },
   { value: "2", label: "审核拒绝" }
 ];
-// 如果表格需要初始化请求参数,直接定义传给 ProTable (之后每次请求都会自动带上该参数,此参数更改之后也会一直带上,改变此参数会自动刷新表格数据)
-const initParam = reactive({});
 
-// 定义 filterValues
-const filterValues = reactive({});
+// 表格配置项
+const columns = reactive<ColumnProps<any>[]>([
+  {
+    prop: "index",
+    label: "序号",
+    width: 100,
+    render: (scope: any) => {
+      return scope.$index + (proTable.value!.pageable.pageNum - 1) * proTable.value!.pageable.pageSize + 1;
+    }
+  },
+  {
+    prop: "tradeNo",
+    label: "团购名称",
+    isShow: false,
+    search: {
+      el: "input"
+    }
+  },
+  {
+    prop: "goodsId",
+    label: "团购编号",
+    isShow: false,
+    search: {
+      el: "input"
+    }
+  },
+  {
+    prop: "Information",
+    label: "团购信息"
+  },
+  {
+    prop: "goodsId",
+    label: "已售"
+  },
+  {
+    prop: "goodsId",
+    isShow: false,
+    label: "剩余库存"
+  },
+  {
+    prop: "goodsId",
+    label: "优惠价"
+  },
+  {
+    prop: "goodsId",
+    label: "成本价"
+  },
+  {
+    prop: "goodsId",
+    label: "利润"
+  },
+  {
+    prop: "tradeStatus",
+    label: "审核状态",
+    isShow: false,
+    render: scope => {
+      const statusObj = statusEnum.find(item => item.value === scope.row.tradeStatus);
+      return statusObj ? statusObj.label : "--";
+    },
+    search: {
+      el: "select"
+    },
+    enum: statusEnum,
+    fieldNames: { label: "label", value: "value" }
+  },
+  {
+    prop: "status",
+    label: "状态"
+  },
+  { prop: "operation", label: "操作", fixed: "right", width: 330 }
+]);
 
-const getStatusObj = (statusValue: string) => {
-  const statusObj = statusEnum.find(item => item.value === statusValue);
-  if (statusObj) {
-    filterValues.status = statusObj;
-  } else {
-    filterValues.status = "";
-  }
-  return statusObj;
-};
+// 在 script setup 中添加
+const tabOptions = [
+  { label: "全部", name: "0" },
+  { label: "草稿", name: "1" },
+  { label: "进行中", name: "2" },
+  { label: "未开始", name: "3" },
+  { label: "已下架", name: "4" },
+  { label: "已售罄", name: "5" },
+  { label: "已结束", name: "6" }
+];
+// 如果表格需要初始化请求参数,直接定义传给 ProTable (之后每次请求都会自动带上该参数,此参数更改之后也会一直带上,改变此参数会自动刷新表格数据)
+const initParam = reactive({
+  activeName: activeName
+});
 
 // ProTable 实例
 const proTable = ref<ProTableInstance>();
@@ -104,45 +215,33 @@ const getTableList = (params: any) => {
 
 // 跳转详情页
 const toDetail = row => {
-  router.push(`/store/groupPackageManagementDetail?id=${row.id}`);
+  router.push(`/groupPackageManagement/detail?id=${row.id}`);
 };
-
-// 表格配置项
-const columns = reactive<ColumnProps<any>[]>([
-  { type: "index", fixed: "left", label: "序号", width: 130 },
-  { prop: "storeName", label: "所属店铺" },
-  { prop: "name", label: "名称" },
-  { prop: "description", label: "描述" },
-  {
-    prop: "status",
-    label: "状态",
-    render: scope => {
-      const statusObj = getStatusObj(scope.row.status);
-      return statusObj ? statusObj.label : "未知状态";
-    },
-    search: {
-      el: "select"
-    },
-    enum: statusEnum,
-    fieldNames: { label: "label", value: "value" }
-  },
-  { prop: "operation", label: "操作", fixed: "right", width: 330 }
-]);
-
+const editRow = row => {};
+const deleteRow = row => {};
+const newGroupBuying = () => {
+  router.push(`/groupPackageManagement/newGroup?id=1`);
+};
+const handleClick = () => {};
 const changeTypes = (row: any, status: string) => {
   rowData.value = row;
-  if (status === "pass") {
+  if (status === "on") {
     handleChangeStatus(row, "1");
   } else {
-    form.comment = "";
-    dialogFormVisible.value = true;
+    handleChangeStatus(row, "2");
   }
 };
-
+const changeInventory = (row: any) => {
+  formInventory.value.id = 1;
+  formInventory.value.packageName = 1;
+  formInventory.value.remainingInventory = 1;
+  formInventory.value.newInventory = "";
+  dialogFormVisible.value = true;
+};
 const handleChangeStatus = async (row: any, status: string) => {
   try {
     let res = await audit({ id: row.id, status: status, rejectionReason: form.comment });
-    if (res.code === 200) {
+    if (res.code == 200) {
       proTable.value?.getTableList();
       if (status === "2") closeDialog();
       ElMessage.success("审核成功");
@@ -152,43 +251,25 @@ const handleChangeStatus = async (row: any, status: string) => {
   }
 };
 
-// 导出信息
-const exportInfoExcel = async scope => {
-  let res;
-  // 获取原始状态值(可能为数字、字符串或 undefined)
-  const rawStatus = proTable.value.searchParam.status;
-  // 转换为字符串(处理 undefined/null 为 "" 或保留原始字符串)
-  const statusParam = rawStatus !== undefined && rawStatus !== null ? String(rawStatus) : undefined;
-  // 将筛选条件作为参数传递给后台
-  res = await exportExcelStaffConfig({ status: statusParam });
-  if (res.code === 200) {
-    if (!res.data) {
-      ElMessage.error("暂无可下载数据");
-      return;
-    }
-    const exportFile = document.createElement("a");
-    exportFile.style.display = "none";
-    exportFile.download = `团购管理.xlsx`;
-    exportFile.href = `${res.data}?timestamp=${new Date().getTime()}`; // 添加时间戳防止缓存
-    document.body.appendChild(exportFile);
-    exportFile.click();
-    document.body.removeChild(exportFile);
-    ElMessage.success("下载成功");
-  }
-};
-
 // 弹窗提交
-const handleSubmit = () => {
-  if (!form.comment) {
-    ElMessage.error("请输入审批意见");
-    return;
-  }
-  handleChangeStatus(rowData.value, "2");
+const handleSubmit = async () => {
+  if (!ruleFormRef.value) return;
+  await ruleFormRef.value.validate((valid, fields) => {
+    if (valid) {
+      ElMessage.success("修改成功");
+      dialogFormVisible.value = false;
+    }
+  });
 };
 // 关闭弹窗;
 const closeDialog = () => {
   dialogFormVisible.value = false;
-  form.comment = "";
+  formInventory.value = {
+    id: "",
+    packageName: "",
+    remainingInventory: "",
+    newInventory: ""
+  };
 };
 </script>
 
@@ -200,4 +281,12 @@ const closeDialog = () => {
   word-wrap: break-word; // 长单词内换行
   white-space: normal; // 允许自然换行
 }
+.table-header-btn {
+  .tabs {
+    margin-top: 10px;
+    :deep(.el-tabs__nav-wrap::after) {
+      height: 0;
+    }
+  }
+}
 </style>

+ 718 - 0
src/views/groupPackageManagement/newGroup.vue

@@ -0,0 +1,718 @@
+<template>
+  <div class="table-box" style="width: 100%; min-height: 100%; background-color: white">
+    <div class="content">
+      <div class="contentLeft">
+        <!-- 商铺信息设置模块 -->
+        <div class="model">
+          <h3 style="font-weight: bold">基础信息:</h3>
+          <el-form :model="storeInfoModel" ref="ruleFormRef1" :rules="rules" label-width="120px" class="formBox">
+            <el-form-item label="图片" prop="fileList">
+              <template v-if="isDisabled">
+                <div
+                  v-for="(item, idx) in storeInfoModel.fileList"
+                  :key="item.url || idx"
+                  style="width: 150px; height: 150px; overflow: hidden; border: 1px solid rgb(0 0 0 / 10%); border-radius: 6px"
+                >
+                  <el-image :src="item.url" style="width: 100%; height: 100%" fit="contain" />
+                </div>
+              </template>
+              <el-upload
+                v-else
+                v-model:file-list="storeInfoModel.fileList"
+                :action="uploadUrl"
+                list-type="picture-card"
+                :accept="'.jpg,.png'"
+                :limit="9"
+                :on-preview="handlePictureCardPreview"
+                :on-remove="handleRemove"
+                :on-success="handleSuccess"
+                :show-file-list="true"
+              >
+                <el-icon>
+                  <Plus />
+                </el-icon>
+              </el-upload>
+            </el-form-item>
+            <el-form-item label="团购名称" prop="storeName">
+              <el-input maxlength="50" v-model="storeInfoModel.storeName" placeholder="请填写团购名称" clearable />
+            </el-form-item>
+            <el-form-item label="开始售卖时间" prop="storeStatus">
+              <el-radio-group v-model="storeInfoModel.storeStatus" class="ml-4">
+                <el-radio v-for="status in storeStatusList" :value="status.value" :key="status.value">
+                  {{ status.label }}
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="" prop="startTime" v-show="storeInfoModel.storeStatus == 1">
+              <el-date-picker
+                v-model="storeInfoModel.startTime"
+                format="YYYY/MM/DD hh:mm:ss"
+                value-format="YYYY-MM-DD h:m:s"
+                type="datetime"
+                placeholder="请选择开始售卖时间"
+              />
+            </el-form-item>
+            <el-form-item label="结束售卖时间" prop="endTime">
+              <el-date-picker
+                v-model="storeInfoModel.endTime"
+                format="YYYY/MM/DD hh:mm:ss"
+                value-format="YYYY-MM-DD h:m:s"
+                type="datetime"
+                placeholder="请选择结束售卖时间"
+              />
+            </el-form-item>
+            <el-form-item label="库存数量" prop="storeTel">
+              <el-input v-model="storeInfoModel.storeTel" maxlength="15" placeholder="请填写库存数量" clearable />
+            </el-form-item>
+            <el-form-item label="每人限购" prop="purchaseLimitPerPerson">
+              <el-radio-group v-model="storeInfoModel.purchaseLimitPerPerson" class="ml-4">
+                <el-radio v-for="status in perList" :value="status.value" :key="status.value">
+                  {{ status.label }}
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="" prop="purchaseLimit" v-show="storeInfoModel.purchaseLimitPerPerson == 1">
+              <el-input v-model="storeInfoModel.purchaseLimit" maxlength="15" placeholder="请填写自定义限购数量" clearable />
+            </el-form-item>
+            <el-form-item label="容纳人数" prop="storeCapacity">
+              <el-input-number
+                type="storeCapacity"
+                :disabled="isDisabled"
+                v-model="storeInfoModel!.storeCapacity"
+                placeholder="容纳人数"
+                clearable
+                :min="0"
+                :max="9999999"
+              />
+            </el-form-item>
+            <el-form-item label="门店面积" prop="storeArea">
+              <el-radio-group :disabled="isDisabled" v-model="storeInfoModel!.storeArea" class="ml-4">
+                <el-radio v-for="storeArea in storeAreaList" :value="storeArea.value" :key="storeArea.value">
+                  {{ storeArea.label }}
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <!--            <el-form-item label="是否连锁" prop="isChain">-->
+            <!--              <el-radio-group :disabled="isDisabled" v-model="storeInfoModel!.isChain" class="ml-4">-->
+            <!--                <el-radio label="0" :value="0"> 否 </el-radio>-->
+            <!--                <el-radio label="1" :value="1"> 是 </el-radio>-->
+            <!--              </el-radio-group>-->
+            <!--            </el-form-item>-->
+            <el-form-item label="详细地址" prop="storeAddress">
+              <el-input
+                maxlength="100"
+                :disabled="isDisabled"
+                v-model="storeInfoModel!.storeAddress"
+                :rows="2"
+                type="textarea"
+                placeholder="请输入详细地址"
+              />
+            </el-form-item>
+            <el-form-item label="行政区域" prop="district">
+              <el-cascader :props="props" :disabled="isDisabled" v-model="storeInfoModel!.district" style="width: 100%" />
+            </el-form-item>
+            <el-form-item label="门店简介" prop="storeBlurb">
+              <el-input
+                maxlength="100"
+                :disabled="isDisabled"
+                v-model="storeInfoModel!.storeBlurb"
+                :rows="2"
+                type="textarea"
+                placeholder="请输入门店简介"
+              />
+            </el-form-item>
+          </el-form>
+        </div>
+        <div class="model">
+          <h3 style="font-weight: bold">价格:</h3>
+          <el-form :model="storeInfoModel" ref="ruleFormRef2" :rules="rules" label-width="120px" class="formBox">
+            <el-form-item label="原价" prop="price">
+              <el-input maxlength="50" v-model="storeInfoModel.price" placeholder="请填写原价" clearable />
+            </el-form-item>
+            <el-form-item label="优惠价" prop="discountedPrice">
+              <el-input maxlength="50" v-model="storeInfoModel.discountedPrice" placeholder="请填写优惠价" clearable />
+            </el-form-item>
+          </el-form>
+        </div>
+      </div>
+      <div class="contentRight">
+        <div class="model">
+          <h3 style="font-weight: bold">购买须知:</h3>
+          <el-form :model="storeInfoModel" ref="ruleFormRef3" :rules="rules" label-width="120px" class="formBox">
+            <el-form-item label="预约规则" prop="appointmentRules">
+              <el-input
+                maxlength="300"
+                v-model="storeInfoModel.appointmentRules"
+                :rows="4"
+                type="textarea"
+                placeholder="请输入预约规则"
+              />
+            </el-form-item>
+            <el-form-item label="使用规则" prop="rulesOfUse">
+              <el-input
+                maxlength="300"
+                v-model="storeInfoModel.rulesOfUse"
+                :rows="4"
+                type="textarea"
+                placeholder="请输入详细地址"
+              />
+            </el-form-item>
+            <el-form-item label="适用人数" prop="numberOfPeople">
+              <el-input v-model="storeInfoModel.numberOfPeople" maxlength="15" placeholder="请填写适用人数" clearable />
+            </el-form-item>
+            <el-form-item label="其他规则" prop="otherRules">
+              <el-input
+                maxlength="300"
+                v-model="storeInfoModel.otherRules"
+                :rows="4"
+                type="textarea"
+                placeholder="请输入详细地址"
+              />
+            </el-form-item>
+            <el-form-item label="发票信息" prop="businessTypes">
+              <el-checkbox-group v-model="storeInfoModel.businessTypes">
+                <el-checkbox v-for="bt in businessTypes" :key="bt.value" :value="bt.value" :label="bt.label">
+                  {{ bt.label }}
+                  <el-tooltip
+                    class="box-item"
+                    effect="dark"
+                    content="指射箭、射击、赛车、攀岩、滑翔伞、滑雪滑冰等"
+                    placement="top"
+                  >
+                    <el-icon v-if="bt.label == '休闲运动'" :size="13">
+                      <QuestionFilled />
+                    </el-icon>
+                  </el-tooltip>
+                </el-checkbox>
+              </el-checkbox-group>
+            </el-form-item>
+            <el-form-item label="发票说明" prop="invoiceDescription">
+              <el-input v-model="storeInfoModel.invoiceDescription" maxlength="15" placeholder="请填写发票说明" clearable />
+            </el-form-item>
+          </el-form>
+          <el-button v-if="type != 'show'" type="primary" @click="handleSubmit"> 确定 </el-button>
+        </div>
+      </div>
+    </div>
+    <!--图片预览-->
+    <el-dialog v-model="imagePopupVisible" title="预览" width="30%">
+      <el-image style="width: 100%" :src="previewImage" fit="contain" />
+    </el-dialog>
+    <el-button @click="goBack"> 返回 </el-button>
+  </div>
+</template>
+
+<script setup lang="tsx" name="useProTable">
+import { ref, reactive, computed, onMounted, nextTick } from "vue";
+import { StoreUser } from "@/api/interface";
+import { ElMessage } from "element-plus";
+import ProTable from "@/components/ProTable/index.vue";
+import ImportExcel from "@/components/ImportExcel/index.vue";
+import StoreUserDrawer from "@/views/proTable/components/StoreUserDrawer.vue";
+import { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
+import {
+  CirclePlus,
+  Delete,
+  EditPen,
+  Download,
+  Upload,
+  Refresh,
+  Check,
+  Close,
+  Search,
+  QuestionFilled
+} from "@element-plus/icons-vue";
+import {
+  getStoreUserList,
+  addStoreUser,
+  editStoreUser,
+  deleteStoreUser,
+  resetStoreUserPassWord,
+  getStoreAuditStatus,
+  getBusinessSection,
+  getBusinessSectionTypes,
+  getUnboundAccountList,
+  addBusinessSectionAndTypes,
+  saveStoreInfo,
+  getStoreDetail,
+  editStoreInfo,
+  getInputPrompt,
+  getDistrict
+} from "@/api/modules/storeUser";
+import { useHandleData } from "@/hooks/useHandleData";
+import { useRouter, useRoute } from "vue-router";
+import type { UploadProps, UploadUserFile, FormInstance } from "element-plus";
+import { forEach } from "lodash";
+
+const imagePopupVisible = ref(false);
+
+const rules = reactive({
+  fileList: [{ required: true, message: "请上传图片" }],
+  storeName: [{ required: true, message: "请填写团购名称" }],
+  storeStatus: [{ required: true, message: "请选择开始售卖时间" }],
+  startTime: [{ required: true, message: "请选择开始售卖时间" }],
+  endTime: [{ required: true, message: "请选择结束售卖时间" }],
+  storeTel: [{ required: true, message: "请填写库存数量" }],
+  purchaseLimitPerPerson: [{ required: true, message: "请选择每人限购" }],
+  purchaseLimit: [{ required: true, message: "请输入每人限购" }],
+  price: [{ required: true, message: "请输入原价" }],
+  discountedPrice: [{ required: true, message: "请输入优惠价" }],
+  appointmentRules: [{ required: true, message: "请输入预约规则" }],
+  rulesOfUse: [{ required: true, message: "请输入使用规则" }],
+  numberOfPeople: [{ required: true, message: "请输入适用人数" }],
+  otherRules: [{ required: true, message: "请输入其他规则" }],
+  businessTypes: [{ required: true, message: "请选择发票信息" }],
+  invoiceDescription: [{ required: true, message: "请输入发票说明" }],
+  storeContact: [{ required: true, message: "请填写联系人" }],
+  name: [{ required: true, message: "请填写联系人" }],
+  storePhone: [{ required: true, message: "请填写联系人电话" }],
+  phone: [{ required: true, message: "请填写联系人电话" }],
+  password: [{ required: true, message: "请填写密码" }],
+  payPassword: [{ required: true, message: "请填写支付密码" }],
+  storeCapacity: [{ required: true, message: "请填写容纳人数" }],
+  isChain: [{ required: true, message: "请选择是否连锁" }],
+  district: [{ required: true, message: "请选择行政区域" }],
+  storeBlurb: [{ required: true, message: "请输入门店简介" }],
+  storeTypeList: [{ required: true, message: "请选择经营种类" }],
+  businessStatus: [{ required: true, message: "请选择门店营业状态" }],
+  storePositionLongitude: [{ required: true, message: "请选择门店经度" }],
+  storePositionLatitude: [{ required: true, message: "请选择门店纬度" }],
+  foodLicenceExpirationTime: [{ required: true, message: "请选择门店经营许可证到期时间" }],
+  storePass: [{ required: true, message: "请输入门店密码" }],
+  storeArea: [{ required: true, message: "请选择门店面积" }],
+  businessSection: [{ required: true, message: "请选择经营板块" }],
+
+  userAccount: [{ required: true, message: "请选择用户账号" }],
+  contractImage: [{ required: true, message: "请上传合同图片" }],
+  foodLicenceImage: [{ required: true, message: "请上传食品经营许可证图片" }],
+  commissionRate: [{ required: true, message: "请填写抽成比例" }],
+  // createdTime: [{ required: true, message: "请选择创建时间" }],
+  storeApplicationStatus: [{ required: true, message: "请填写审核状态" }]
+  // reason: [{ required: true, message: "请填写拒绝原因" }],
+});
+//文件上传地址
+const uploadUrl = ref(`${import.meta.env.VITE_API_URL_STORE}/file/upload`);
+//行政区域组件
+const props: any = {
+  lazy: true,
+  async lazyLoad(node, resolve) {
+    const { level } = node;
+    try {
+      let param = { adCode: node.data.adCode ? node.data.adCode : "" };
+      // 调用后台接口获取数据
+      const response: any = await getDistrict(param as any);
+      // 转换数据格式
+      const nodes = (response?.data?.districts?.[0]?.districts || []).map((item: any) => ({
+        value: item.adcode,
+        adCode: item.adcode,
+        label: item.name,
+        leaf: level >= 2 // 假设最多三级,可以根据实际需求调整
+      }));
+
+      // 返回数据
+      resolve(nodes);
+    } catch (error) {
+      console.error("获取区域数据失败:", error);
+      resolve([]);
+    }
+  }
+};
+const fileList = ref<UploadUserFile[]>([]);
+
+const router = useRouter();
+const route = useRoute();
+const InputRef = ref<any>();
+//页面操作列是否禁用
+const isDisabled = ref<boolean>(false);
+//进入页面类型(新增:add,查看:show,编辑:edit)
+//用户账号
+const userAccountModel = ref<any>({ userAccount: "" });
+//新增板块
+const storeSectionModel = ref<any>({ sectionName: "", types: [] });
+//页面展开类型
+const type = ref<string>("");
+//页面id参数
+const id = ref<string>("");
+//地址名称
+const addressName = ref<string>("");
+//查询地址名称
+const queryAddress = ref<string>("");
+//地址集合
+const addressList = ref<any[]>([]);
+
+//商铺信息模块
+const storeInfoModel = ref<any>({
+  //店铺名称
+  storeName: "",
+  //容纳人数
+  storeCapacity: "1",
+  //门店电话
+  storeTel: "",
+  //门店面积
+  storeArea: 1,
+  //是否连锁
+  isChain: 1,
+  //详细地址
+  storeAddress: "",
+  //门店简介
+  storeBlurb: "",
+  //经营板块
+  businessSection: "1",
+  //经营种类
+  businessTypes: [],
+  //营业执照
+  fileList: [],
+  //用户账号id
+  userAccount: "",
+  //门店状态
+  storeStatus: 1,
+  purchaseLimitPerPerson: 0,
+  //门店营业状态
+  businessStatus: 0,
+  //行政区域
+  district: [],
+  // 抽成比例
+  commissionRate: "3",
+  // 创建时间
+  createdTime: "",
+  // 审核状态
+  storeApplicationStatus: "",
+  // 拒绝原因
+  reason: ""
+});
+//用户列表
+const userOptions = ref<StoreUser.UserOptions[]>([]);
+//用户经营板块对话框开启标识
+const addSectionDialogVisible = ref<boolean>(false);
+//添加板块类型开启标识
+const sectionTypeVisable = ref<boolean>(false);
+//添加板块类型值
+const sectionTypeValue = ref<string>("");
+//添加板块类型名称
+const sectionSectionName = ref<string>("");
+//添加板块类型英文值
+const businessTypeValue = ref<string>("");
+//添加板块类型名称
+const sectionSectionTypes = ref<string[]>([]);
+//营业执照图片集合
+const videoUrlList = ref<string[]>([]);
+//合同图片集合
+const contractImageList = ref<string[]>([]);
+//合同图片集合
+const foodLicenceImageList = ref<string[]>([]);
+
+// 门店面积列表
+const storeAreaList = ref<any[]>([
+  { value: 1, label: "小于20平米" },
+  { value: 2, label: "20~50平米" },
+  { value: 3, label: "50~100平米" },
+  { value: 4, label: "100~300平米" },
+  { value: 5, label: "300~500平米" },
+  { value: 6, label: "500~1000平米" },
+  { value: 7, label: "大于1000平米" }
+]);
+// 经营板块列表
+const businessSectionList = ref<any[]>([]);
+//经营种类列表
+const businessTypes = ref<any[]>([
+  { value: 1, label: "提供电子发票" },
+  { value: 2, label: "提供纸质发票" }
+]);
+//获取用户列表
+const getUserOptions = async () => {
+  let res: any = await getUnboundAccountList({ id: id.value } as any);
+  //todo 此处修改成调用接口
+  // let a = { name: "张三", id: 1 };
+  // let b = { name: "李四", id: 2 };
+  (res?.data || []).forEach((element: any) => {
+    let addData = {
+      name: `${element.phone}(${element.name ? element.name : "未知"})`,
+      id: element.id
+    };
+    userOptions.value.push(addData);
+  });
+};
+const storeStatusList = ref<any[]>([
+  { value: 0, label: "审核通过后立即开始" },
+  { value: 1, label: "设置售卖时间" }
+]);
+const perList = ref<any[]>([
+  { value: 0, label: "不限量" },
+  { value: 1, label: "自定义限购数量" }
+]);
+// 门店营业状态列表
+const businessStatusList = ref<any[]>([
+  { value: 0, label: "正常营业" },
+  { value: 1, label: "暂停营业" },
+  { value: 2, label: "筹建中" },
+  { value: 99, label: "永久关门" }
+]);
+//新增经营板块
+const addSection = () => {
+  addSectionDialogVisible.value = true;
+};
+//关闭新增经营板块弹窗
+const closeSection = () => {
+  sectionSectionName.value = "";
+  businessTypeValue.value = "";
+  sectionSectionTypes.value = [];
+  addSectionDialogVisible.value = false;
+};
+//删除门店经营板块分类
+const handleClose = (tag: string) => {
+  storeSectionModel.value.types.splice(storeSectionModel.value.types.indexOf(tag), 1);
+};
+//新增标签
+const handleInputConfirm = () => {
+  if (sectionTypeValue.value) {
+    sectionSectionTypes.value.push(sectionTypeValue.value);
+  }
+  sectionTypeVisable.value = false;
+  sectionTypeValue.value = "";
+};
+//展示新增标签input
+const showInput = () => {
+  sectionTypeVisable.value = true;
+  nextTick(() => {
+    InputRef.value!.input!.focus();
+  });
+};
+//返回上一页
+const goBack = () => {
+  router.go(-1);
+};
+const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
+  videoUrlList.value = [];
+};
+
+const handleSuccess = (response: any, uploadFile: UploadUserFile) => {
+  ElMessage.success("图片上传成功");
+  console.log(response);
+  if (response.data) {
+    videoUrlList.value.push(response.data);
+    // videoUrl.value = response.data;
+  }
+  console.log("videoUrlList.value ===> ", videoUrlList.value);
+};
+
+const handleContractRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
+  contractImageList.value = [];
+  (uploadFiles || []).forEach((f: any) => {
+    if (f.url) contractImageList.value.push(f.url);
+  });
+  // storeInfoModel.value.contractImageList = storeInfoModel.value.contractImageList.filter(item => item.uid !== uploadFile.uid)
+};
+
+const handleContractSuccess = (response: any, uploadFile: UploadUserFile) => {
+  ElMessage.success("合同上传成功");
+  if (response.data) {
+    contractImageList.value.push(response.data);
+  }
+  console.log(contractImageList.value);
+};
+
+const handleFoodLicenceSuccess = (response: any, uploadFile: UploadUserFile) => {
+  ElMessage.success("食品经营许可上传成功");
+  if (response.data) {
+    foodLicenceImageList.value.push(response.data);
+  }
+  console.log(response);
+};
+
+const handleFoodLicenceRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
+  foodLicenceImageList.value = [];
+  (uploadFiles || []).forEach((item: any) => {
+    if (item.url) foodLicenceImageList.value.push(item.url);
+  });
+  console.log("foodLicenceImageList.value ===> ", foodLicenceImageList.value);
+};
+
+const getBusinessSectionList = async () => {
+  let res: any = await getBusinessSection();
+  let addData: any[] = [];
+  (res?.data || []).forEach((element: any) => {
+    addData.push({ value: element.dictId, label: element.dictDetail, parentId: element.parentId });
+  });
+  //默认 storeInfoModel!.businessSection 为第一个元素
+  storeInfoModel.value.businessSection = addData[0].value;
+  businessSectionList.value = addData;
+  changeSection();
+};
+
+const changeSection = async () => {
+  storeInfoModel.value.businessTypes = [];
+  //获取经营种类
+  const resType: any = await getBusinessSectionTypes({ parentId: storeInfoModel.value.businessSection } as any);
+  let addData: any[] = [];
+  (resType?.data || []).forEach((element: any) => {
+    addData.push({ value: element.dictId, label: element.dictDetail, parentId: element.parentId });
+  });
+  businessTypes.value = addData;
+  if (type.value == "add") {
+    storeInfoModel.value.businessTypes = ["0"];
+  }
+};
+
+// const handlePictureCardPreview: UploadProps["onPreview"] = uploadFile => {};
+const previewImage = ref("");
+const handlePictureCardPreview = (e: any) => {
+  imagePopupVisible.value = true;
+  previewImage.value = e.url;
+};
+
+const closeImagePopup = () => {
+  imagePopupVisible.value = false;
+  previewImage.value = "";
+};
+
+// 提交数据(新增/编辑)
+const ruleFormRef = ref<FormInstance>();
+const ruleFormRef2 = ref<FormInstance>();
+const ruleFormRef3 = ref<FormInstance>();
+const handleSubmit = () => {
+  ruleFormRef.value!.validate(async valid => {
+    if (!valid) return;
+    ruleFormRef2.value!.validate(async valid2 => {
+      if (!valid2) return;
+      ruleFormRef3.value!.validate(async valid3 => {
+        if (!valid3) return;
+        if (!storeInfoModel.value.district[0] || !storeInfoModel.value.district[1] || !storeInfoModel.value.district[2]) {
+          ElMessage.error("请完整选择行政区域");
+          return;
+        }
+        let param: any = storeInfoModel.value;
+        param.queryAddress = queryAddress.value;
+        console.log("videoUrlList.value ===> ", videoUrlList.value);
+        console.log("storeInfoModel.value ===> ", storeInfoModel.value);
+        param.businessLicenseAddress = videoUrlList.value;
+        param.contractImageList = handleImageResult(contractImageList.value);
+        let arr = handleImageResult(foodLicenceImageList.value);
+        param.foodLicenceUrl = arr.length > 0 ? arr[0] : "";
+        param.createTime = null;
+        param.updatedTime = null;
+        param.administrativeRegionProvinceAdcode = storeInfoModel.value.district[0];
+        param.administrativeRegionCityAdcode = storeInfoModel.value.district[1];
+        param.administrativeRegionDistrictAdcode = storeInfoModel.value.district[2];
+        if (type.value == "add") {
+          let res = await saveStoreInfo(param);
+          if (res.code == "200") {
+            ElMessage.success("新增成功");
+            router.go(-1);
+          } else {
+            ElMessage.error("新增失败");
+          }
+        } else if (type.value == "edit") {
+          let res = await editStoreInfo(param);
+          if (res.code == "200") {
+            ElMessage.success("编辑成功");
+            router.go(-1);
+          } else {
+            ElMessage.error("编辑失败");
+          }
+        }
+      });
+    });
+  });
+};
+
+onMounted(async () => {
+  id.value = (route.query.id as string) || "";
+  type.value = (route.query.type as string) || "";
+  //调用获取用户列表
+  getUserOptions();
+  //获取商铺经营板块
+  if (type.value != "add") {
+    if (type.value == "show") {
+      isDisabled.value = true;
+    }
+    let res: any = await getStoreDetail({ id: id.value } as any);
+    storeInfoModel.value = res.data as any;
+    storeInfoModel.value.businessSection = storeInfoModel.value.businessSection + "";
+    storeInfoModel.value.userAccount = Number(storeInfoModel.value.userAccount);
+    await changeSection();
+    storeInfoModel.value.businessTypes = storeInfoModel.value.businessTypesList;
+    storeInfoModel.value.storePositionLongitude = storeInfoModel.value.storePosition.split(",")[0];
+    storeInfoModel.value.storePositionLatitude = storeInfoModel.value.storePosition.split(",")[1];
+    let district: any[] = [];
+    district[0] = storeInfoModel.value.administrativeRegionProvinceAdcode;
+    district[1] = storeInfoModel.value.administrativeRegionCityAdcode;
+    district[2] = storeInfoModel.value.administrativeRegionDistrictAdcode;
+    storeInfoModel.value.district = district;
+    videoUrlList.value = (res.data as any).businessLicenseAddress || [];
+    let fileList: any[] = [];
+    handleImageParam((res.data as any).businessLicenseAddress || [], fileList);
+
+    let contractImageList: any[] = [];
+    handleImageParam((res.data as any).contractImageList || [], contractImageList);
+
+    let foodLicenceImageList: any[] = [];
+    handleImageParam((res.data as any).foodLicenceImageList || [], foodLicenceImageList);
+
+    storeInfoModel.value.fileList = fileList;
+    storeInfoModel.value.contractImage = contractImageList;
+    storeInfoModel.value.contractImageList = contractImageList;
+    (contractImageList as any).value = contractImageList as any;
+    storeInfoModel.value.foodLicenceImage = foodLicenceImageList;
+    storeInfoModel.value.foodLicenceImageList = foodLicenceImageList;
+  }
+});
+//图片list 转换为upload 组件的参数
+const handleImageParam = (list: any[], result: any[]) => {
+  (list || []).forEach((item: any) => {
+    // 使用split方法以'/'为分隔符将URL拆分成数组
+    const parts = item.split("/");
+    // 取数组的最后一项,即图片名称
+    const imageName = parts[parts.length - 1];
+    result.push({
+      name: imageName,
+      percentage: 100,
+      url: item
+    });
+  });
+};
+
+const handleImageResult = (list: any[]) => {
+  let result: any[] = [];
+  (list || []).forEach((item: any) => {
+    if (item.uid) {
+      result.push(item.url);
+    } else {
+      result.push(item);
+    }
+  });
+  return result;
+};
+
+// 判断审核状态
+const storeApplicationStatusText = computed(() => {
+  const status = storeInfoModel.value.storeApplicationStatus;
+  if (status == 0) return "待审核";
+  if (status == 1) return "审核通过";
+  if (status == 2) return "审核拒绝";
+  return "";
+});
+</script>
+
+<style scoped lang="scss">
+.content {
+  display: flex;
+  width: 98%;
+  height: 98%;
+  margin: auto;
+  .contentLeft {
+    width: 50%;
+  }
+  .contentRight {
+    width: 50%;
+  }
+}
+.model {
+  margin-bottom: 50px;
+}
+.formBox {
+  width: 70%;
+}
+.table-box {
+  height: auto !important;
+}
+</style>