Bladeren bron

消息/修改密码

zhuli 1 maand geleden
bovenliggende
commit
fc9fe9b1de

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

@@ -21,6 +21,26 @@ export const getMerchantByPhone = params => {
 export const getNoticeList = params => {
   return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/notice/getNoticeList`, params);
 };
+//通知列表  一键已读
+export const markAllNoticesAsRead = params => {
+  return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/notice/markAllNoticesAsRead`, params);
+};
+//今日订单量
+export const getTodayOrderCount = params => {
+  return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/storeManage/getTodayOrderCount`, params);
+};
+//今日预计收益
+export const getTodayIncome = params => {
+  return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/storeManage/getTodayIncome`, params);
+};
+
+//验券
+export const verifyOrder = params => {
+  return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/couponManage/verifyOrder`, params);
+};
+export const verifyCoupon = params => {
+  return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/couponManage/verifyCoupon`, params);
+};
 export const getUserByPhone = params => {
   return http.get(PORT_NONE + `/merchantUser/getMerchantByPhone`, params);
 };

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

@@ -33,6 +33,11 @@ export const forgetPassword = params => {
   return httpLogin.get(`/alienStorePlatform/storePlatformLogin/updatePassword`, params, { loading: false });
 };
 
+// 修改密码
+export const updatePassword = params => {
+  return httpLogin.post(`/alienStorePlatform/storePlatformLogin/updatePassword`, params, { loading: false });
+};
+
 //经营板块
 export const getBusinessSection = () => {
   return httpLogin.get(`/alienStore/store/info/getBusinessSection`);

+ 23 - 11
src/layouts/components/Header/components/InfoDialog.vue

@@ -27,7 +27,7 @@
     <template #footer>
       <span class="dialog-footer">
         <el-button @click="dialogVisible = false">取消</el-button>
-        <el-button type="primary" @click="dialogVisible = false">确认</el-button>
+        <el-button type="primary" @click="getUserInfo()">确认</el-button>
       </span>
     </template>
   </el-dialog>
@@ -38,22 +38,34 @@ import { ref, reactive } from "vue";
 import { ElMessage, type FormInstance, type FormRules } from "element-plus";
 import { Plus } from "@element-plus/icons-vue";
 import { getMerchantByPhone } from "@/api/modules/homeEntry.ts";
-
+import { localGet } from "@/utils/index";
+const userInfo = localGet("geeker-user").userInfo;
 const dialogVisible = ref(false);
-const openDialog = async () => {
-  const res = await getMerchantByPhone({ phone: "15242687180" });
-  console.log(res);
-  dialogVisible.value = true;
-};
-
-defineExpose({ openDialog });
 
 const formRef = ref<FormInstance>();
 const form = reactive({
   avatarList: [] as any[],
-  nickname: "重庆老火锅",
-  intro: "这——家优秀的火锅店"
+  nickname: "",
+  intro: ""
 });
+const openDialog = async () => {
+  form.nickname = userInfo.nickName;
+  form.intro = userInfo.accountBlurb;
+
+  dialogVisible.value = true;
+};
+const getUserInfo = async () => {
+  if (!formRef.value) return;
+  await formRef.value.validate(valid => {
+    if (!valid) return;
+    const res = getMerchantByPhone({ phone: "" });
+    if (res.code === 200) {
+      ElMessage.success("保存成功");
+    }
+  });
+};
+
+defineExpose({ openDialog });
 
 const rules: FormRules = {
   nickname: [{ required: true, message: "请输入昵称", trigger: "blur" }],

+ 40 - 1
src/layouts/components/Header/components/Message.vue

@@ -1,14 +1,53 @@
 <template>
   <div class="message">
-    <el-badge :value="0" class="item">
+    <el-badge :value="unreadCount > 0 ? unreadCount : undefined" class="item">
       <i :class="'iconfont icon-xiaoxi'" class="toolBar-icon" @click="getMessage" />
     </el-badge>
   </div>
 </template>
 <script setup lang="ts">
+import { ref, onMounted, onBeforeUnmount } from "vue";
 import { useRouter } from "vue-router";
+import { getNoticeList } from "@/api/modules/homeEntry";
+import { localGet } from "@/utils/index";
+import mittBus from "@/utils/mittBus";
+
 const router = useRouter();
+const unreadCount = ref<number>(0);
+
+// 获取未读消息数量
+const getUnreadCount = async () => {
+  try {
+    const receiverId = localGet("iphone") || localGet("geeker-user")?.userInfo?.phone || "";
+    if (!receiverId) return;
+
+    const res: any = await getNoticeList({ pageNum: 1, pageSize: 100, receiverId });
+    if (res.code == "200") {
+      const noticeList = res.data?.records || res.data?.list || [];
+      // 计算未读消息数量
+      unreadCount.value = noticeList.filter((item: any) => !item.isRead).length;
+    }
+  } catch (error) {
+    console.error("获取消息列表失败:", error);
+  }
+};
+
 const getMessage = () => {
   router.push(`/home/notice`);
 };
+
+onMounted(() => {
+  // 初始化获取未读数量
+  getUnreadCount();
+
+  // 监听消息更新事件,当消息页面有操作时(标记已读等)更新未读数量
+  mittBus.on("updateUnreadCount", () => {
+    getUnreadCount();
+  });
+});
+
+onBeforeUnmount(() => {
+  // 移除事件监听
+  mittBus.off("updateUnreadCount");
+});
 </script>

+ 118 - 5
src/layouts/components/Header/components/PasswordDialog.vue

@@ -1,22 +1,135 @@
 <template>
-  <el-dialog v-model="dialogVisible" title="修改密码" width="500px" draggable>
-    <span>This is Password</span>
+  <el-dialog v-model="dialogVisible" title="修改密码" width="500px" draggable :close-on-click-modal="false">
+    <el-form ref="passwordFormRef" :model="passwordForm" :rules="passwordRules" label-width="100px" label-position="left">
+      <el-form-item label="输入原密码" prop="oldPassword">
+        <el-input v-model="passwordForm.oldPassword" type="password" placeholder="请输入原密码" show-password clearable />
+      </el-form-item>
+
+      <el-form-item label="输入新密码" prop="newPassword">
+        <el-input
+          v-model="passwordForm.newPassword"
+          type="password"
+          placeholder="请输入6-16位的密码,包含字母和数字"
+          show-password
+          clearable
+        />
+      </el-form-item>
+
+      <el-form-item label="确认密码" prop="confirmPassword">
+        <div style="display: flex; align-items: center; width: 100%">
+          <el-input
+            v-model="passwordForm.confirmPassword"
+            type="password"
+            placeholder="请确认密码"
+            show-password
+            clearable
+            style="flex: 1"
+          />
+          <el-link type="primary" :underline="false" style="margin-left: 12px" @click="handleForgotPassword"> 忘记密码 </el-link>
+        </div>
+      </el-form-item>
+    </el-form>
+
     <template #footer>
       <span class="dialog-footer">
-        <el-button @click="dialogVisible = false">取消</el-button>
-        <el-button type="primary" @click="dialogVisible = false">确认</el-button>
+        <el-button @click="handleCancel">取消</el-button>
+        <el-button type="primary" :loading="loading" @click="handleConfirm">确定</el-button>
       </span>
     </template>
   </el-dialog>
 </template>
 
 <script setup lang="ts">
-import { ref } from "vue";
+import { ref, reactive } from "vue";
+import { ElMessage, type FormInstance, type FormRules } from "element-plus";
+import { validatePassword, validateConfirmPassword } from "@/utils/eleValidate";
+import { updatePassword } from "@/api/modules/newLoginApi";
 
 const dialogVisible = ref(false);
+const loading = ref(false);
+const passwordFormRef = ref<FormInstance>();
+
+const passwordForm = reactive({
+  oldPassword: "",
+  newPassword: "",
+  confirmPassword: ""
+});
+
+// 表单验证规则
+const passwordRules: FormRules = {
+  oldPassword: [{ required: true, message: "请输入原密码", trigger: "blur" }],
+  newPassword: [{ required: true, validator: validatePassword, trigger: "blur" }],
+  confirmPassword: [
+    {
+      required: true,
+      validator: validateConfirmPassword(() => passwordForm.newPassword),
+      trigger: "blur"
+    }
+  ]
+};
+
+// 打开对话框
 const openDialog = () => {
   dialogVisible.value = true;
+  // 重置表单
+  if (passwordFormRef.value) {
+    passwordFormRef.value.resetFields();
+  }
+};
+
+// 取消
+const handleCancel = () => {
+  dialogVisible.value = false;
+  if (passwordFormRef.value) {
+    passwordFormRef.value.resetFields();
+  }
+};
+
+// 确定
+const handleConfirm = async () => {
+  if (!passwordFormRef.value) return;
+
+  await passwordFormRef.value.validate(async valid => {
+    if (!valid) return;
+
+    loading.value = true;
+    try {
+      const res: any = await updatePassword({
+        oldPassword: passwordForm.oldPassword,
+        newPassword: passwordForm.newPassword
+      });
+
+      if (res.code === "200" || res.code === 200) {
+        ElMessage.success(res.msg || "密码修改成功");
+        dialogVisible.value = false;
+        if (passwordFormRef.value) {
+          passwordFormRef.value.resetFields();
+        }
+      } else {
+        ElMessage.error(res.msg || "密码修改失败,请重试");
+      }
+    } catch (error: any) {
+      ElMessage.error(error?.msg || error?.message || "密码修改失败,请重试");
+    } finally {
+      loading.value = false;
+    }
+  });
+};
+
+// 忘记密码
+const handleForgotPassword = () => {
+  ElMessage.info("忘记密码功能,请跳转到登录页面");
+  // TODO: 可以跳转到忘记密码页面或打开忘记密码对话框
+  dialogVisible.value = false;
 };
 
 defineExpose({ openDialog });
 </script>
+
+<style scoped lang="scss">
+.dialog-footer {
+  display: flex;
+  gap: 12px;
+  justify-content: flex-end;
+}
+</style>

+ 33 - 7
src/views/home/components/go-examine.vue

@@ -18,7 +18,7 @@
         <div class="stat-card">
           <div class="stat-title">店铺钱包(元)</div>
           <div class="stat-value">
-            {{ walletAmount.toFixed(2) }}
+            {{ walletAmount }}
           </div>
         </div>
         <el-image :src="homeWallet" class="walletImg" />
@@ -36,7 +36,7 @@
         <div class="stat-card">
           <div class="stat-title">今日收益(元)</div>
           <div class="stat-value">
-            {{ todayRevenue.toFixed(2) }}
+            {{ todayRevenue }}
           </div>
         </div>
         <el-image :src="homeIncome" class="walletImg" />
@@ -46,12 +46,13 @@
 </template>
 
 <script setup lang="ts">
-import { ref } from "vue";
+import { onMounted, ref } from "vue";
+import { ElMessage } from "element-plus";
 import homeIcon from "../../../assets/images/home-icon.png";
 import homeWallet from "../../../assets/images/home-wallet.png";
 import homeOrder from "../../../assets/images/home-order.png";
 import homeIncome from "../../../assets/images/home-income.png";
-
+import { verifyOrder, verifyCoupon, getTodayOrderCount, getTodayIncome } from "@/api/modules/homeEntry.ts";
 // 数据(可根据实际接口替换)
 const storeName = ref("时间图书馆");
 const expireDate = ref("2027/10/29");
@@ -60,11 +61,36 @@ const voucherCode = ref("");
 const walletAmount = ref(0);
 const todayOrders = ref(0);
 const todayRevenue = ref(0);
-
-const handleVerify = () => {
+onMounted(() => {
+  getOrder();
+  getInCome();
+});
+const getOrder = async () => {
+  const res = await getTodayOrderCount({ storeId: 120 });
+  if (res.success) {
+    todayOrders.value = res.data;
+  }
+};
+const getInCome = async () => {
+  const res = await getTodayIncome({ storeId: 120 });
+  if (res.success) {
+    todayRevenue.value = res.data;
+  }
+};
+const handleVerify = async () => {
   // 调用验券接口
   if (!voucherCode.value) return;
-  // TODO: 接入后端验券逻辑
+  const res = await verifyOrder({ orderCode: voucherCode.value });
+  if (res.success) {
+    let i = {
+      quanCode: voucherCode.value,
+      storeId: 120
+    };
+    const res1 = await verifyCoupon(i);
+    if (res && res.data.code === "true") {
+      ElMessage.success(res.msg);
+    }
+  }
   console.log("verify voucher:", voucherCode.value);
 };
 </script>

+ 247 - 51
src/views/home/components/go-flow.vue

@@ -50,6 +50,10 @@
                 <el-input-number v-model="step2Form.storeCapacity" :min="1" :max="9999" />
               </el-form-item>
 
+              <el-form-item label="门店电话" prop="storeTel">
+                <el-input v-model="step2Form.storeTel" placeholder="请输入门店电话" />
+              </el-form-item>
+
               <el-form-item label="门店面积" prop="storeArea">
                 <el-radio-group v-model="step2Form.storeArea">
                   <el-radio label="小于20平米" value="1"> 小于20平米 </el-radio>
@@ -65,16 +69,16 @@
                 <el-cascader :props="areaProps" v-model="step2Form.region" style="width: 100%" />
               </el-form-item>
 
-              <el-form-item label="详细地址" prop="storeAddress">
-                <el-input v-model="step2Form.storeAddress" type="textarea" :rows="3" placeholder="请输入" />
+              <el-form-item label="详细地址" prop="storeDetailAddress">
+                <el-input v-model="step2Form.storeDetailAddress" type="textarea" :rows="3" placeholder="请输入" />
               </el-form-item>
 
               <el-form-item label="门店简介" prop="storeBlurb">
                 <el-input v-model="step2Form.storeBlurb" type="textarea" :rows="3" placeholder="请输入" />
               </el-form-item>
 
-              <el-form-item label="经营板块" prop="businessSector">
-                <el-radio-group v-model="step2Form.businessSector" @change="changeBusinessSector">
+              <el-form-item label="经营板块" prop="businessSection">
+                <el-radio-group v-model="step2Form.businessSection" @change="changeBusinessSector">
                   <el-radio
                     v-for="businessSection in businessSectionList"
                     :value="businessSection.value"
@@ -85,8 +89,8 @@
                 </el-radio-group>
               </el-form-item>
 
-              <el-form-item label="经营种类" prop="businessType">
-                <el-checkbox-group v-model="step2Form.businessType">
+              <el-form-item label="经营种类" prop="businessTypes">
+                <el-checkbox-group v-model="step2Form.businessTypes">
                   <el-checkbox
                     v-for="businessType in businessTypeList"
                     :key="businessType"
@@ -112,9 +116,9 @@
               <el-form-item label="纬度" prop="storePositionLatitude">
                 <el-input disabled v-model="step2Form.storePositionLatitude" placeholder="请填写纬度" clearable />
               </el-form-item>
-              <el-form-item label="经纬度查询" prop="addressName">
+              <el-form-item label="经纬度查询" prop="address">
                 <el-select
-                  v-model="step2Form.addressName"
+                  v-model="address"
                   filterable
                   placeholder="请输入地址进行查询"
                   remote
@@ -131,45 +135,48 @@
 
               <el-form-item label="营业执照" prop="businessLicenseFiles">
                 <el-upload
-                  v-model:file-list="step2Form.businessLicenseFiles"
+                  v-model:file-list="step2Form.businessLicenseAddress"
                   :http-request="handleHttpUpload"
                   list-type="picture-card"
                   :limit="1"
                   :on-exceed="handleExceed"
+                  :on-success="handleUploadSuccess"
                 >
                   <el-icon><Plus /></el-icon>
                   <template #tip>
-                    <div class="el-upload__tip">(0/1)</div>
+                    <div class="el-upload__tip">({{ step2Form.businessLicenseAddress.length }}/1)</div>
                   </template>
                 </el-upload>
               </el-form-item>
 
               <el-form-item label="合同图片" prop="contractImageFiles">
                 <el-upload
-                  v-model:file-list="step2Form.contractImageFiles"
+                  v-model:file-list="step2Form.contractImageList"
                   :http-request="handleHttpUpload"
                   list-type="picture-card"
                   :limit="20"
                   :on-exceed="handleExceed"
+                  :on-success="handleUploadSuccess"
                 >
                   <el-icon><Plus /></el-icon>
                   <template #tip>
-                    <div class="el-upload__tip">(0/20)</div>
+                    <div class="el-upload__tip">({{ step2Form.contractImageList.length }}/20)</div>
                   </template>
                 </el-upload>
               </el-form-item>
 
               <el-form-item label="食品经营许可证" prop="foodLicenseFiles ">
                 <el-upload
-                  v-model:file-list="step2Form.foodLicenseFiles"
+                  v-model:file-list="step2Form.foodLicenceImgList"
                   :http-request="handleHttpUpload"
                   list-type="picture-card"
                   :limit="1"
                   :on-exceed="handleExceed"
+                  :on-success="handleUploadSuccess"
                 >
                   <el-icon><Plus /></el-icon>
                   <template #tip>
-                    <div class="el-upload__tip">(0/1)</div>
+                    <div class="el-upload__tip">({{ step2Form.foodLicenceImgList.length }}/1)</div>
                   </template>
                 </el-upload>
               </el-form-item>
@@ -194,7 +201,15 @@
 </template>
 <script setup lang="ts">
 import { ref, reactive, watch, onMounted } from "vue";
-import { ElMessage, ElMessageBox, type FormInstance, type FormRules, UploadProps, UploadRequestOptions } from "element-plus";
+import {
+  ElMessage,
+  ElMessageBox,
+  type FormInstance,
+  type FormRules,
+  UploadProps,
+  UploadUserFile,
+  UploadRequestOptions
+} from "element-plus";
 import { Plus } from "@element-plus/icons-vue";
 
 import { verifyIdInfo, applyStore } from "@/api/modules/homeEntry.ts";
@@ -226,6 +241,8 @@ const entryList = ref([
 const addressList = ref<any[]>([]);
 //查询地址名称
 const queryAddress = ref<string>("");
+//地址名称
+const address = ref<string>("");
 
 const props = defineProps({
   currentStep: {
@@ -254,7 +271,7 @@ const setStep = (val: number) => {
 const step1FormRef = ref<FormInstance>();
 const step1Form = reactive({
   name: "朱丽",
-  idNumber: "231084199304282927"
+  idNumber: ""
 });
 
 const step1Rules: FormRules = {
@@ -272,33 +289,38 @@ const step1Rules: FormRules = {
 // 第二步表单
 const step2FormRef = ref<FormInstance>();
 const step2Form = reactive({
+  storeName: "", //门店名称
+  storeCapacity: 1, //容纳人数
+  storeArea: "1", //门店面积
+  storeTel: "", //门店电话
+  isChain: 0, //是否连锁
+  storeDetailAddress: "", //详细地址
   region: [],
-  addressName: "",
-  storePositionLongitude: "",
-  storePositionLatitude: "",
-  storeName: "",
-  storeCapacity: 1,
-  storePhone: "",
-  storeArea: "小于20平米",
-  province: "",
-  city: "",
-  district: "",
-  storeAddress: "",
-  storeBlurb: "",
-  businessSector: "1",
-  businessType: "正常营业",
-  coordinates: "",
-  businessLicenseFiles: [],
-  contractImageFiles: [],
-  foodLicenseFiles: []
+  administrativeRegionProvinceAdcode: "", //省
+  administrativeRegionCityAdcode: "", //市
+  administrativeRegionDistrictAdcode: "", //区
+  storeAddress: "", //门店地址(完整地址)
+  storeBlurb: "", //门店简介
+  businessSection: "3", //经营板块
+  businessSectionName: "KTV",
+  businessTypes: [], //经营种类
+  businessTypesList: [], //经营种类集合
+  businessStatus: 0, //营业状态
+  storeStatus: 1, //门店状态
+  businessType: "正常营业", //门店营业状态(用于表单显示)
+  storePositionLongitude: "", //经度
+  storePositionLatitude: "", //纬度
+  businessLicenseAddress: [] as UploadUserFile[], //营业执照地址
+  contractImageList: [] as UploadUserFile[], //合同图片集合
+  foodLicenceImgList: [] as UploadUserFile[] //食品经营许可证
 });
 
 const step2Rules: FormRules = {
   storeName: [{ required: true, message: "请输入店铺名称", trigger: "blur" }],
-  storePhone: [{ required: true, message: "请输入门店电话", trigger: "blur" }],
+  storeTel: [{ required: true, message: "请输入门店电话", trigger: "blur" }],
   storeArea: [{ required: true, message: "请选择门店面积", trigger: "change" }],
   storeIntro: [{ required: true, message: "请输入门店简介", trigger: "blur" }],
-  businessSector: [{ required: true, message: "请选择经营板块", trigger: "change" }],
+  businessSection: [{ required: true, message: "请选择经营板块", trigger: "change" }],
   businessType: [{ required: true, message: "请选择经营种类", trigger: "change" }],
   coordinates: [{ required: true, message: "请输入经纬度", trigger: "blur" }],
   businessLicense: [{ required: true, message: "请上传营业执照", trigger: "change" }],
@@ -332,15 +354,25 @@ const areaProps: any = {
         label: item.name,
         leaf: level >= 2 // 假设最多三级,可以根据实际需求调整
       }));
-
+      console.log(nodes);
       // 返回数据
       resolve(nodes);
     } catch (error) {
-      console.error("获取区域数据失败:", error);
       resolve([]);
     }
   }
 };
+watch(
+  () => step2Form.region,
+  (newVal: any[]) => {
+    if (newVal.length > 0) {
+      step2Form.administrativeRegionProvinceAdcode = newVal[0];
+      step2Form.administrativeRegionCityAdcode = newVal[1];
+      step2Form.administrativeRegionDistrictAdcode = newVal[2];
+    }
+  }
+);
+
 //经营板块
 const businessSectionList = ref<any[]>([]);
 const getBusinessSectionList = async () => {
@@ -350,15 +382,35 @@ const getBusinessSectionList = async () => {
     addData.push({ value: element.dictId, label: element.dictDetail, parentId: element.parentId });
   });
   businessSectionList.value = addData;
+  // 如果businessSection有默认值,自动设置对应的id和name
+  if (step2Form.businessSection) {
+    const selectedSection = addData.find((item: any) => item.value === step2Form.businessSection);
+    if (selectedSection) {
+      step2Form.businessSection = selectedSection.value;
+      step2Form.businessSectionName = selectedSection.label;
+    }
+  }
 };
 const changeBusinessSector = async (val: any) => {
+  // 根据选中的value从businessSectionList中查找对应的项
+  const selectedSection = businessSectionList.value.find((item: any) => item.value === val);
+  if (selectedSection) {
+    step2Form.businessSection = selectedSection.value; // dictId
+    step2Form.businessSectionName = selectedSection.label; // dictDetail
+  } else {
+    step2Form.businessSection = "";
+    step2Form.businessSectionName = "";
+  }
+  // 清空之前选中的经营种类
+  step2Form.businessTypesList = [];
+  step2Form.businessTypes = [];
   getBusinessTypes(val);
 };
 
 //经营种类
 const businessTypeList = ref<any[]>([]);
 const getBusinessTypes = async (val: any) => {
-  let res: any = await getBusinessSectionTypes({ parentId: val ? val : step2Form.businessSector });
+  let res: any = await getBusinessSectionTypes({ parentId: val ? val : step2Form.businessSection });
   let addData1: any[] = [];
   (res?.data || []).forEach((element: any) => {
     addData1.push({ value: element.dictId, label: element.dictDetail });
@@ -385,9 +437,9 @@ const getLonAndLat = async (keyword: string) => {
   }
 };
 const selectAddress = async (param: any) => {
-  let locationList = step2Form.addressName.split(",");
+  let locationList = address.value.split(",");
   addressList.value.forEach((item: any) => {
-    if (item.location == step2Form.addressName) {
+    if (item.location == address.value) {
       queryAddress.value = item.name;
     }
   });
@@ -400,9 +452,25 @@ const handleHttpUpload = async (options: UploadRequestOptions) => {
   formData.append("file", options.file);
   try {
     const res: any = await uploadImg(formData);
-    console.log(res);
+    // 上传成功,将URL保存到文件对象中
+    const fileUrl = res?.data?.fileUrl || res?.data?.[0] || res?.fileUrl;
+    if (fileUrl) {
+      // 调用 onSuccess 回调,传入响应数据
+      options.onSuccess({ fileUrl });
+    } else {
+      throw new Error("上传失败:未获取到文件URL");
+    }
   } catch (error) {
     options.onError(error as any);
+    ElMessage.error("文件上传失败,请重试");
+  }
+};
+
+// 文件上传成功回调
+const handleUploadSuccess = (response: any, uploadFile: UploadUserFile) => {
+  // 将URL保存到文件对象中
+  if (response?.fileUrl) {
+    uploadFile.url = response.fileUrl;
   }
 };
 // 下一步
@@ -434,25 +502,153 @@ const handlePrevStep = () => {
   setStep(1);
 };
 
+// 提取文件列表中的URL
+const getFileUrls = (fileList: UploadUserFile[]): string[] => {
+  return fileList
+    .map((file: UploadUserFile) => {
+      // 优先使用 url,如果没有则使用 response 中的 fileUrl
+      const response = file.response as any;
+      return file.url || response?.fileUrl || "";
+    })
+    .filter((url: string) => url); // 过滤掉空字符串
+};
+
+// 根据adcode获取地区详细信息
+const getDistrictInfo = async (adcode: string) => {
+  try {
+    const response: any = await getDistrict({ adCode: adcode } as any);
+    const district = response?.data?.districts?.[0];
+    if (district) {
+      return {
+        citycode: district.citycode ? [district.citycode] : [],
+        adcode: district.adcode,
+        level: district.level,
+        center: district.center,
+        name: district.name,
+        districts: []
+      };
+    }
+  } catch (error) {
+    console.error("获取地区信息失败:", error);
+  }
+  return null;
+};
+
+// 构建whereAddress数组
+const buildWhereAddress = async (regionCodes: string[]) => {
+  const whereAddress: any[] = [];
+  if (regionCodes && regionCodes.length > 0) {
+    for (const code of regionCodes) {
+      const districtInfo = await getDistrictInfo(code);
+      if (districtInfo) {
+        whereAddress.push(districtInfo);
+      }
+    }
+  }
+  return whereAddress;
+};
+
 // 提交
 const handleSubmit = async () => {
-  console.log(step2Form);
-  return;
-  let res = await applyStore(param);
-  return;
   if (!step2FormRef.value) return;
 
-  await step2FormRef.value.validate(valid => {
+  await step2FormRef.value.validate(async valid => {
     if (valid) {
+      // 提取上传图片的URL
+      const businessLicenseUrls = getFileUrls(step2Form.businessLicenseAddress);
+      const contractImageUrls = getFileUrls(step2Form.contractImageList);
+      const foodLicenceUrls = getFileUrls(step2Form.foodLicenceImgList);
+
+      // 构建whereAddress数组
+      const whereAddress = await buildWhereAddress(step2Form.region);
+
+      // 处理营业状态映射
+      let storeStatus = 1; // 默认值
+      if (step2Form.businessType === "正常营业") {
+        storeStatus = 1;
+      } else if (step2Form.businessType === "暂停营业") {
+        storeStatus = 0;
+      } else if (step2Form.businessType === "筹建中") {
+        storeStatus = 2;
+      }
+
+      // 处理门店面积:转换为数字
+      const storeAreaNum = typeof step2Form.storeArea === "string" ? parseInt(step2Form.storeArea) : step2Form.storeArea;
+
+      // 构建地址对象
+      const addressObj = {
+        address: queryAddress.value || "",
+        longitude: parseFloat(step2Form.storePositionLongitude) || 0,
+        latitude: parseFloat(step2Form.storePositionLatitude) || 0
+      };
+
+      // 构建门店位置字符串
+      const storePosition =
+        step2Form.storePositionLongitude && step2Form.storePositionLatitude
+          ? `${step2Form.storePositionLongitude},${step2Form.storePositionLatitude}`
+          : "";
+
+      // 构建完整地址(省市区+详细地址)
+      let fullStoreAddress = "";
+      if (whereAddress.length > 0) {
+        const provinceName = whereAddress[0]?.name || "";
+        const cityName = whereAddress[1]?.name || "";
+        const districtName = whereAddress[2]?.name || "";
+        fullStoreAddress = `${provinceName}${cityName}${districtName}`;
+      }
+
+      // 构建提交参数(按照JSON格式)
+      const params = {
+        storeName: step2Form.storeName,
+        storeCapacity: step2Form.storeCapacity,
+        storeTel: step2Form.storeTel,
+        storeArea: storeAreaNum,
+        isChain: step2Form.isChain,
+        storeDetailAddress: step2Form.storeDetailAddress,
+        storeBlurb: step2Form.storeBlurb,
+        businessSection: step2Form.businessSection,
+        businessTypesList: step2Form.businessTypes.length > 0 ? step2Form.businessTypes : step2Form.businessTypesList,
+        storeStatus: storeStatus,
+        businessStatus: step2Form.businessStatus,
+        address: addressObj,
+        businessLicenseAddress: businessLicenseUrls,
+        contractImageList: contractImageUrls,
+        foodLicenceImgList: foodLicenceUrls,
+        storeAddress: fullStoreAddress,
+        whereAddress: whereAddress,
+        updatedTime: null,
+        queryAddress: queryAddress.value,
+        storePosition: storePosition,
+        storePositionLatitude: parseFloat(step2Form.storePositionLatitude) || 0,
+        storePositionLongitude: parseFloat(step2Form.storePositionLongitude) || 0,
+        businessSectionName: step2Form.businessSectionName,
+        businessTypes: step2Form.businessTypes.length > 0 ? step2Form.businessTypes : step2Form.businessTypesList,
+        foodLicenceUrl: foodLicenceUrls.length > 0 ? foodLicenceUrls[0] : "",
+        userAccount: 0, // 需要从用户信息中获取
+        administrativeRegionProvinceAdcode: step2Form.administrativeRegionProvinceAdcode,
+        administrativeRegionCityAdcode: step2Form.administrativeRegionCityAdcode,
+        administrativeRegionDistrictAdcode: step2Form.administrativeRegionDistrictAdcode,
+        storeContact: step1Form.name,
+        idCard: step1Form.idNumber
+      };
+
       ElMessageBox.confirm("确认提交入驻申请吗?", "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
       })
-        .then(() => {
-          // 这里可以调用API提交数据
-          ElMessage.success("提交成功,等待审核");
-          setStep(3); // 跳转到等待审核步骤
+        .then(async () => {
+          try {
+            const res = await applyStore(params);
+            if (res.code === "200") {
+              ElMessage.success(res.msg || "提交成功,等待审核");
+              setStep(3); // 跳转到等待审核步骤
+            } else {
+              ElMessage.error(res.msg || "提交失败");
+            }
+          } catch (error) {
+            ElMessage.error("提交失败,请重试");
+          }
         })
         .catch(() => {
           // 取消提交

+ 1 - 1
src/views/home/index.vue

@@ -17,7 +17,7 @@ import { ref } from "vue";
 import goEnter from "./components/go-enter.vue";
 import goFlow from "./components/go-flow.vue";
 import goExamine from "./components/go-examine.vue";
-const userInfo = ref(0);
+const userInfo = ref(1);
 
 // 当前步骤:0-首页,1-第一步,2-第二步
 const currentStep = ref(0);

+ 44 - 9
src/views/home/notice.vue

@@ -10,6 +10,12 @@
 
     <!-- 通知列表 -->
     <div class="notice-list">
+      <!-- 空状态 -->
+      <div v-if="total === 0" class="empty-state">
+        <img src="@/assets/images/notData.png" alt="暂无数据" class="empty-image" />
+        <p class="empty-text">暂无数据</p>
+      </div>
+      <!-- 通知卡片列表 -->
       <div v-for="(item, index) in noticeList" :key="index" class="notice-card" :class="{ unread: !item.isRead }">
         <div class="card-header">
           <h3 class="card-title">
@@ -42,7 +48,8 @@
 import { ref, onMounted } from "vue";
 import { ElMessage } from "element-plus";
 import { CircleCheck } from "@element-plus/icons-vue";
-import { getNoticeList } from "@/api/modules/homeEntry.ts";
+import { getNoticeList, markAllNoticesAsRead } from "@/api/modules/homeEntry.ts";
+import mittBus from "@/utils/mittBus";
 
 interface NoticeItem {
   id: number;
@@ -57,11 +64,13 @@ onMounted(() => {
 });
 
 const noticeList = ref<NoticeItem[]>([]);
+const total = ref<number>(0);
 const getList = async () => {
-  let res = await getNoticeList({ pageNum: 1, pageSize: 10, receiverId: "15242687180" });
+  let res: any = await getNoticeList({ pageNum: 1, pageSize: 10, receiverId: "" });
   console.log(res);
   if (res.code == "200") {
-    noticeList.value = res.data.records;
+    noticeList.value = res.data?.records || res.data?.list || [];
+    total.value = res.data?.total || 0;
   }
 };
 
@@ -69,17 +78,26 @@ const dialogVisible = ref(false);
 const currentNotice = ref<NoticeItem | null>(null);
 
 // 一键已读
-const handleMarkAllRead = () => {
-  noticeList.value.forEach(item => {
-    item.isRead = true;
-  });
-  ElMessage.success("已全部标记为已读");
+const handleMarkAllRead = async () => {
+  let res: any = await markAllNoticesAsRead({ receiverId: "" });
+  if (res.code == "200") {
+    ElMessage.success("操作成功");
+    getList();
+    // 通知 Message 组件更新未读数量
+    mittBus.emit("updateUnreadCount");
+  } else {
+    ElMessage.error(res.message);
+  }
 };
 
 // 查看详情
 const handleViewDetail = (item: NoticeItem) => {
   // 标记为已读
-  item.isRead = true;
+  if (!item.isRead) {
+    item.isRead = true;
+    // 通知 Message 组件更新未读数量
+    mittBus.emit("updateUnreadCount");
+  }
   // 显示详情对话框
   currentNotice.value = item;
   dialogVisible.value = true;
@@ -115,6 +133,23 @@ const handleViewDetail = (item: NoticeItem) => {
     display: flex;
     flex-direction: column;
     gap: 16px;
+    .empty-state {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      padding: 80px 20px;
+      .empty-image {
+        width: 360px;
+        height: 360px;
+        margin-bottom: 20px;
+      }
+      .empty-text {
+        margin: 0;
+        font-size: 16px;
+        color: #909399;
+      }
+    }
     .notice-card {
       padding: 20px;
       background: #ffffff;

+ 5 - 2
src/views/home/userInfo.vue

@@ -2,7 +2,7 @@
   <div class="user-info-page">
     <div class="top-bar">
       <el-button class="back-btn" @click="handleBack"> 返回 </el-button>
-      <div class="title">个人信息</div>
+      <div class="title">个人信息111</div>
     </div>
     <div class="form-wrap">
       <el-form :model="form" :rules="rules" ref="formRef" label-width="72px">
@@ -35,7 +35,10 @@
 import { ref, reactive } from "vue";
 import { ElMessage, type FormInstance, type FormRules } from "element-plus";
 import { Plus } from "@element-plus/icons-vue";
-
+import { localGet } from "@/utils/index";
+console.log(localGet);
+const info = localGet("geeker-user");
+console.log(1111111, info);
 const formRef = ref<FormInstance>();
 const form = reactive({
   avatarList: [] as any[],