zhuli vor 1 Monat
Ursprung
Commit
238f3c982f

+ 5 - 1
src/api/modules/homeEntry.ts

@@ -23,7 +23,7 @@ export const getNoticeList = params => {
 };
 //通知列表  一键已读
 export const markAllNoticesAsRead = params => {
-  return http.get<StoreUser.ResStoreUserList>(PORT_NONE + `/notice/markAllNoticesAsRead`, params);
+  return http.post(PORT_NONE + `/notice/markAllNoticesAsRead`, params);
 };
 //今日订单量
 export const getTodayOrderCount = params => {
@@ -46,6 +46,10 @@ export const updateMerchantUserInfo = params => {
   return http.post(PORT_NONE + `/merchantUser/updateMerchantUserInfo`, params);
 };
 
+//财务   可提现金额
+export const getAccountBalance = params => {
+  return http.post(PORT_NONE + `/incomeManage/getAccountBalance`, params);
+};
 export const getUserByPhone = params => {
   return http.get(PORT_NONE + `/merchantUser/getMerchantByPhone`, params);
 };

BIN
src/assets/financial/financeBg.png


BIN
src/assets/financial/gold.png


+ 1 - 1
src/layouts/components/Header/components/InfoDialog.vue

@@ -116,7 +116,7 @@ const getSaveUserInfo = async () => {
       accountBlurb: form.intro
     });
 
-    if (res.code === "200" || res.code === 200) {
+    if (res.code == 200) {
       ElMessage.success(res.msg || "保存成功");
       dialogVisible.value = false;
       // 可以刷新用户信息

+ 2 - 2
src/layouts/components/Header/components/PasswordDialog.vue

@@ -176,7 +176,7 @@ const handleConfirm = async () => {
         confirmNewPassword: passwordForm.newPassword
       });
 
-      if (res.code === "200" || res.code === 200) {
+      if (res.code === 200) {
         ElMessage.success(res.msg || "密码修改成功");
         dialogVisible.value = false;
         if (passwordFormRef.value) {
@@ -258,7 +258,7 @@ const handleForgotPasswordConfirm = async () => {
         newPassword: forgotPasswordForm.newPassword
       });
 
-      if (res.code === "200" || res.code === 200) {
+      if (res.code === 200) {
         ElMessage.success(res.msg || "密码修改成功");
         forgotPasswordVisible.value = false;
         if (forgotPasswordFormRef.value) {

+ 0 - 93
src/views/financialManagement/detail.vue

@@ -1,93 +0,0 @@
-<template>
-  <div class="card content-box">
-    <el-form :model="formData" label-width="140px">
-      <el-row>
-        <el-col :span="12">
-          <el-form-item label="店铺名称 :">
-            <span>{{ formData.storeName }}</span>
-          </el-form-item>
-          <el-form-item label="名称 :">
-            <span>{{ formData.name }}</span>
-          </el-form-item>
-          <el-form-item label="描述 :">
-            <span>{{ formData.description }}</span>
-          </el-form-item>
-        </el-col>
-        <el-col :span="12">
-          <el-form-item label="状态:">
-            <span>{{ getStatusName(formData.status) }}</span>
-          </el-form-item>
-          <el-form-item label="拒绝原因:" v-if="formData.status === '2'">
-            <span>{{ formData.rejectionReason }}</span>
-          </el-form-item>
-        </el-col>
-      </el-row>
-      <el-row class="text-center" style="margin-top: 20px">
-        <el-col :span="24">
-          <el-button type="primary" @click="goBack"> 确定 </el-button>
-        </el-col>
-      </el-row>
-    </el-form>
-  </div>
-</template>
-
-<script setup lang="tsx" name="financialManagementDetail">
-import { ref, onMounted } from "vue";
-import { useRoute, useRouter } from "vue-router";
-import { ElMessage } from "element-plus";
-import { getStaffConfigDeatail } from "@/api/modules/staffConfig";
-
-const route = useRoute();
-const router = useRouter();
-
-const formData = ref({});
-
-const id = ref((route.query.id as string) || "");
-
-const getStatusName = (status: string) => {
-  switch (status) {
-    case "0":
-      return "待审核";
-    case "1":
-      return "审核通过";
-    case "2":
-      return "审核拒绝";
-    default:
-      return "未知状态";
-  }
-};
-
-onMounted(async () => {
-  await initData();
-});
-
-const initData = async () => {
-  if (id.value) {
-    try {
-      const response = await getStaffConfigDeatail({ id: id.value });
-      if (response.code === 200) {
-        formData.value = response.data;
-      }
-    } catch (error) {
-      ElMessage.error("获取详情失败");
-    }
-  }
-};
-
-const goBack = () => {
-  router.go(-1);
-};
-</script>
-
-<style lang="scss" scoped>
-.el-form {
-  width: 100%;
-  .text-center {
-    text-align: center;
-  }
-}
-.el-col {
-  box-sizing: border-box;
-  padding-right: 10px;
-}
-</style>

+ 162 - 173
src/views/financialManagement/index.vue

@@ -1,207 +1,196 @@
 <template>
-  <div class="financial-dashboard">
-    <h3 class="title"><el-image :src="homeIcon" class="homeIcon" />账户总览</h3>
-    <el-row :gutter="16">
-      <el-col v-for="card in cards" :key="card.key" :span="5">
-        <div class="summary-card" :class="{ 'is-disabled': card.disabled }">
-          <div class="card-header">
-            <div class="header-left">
-              <span class="card-title">{{ card.title }}</span>
-              <el-tooltip v-if="card.tooltip" :content="card.tooltip" placement="top">
-                <el-icon class="info-icon">
-                  <QuestionFilled />
-                </el-icon>
-              </el-tooltip>
-            </div>
-            <el-icon v-if="card.showArrow" class="arrow-icon" @click="handleAction(card)">
-              <ArrowRight />
+  <div class="finance-page">
+    <!-- 今日收益 -->
+    <el-card class="summary-card" shadow="hover">
+      <div class="card-img">
+        <div class="summary-header">
+          <span class="title">今日收益1</span>
+          <el-tooltip content="今日收益为今天入账的金额" placement="top">
+            <el-icon class="question-icon">
+              <QuestionFilled />
             </el-icon>
+          </el-tooltip>
+        </div>
+        <div class="summary-body">
+          <el-image :src="gold" class="gold" />
+          <div class="summary-amount">
+            <span class="currency">¥</span>
+            <span class="amount">{{ formatCurrency(summaryData.todayIncome) }}</span>
+            <span class="unit">元</span>
           </div>
-          <div class="card-amount">¥{{ formatAmount(card.amount) }}</div>
-          <div class="card-button-wrapper">
-            <el-button
-              v-if="card.buttonText"
-              class="card-button"
-              size="large"
-              :type="card.disabled ? 'default' : 'primary'"
-              :plain="card.disabled"
-              :disabled="card.disabled"
-              @click="handleAction(card)"
-            >
-              {{ card.buttonText }}
-            </el-button>
-          </div>
         </div>
-      </el-col>
-    </el-row>
+      </div>
+    </el-card>
+
+    <!-- 统计信息 -->
+    <div class="stat-cards">
+      <el-card v-for="stat in stats" :key="stat.key" class="stat-card" shadow="hover">
+        <div class="stat-header">
+          <span class="stat-title">{{ stat.title }}</span>
+          <el-tooltip :content="stat.tooltip" placement="top" v-if="stat.tooltip">
+            <el-icon class="question-icon">
+              <QuestionFilled />
+            </el-icon>
+          </el-tooltip>
+        </div>
+        <div class="stat-amount">
+          {{ formatCurrency(stat.amount) }}
+        </div>
+        <el-button type="primary" class="stat-btn" @click="handleAction(stat.key)">
+          {{ stat.buttonText }}
+        </el-button>
+      </el-card>
+    </div>
   </div>
 </template>
 
-<script setup lang="ts" name="financialManagement">
-import homeIcon from "../../assets/images/home-icon.png";
-
-import { computed } from "vue";
+<script setup lang="ts">
+import { ref, reactive, watch, onMounted } from "vue";
+import { QuestionFilled } from "@element-plus/icons-vue";
+import gold from "../../assets/financial/gold.png";
+import { getAccountBalance } from "@/api/modules/homeEntry";
+import { localGet } from "@/utils/index";
 import { useRouter } from "vue-router";
-import { ArrowRight, QuestionFilled } from "@element-plus/icons-vue";
-
-type FinancialCard = {
-  key: string;
-  title: string;
-  amount: number;
-  tooltip?: string;
-  buttonText?: string;
-  disabled?: boolean;
-  showArrow?: boolean;
-  route?: string;
-  action?: () => void;
-};
-
 const router = useRouter();
-
-const cards = computed<FinancialCard[]>(() => [
-  {
-    key: "todayIncome",
-    title: "今日收益",
-    amount: 0,
-    tooltip: "今日收益=今日已核销到账金额-技术服务费",
-    showArrow: true,
-    route: "/financialManagement/detail"
-  },
-  {
-    key: "withdrawable",
-    title: "可提现金额",
-    amount: 0,
-    tooltip: "收益产生后3天可提现,28天自动",
-    buttonText: "提现",
-    disabled: true
-  },
-  {
-    key: "arrivedAmount",
-    title: "已到账期金额",
-    amount: 0,
-    tooltip: "已完成入账的金额总计",
-    buttonText: "查看",
-    route: "/financialManagement/detail"
-  },
-  {
-    key: "pendingAmount",
-    title: "未到账期金额",
-    amount: 0,
-    tooltip: "正在处理中的预计入账金额",
-    buttonText: "查看",
-    route: "/financialManagement/detail"
+onMounted(() => {
+  fetchAccountBalance();
+});
+//可提现金额
+const fetchAccountBalance = async () => {
+  let param = {
+    storeId: 138
+  };
+  const res: any = await getAccountBalance(param as any);
+  if (res.code == 200) {
   }
-]);
+};
+const summaryData = {
+  todayIncome: 65411
+};
 
-const handleAction = (card: FinancialCard) => {
-  if (card.disabled) return;
-  if (card.action) {
-    card.action();
-    return;
-  }
-  if (card.route) {
-    router.push(card.route);
-  }
+const stats = [
+  { key: "withdraw", title: "可提现金额", amount: 932110, buttonText: "提现", tooltip: "可用于提现的金额" },
+  { key: "settled", title: "已到账期金额", amount: 932110, buttonText: "查看明细", tooltip: "已结算到账的金额" },
+  { key: "pending", title: "未到账期金额", amount: 932110, buttonText: "查看明细", tooltip: "正在结算中的金额" }
+];
+
+const formatCurrency = (value: number) => {
+  return value.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
 };
 
-const formatAmount = (value: number) => {
-  return value.toLocaleString("zh-CN", { minimumFractionDigits: 0, maximumFractionDigits: 2 });
+const handleAction = (key: string) => {
+  switch (key) {
+    case "withdraw":
+      router.push("/financialManagement/realName");
+      break;
+    default:
+      console.log("查看明细");
+  }
 };
 </script>
 
 <style scoped lang="scss">
-.financial-dashboard {
-  box-sizing: border-box;
+.finance-page {
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+  min-height: calc(100vh - 100px);
+}
+.summary-card {
+  position: relative;
   width: 100%;
-  height: calc(100vh - 105px);
   overflow: hidden;
-  background: url("../../assets/images/home-bg.png") center center no-repeat;
-  background-size: cover;
-  .title {
+  border: none;
+  border-radius: 16px;
+  .card-img {
+    width: 100%;
+    height: 214px;
+    background: url("../../assets/financial/financeBg.png") no-repeat;
+    background-position: right;
+    background-size: contain;
+  }
+  .summary-header {
     display: flex;
+    gap: 8px;
     align-items: center;
-    height: 105px;
-    font-size: 20px;
-    font-weight: 600;
-    color: #ffffff;
-    background: linear-gradient(90deg, #6c8ff8 0%, rgb(255 255 255 / 0%) 100%);
-    .homeIcon {
-      width: 76px;
-      height: 76px;
-      margin-right: 8px;
-      margin-left: 25px;
+    margin-bottom: 12px;
+    font-size: 16px;
+    color: #333333;
+    .question-icon {
+      color: #9aa4c2;
+      cursor: pointer;
     }
-
-    border-radius: 10px;
   }
-  :deep(.el-row) {
+  .summary-body {
     display: flex;
-    margin: 0 !important;
+    gap: 24px;
+    align-items: center;
+    justify-content: center;
+    width: 757px;
+    height: 140px;
+    padding: 12px 0;
+    margin: auto;
+    font-weight: 600;
+    background: #6c8ff8;
+    border-radius: 74px;
+    box-shadow: 0 5px 0 0 #355ac8;
   }
-  :deep(.el-col) {
+  .summary-amount {
     display: flex;
-  }
-}
-.summary-card {
-  display: flex;
-  flex-direction: column;
-  gap: 12px;
-  justify-content: space-between;
-  height: 100%;
-  min-height: 148px;
-  padding: 20px 90px;
-  background-color: #ffffff;
-  border: 1px solid #e5e6eb;
-  border-radius: 8px;
-  transition: box-shadow 0.2s;
-  &:hover {
-    box-shadow: 0 6px 12px rgb(31 41 55 / 10%);
-  }
-  &.is-disabled {
-    .card-button {
-      cursor: not-allowed;
+    gap: 8px;
+    align-items: baseline;
+    font-weight: 600;
+    .currency {
+      padding: 8px 16px;
+      font-size: 80px;
+      color: #ffffff;
+      border-radius: 999px 0 0 999px;
+    }
+    .amount {
+      font-size: 80px;
+      color: #ffffff;
+    }
+    .unit {
+      font-size: 16px;
+      color: #ffffff;
     }
   }
 }
-.card-header {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  .header-left {
-    display: inline-flex;
-    gap: 6px;
-    align-items: center;
+.stat-cards {
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  gap: 16px;
+  .stat-card {
+    padding: 16px;
+    text-align: center;
+    border: none;
+    border-radius: 12px;
+    .stat-header {
+      display: inline-flex;
+      gap: 6px;
+      align-items: center;
+      margin-bottom: 16px;
+      font-size: 16px;
+      color: #222222;
+    }
+    .stat-amount {
+      margin-bottom: 20px;
+      font-size: 32px;
+      font-weight: 600;
+      color: #222222;
+    }
+    .stat-btn {
+      width: 120px;
+      background: #7f9dff;
+      border: none;
+      border-radius: 6px;
+    }
   }
 }
-.card-title {
-  font-size: 16px;
-  font-weight: 500;
-  color: #1d2129;
-}
-.card-amount {
-  font-size: 28px;
-  font-weight: 600;
-  line-height: 1.2;
-  color: #1d2129;
-}
-.card-button-wrapper {
-  display: flex;
-  align-items: flex-end;
-  min-height: 40px;
-}
-.card-button {
-  width: 100%;
-}
-.info-icon {
-  font-size: 16px;
-  color: #86909c;
-}
-.arrow-icon {
-  font-size: 18px;
-  color: #c9ccd3;
-  cursor: pointer;
-  &:hover {
-    color: #165dff;
+
+@media (width <= 1024px) {
+  .stat-cards {
+    grid-template-columns: repeat(1, 1fr);
   }
 }
 </style>

+ 497 - 0
src/views/financialManagement/realName.vue

@@ -0,0 +1,497 @@
+<template>
+  <div class="real-name-page">
+    <!-- 头部区域 -->
+    <div class="header-section">
+      <div class="header-content">
+        <div class="shop-info">
+          <el-image :src="homeIcon" class="homeIcon" />
+          <span class="shop-name">每天汪汪的店铺</span>
+        </div>
+        <div class="auth-status">
+          <span class="status-badge">未认证</span>
+        </div>
+      </div>
+    </div>
+
+    <!-- 标签导航栏 -->
+    <div class="tabs-section">
+      <el-tabs v-model="activeTab" @tab-click="handleTabClick">
+        <el-tab-pane label="实名认证" name="realName" />
+        <el-tab-pane label="提现密码" name="withdrawPassword" />
+        <el-tab-pane label="收款账户" name="receivingAccount" />
+      </el-tabs>
+    </div>
+
+    <!-- 实名认证 -->
+    <div class="content-section" v-if="activeTab === 'realName'">
+      <div class="content-wrapper">
+        <el-button type="primary" class="auth-button" @click="handleGoAuth"> 去实名认证 </el-button>
+      </div>
+    </div>
+
+    <!-- 提现密码 -->
+    <div class="content-section" v-if="activeTab === 'withdrawPassword'">
+      <div class="content-wrapper">
+        <!-- <div class="password-form-wrapper">
+          <el-form ref="passwordFormRef" :model="passwordForm" :rules="passwordRules" label-width="120px" label-position="left">
+            <el-form-item label="设置提现密码" prop="password">
+              <el-input
+                v-model="passwordForm.password"
+                type="password"
+                placeholder="请输入6位提现密码"
+                clearable
+                maxlength="6"
+                show-password
+                class="password-input"
+              />
+            </el-form-item>
+            <el-form-item label="请确认密码" prop="confirmPassword">
+              <el-input
+                v-model="passwordForm.confirmPassword"
+                type="password"
+                placeholder="请输入6位提现密码"
+                clearable
+                maxlength="6"
+                show-password
+                class="password-input"
+              />
+            </el-form-item>
+            <el-form-item>
+              <el-button type="primary" class="submit-button" :loading="passwordLoading" @click="handlePasswordSubmit">
+                确认
+              </el-button>
+            </el-form-item>
+          </el-form>
+        </div> -->
+        <div class="password-form-wrapper-step">
+          <el-steps :active="currentStep" style="max-width: 600px">
+            <el-step v-for="(item, index) in passList" :key="index">
+              <template #title>
+                <div class="step-title-wrapper">
+                  <span class="step-title">{{ item.title }}</span>
+                </div>
+              </template>
+            </el-step>
+          </el-steps>
+          <el-form
+            ref="passwordFormRef"
+            :model="passwordForm"
+            :rules="passwordRules"
+            label-width="100px"
+            label-position="left"
+            class="form-wrapper"
+          >
+            <el-form-item label="验证原密码" prop="password">
+              <el-input
+                v-model="passwordForm.password"
+                type="password"
+                placeholder="请输入6位提现密码"
+                clearable
+                maxlength="6"
+                show-password
+                class="password-input"
+              />
+            </el-form-item>
+          </el-form>
+          <div class="forget-password">忘记密码</div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 忘记密码对话框 -->
+    <el-dialog v-model="forgotPasswordVisible" title="忘记密码" width="500px" draggable :close-on-click-modal="false">
+      <el-form
+        ref="forgotPasswordFormRef"
+        :model="forgotPasswordForm"
+        :rules="forgotPasswordRules"
+        label-width="100px"
+        label-position="left"
+      >
+        <el-form-item label="手机号码">
+          <span>{{ maskedPhone }}</span>
+        </el-form-item>
+
+        <el-form-item label="" prop="verificationCode">
+          <div style="display: flex; gap: 12px; width: 100%">
+            <el-input v-model="forgotPasswordForm.verificationCode" placeholder="请输入" clearable style="flex: 1" />
+            <el-button type="primary" :disabled="codeCountdown > 0" @click="sendLoginCode">
+              {{ codeCountdown > 0 ? `${codeCountdown}秒后重新获取` : "获取验证码" }}
+            </el-button>
+          </div>
+        </el-form-item>
+
+        <el-form-item label="输入新密码" prop="newPassword">
+          <el-input
+            v-model="forgotPasswordForm.newPassword"
+            type="password"
+            placeholder="请输入6-16位的密码,包含字母和数字"
+            show-password
+            clearable
+          />
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+
+    <!-- 实名认证对话框 -->
+    <el-dialog v-model="dialogVisible" title="实名认证" width="500px" :close-on-click-modal="false">
+      <el-form ref="authFormRef" :model="authForm" :rules="authRules" label-width="100px" label-position="left">
+        <el-form-item label="姓名" prop="name">
+          <el-input v-model="authForm.name" placeholder="请输入姓名" clearable />
+        </el-form-item>
+        <el-form-item label="身份证号码" prop="idCard">
+          <el-input v-model="authForm.idCard" placeholder="请输入身份证号码" clearable maxlength="18" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="handleCancel">取消</el-button>
+          <el-button type="primary" :loading="loading" @click="handleConfirm">确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive } from "vue";
+import { useRouter } from "vue-router";
+import { ElMessage, type FormInstance, type FormRules } from "element-plus";
+import { localGet } from "@/utils/index";
+import homeIcon from "../../assets/images/home-icon.png";
+
+const router = useRouter();
+const activeTab = ref("realName");
+const dialogVisible = ref(false);
+const loading = ref(false);
+const authFormRef = ref<FormInstance>();
+const passwordFormRef = ref<FormInstance>();
+const passwordLoading = ref(false);
+const currentStep = ref(0);
+const forgotPasswordVisible = ref(false);
+const forgotPasswordFormRef = ref<FormInstance>();
+const forgotPasswordForm = reactive({
+  verificationCode: "",
+  newPassword: ""
+});
+// 忘记密码表单验证规则
+const forgotPasswordRules: FormRules = {
+  verificationCode: [{ required: true, message: "请输入验证码", trigger: "blur" }]
+};
+const passList = [
+  {
+    title: "验证原密码"
+  },
+  {
+    title: "设置新密码"
+  }
+];
+// 获取用户手机号
+const userPhone = computed(() => {
+  return localGet("iphone") || localGet("geeker-user")?.userInfo?.phone || "";
+});
+// 掩码显示手机号
+const maskedPhone = computed(() => {
+  if (!userPhone.value || userPhone.value.length !== 11) {
+    return "";
+  }
+  return userPhone.value.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");
+});
+// 实名认证表单数据
+const authForm = reactive({
+  name: "",
+  idCard: ""
+});
+
+// 提现密码表单数据
+const passwordForm = reactive({
+  password: "",
+  confirmPassword: ""
+});
+
+// 实名认证表单验证规则
+const authRules = reactive<FormRules>({
+  name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
+  idCard: [
+    { required: true, message: "请输入身份证号码", trigger: "blur" },
+    {
+      pattern: /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/,
+      message: "请输入正确的身份证号码",
+      trigger: "blur"
+    }
+  ]
+});
+
+// 提现密码表单验证规则
+const passwordRules = reactive<FormRules>({
+  password: [
+    { required: true, message: "请输入6位提现密码", trigger: "blur" },
+    {
+      pattern: /^\d{6}$/,
+      message: "请输入6位数字密码",
+      trigger: "blur"
+    }
+  ],
+  confirmPassword: [
+    { required: true, message: "请确认密码", trigger: "blur" },
+    {
+      validator: (rule: any, value: any, callback: any) => {
+        if (value !== passwordForm.password) {
+          callback(new Error("两次输入的密码不一致"));
+        } else {
+          callback();
+        }
+      },
+      trigger: "blur"
+    }
+  ]
+});
+
+const handleTabClick = (tab: any) => {
+  // 根据不同的标签页可以跳转到不同的页面或显示不同的内容
+  console.log("切换到标签:", tab.props.name);
+  // 这里可以根据需要实现路由跳转或内容切换
+};
+
+const handleGoAuth = () => {
+  // 打开实名认证对话框
+  dialogVisible.value = true;
+  // 重置表单
+  if (authFormRef.value) {
+    authFormRef.value.resetFields();
+  }
+};
+
+const handleCancel = () => {
+  dialogVisible.value = false;
+  // 重置表单
+  if (authFormRef.value) {
+    authFormRef.value.resetFields();
+  }
+};
+
+const handleConfirm = async () => {
+  if (!authFormRef.value) return;
+
+  // 表单验证
+  await authFormRef.value.validate(valid => {
+    if (valid) {
+      loading.value = true;
+      // 这里可以调用API提交实名认证信息
+      // 模拟API调用
+      setTimeout(() => {
+        loading.value = false;
+        ElMessage.success("实名认证提交成功");
+        dialogVisible.value = false;
+        // 重置表单
+        authFormRef.value?.resetFields();
+        // 这里可以更新认证状态或刷新页面数据
+      }, 1000);
+    }
+  });
+};
+
+const handlePasswordSubmit = async () => {
+  if (!passwordFormRef.value) return;
+
+  // 表单验证
+  await passwordFormRef.value.validate(valid => {
+    if (valid) {
+      passwordLoading.value = true;
+      // 这里可以调用API设置提现密码
+      // 模拟API调用
+      setTimeout(() => {
+        passwordLoading.value = false;
+        ElMessage.success("提现密码设置成功");
+        // 重置表单
+        passwordFormRef.value?.resetFields();
+      }, 1000);
+    }
+  });
+};
+</script>
+
+<style scoped lang="scss">
+.real-name-page {
+  display: flex;
+  flex-direction: column;
+  min-height: calc(100vh - 100px);
+  background-color: #f5f7fa;
+}
+
+// 头部区域
+.header-section {
+  padding: 16px 24px;
+  background: linear-gradient(90deg, #6c8ff8 0%, rgb(255 255 255 / 0%) 100%);
+  border-bottom: 1px solid #e4e7ed;
+  border-radius: 10px;
+  .header-content {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    max-width: 100%;
+    margin: 0 auto;
+    .shop-info {
+      display: flex;
+      gap: 12px;
+      align-items: center;
+      .homeIcon {
+        width: 76px;
+        height: 76px;
+        margin-right: 8px;
+        margin-left: 25px;
+      }
+      .shop-icon {
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        width: 32px;
+        height: 32px;
+        background-color: #ffffff;
+        border-radius: 6px;
+        box-shadow: 0 2px 4px rgb(0 0 0 / 10%);
+      }
+      .shop-name {
+        font-size: 16px;
+        font-weight: 500;
+        color: #ffffff;
+      }
+    }
+    .auth-status {
+      .status-badge {
+        display: inline-block;
+        padding: 3px 20px;
+        font-size: 14px;
+        font-weight: 500;
+        color: #ffffff;
+        background: #f81515;
+        border-radius: 39px;
+      }
+    }
+  }
+}
+
+// 标签导航栏
+.tabs-section {
+  padding: 0 24px;
+  background-color: #ffffff;
+  border-bottom: 1px solid #e4e7ed;
+  :deep(.el-tabs) {
+    max-width: 100%;
+    margin: 0 auto;
+    .el-tabs__header {
+      margin: 0;
+      border-bottom: none;
+    }
+    .el-tabs__nav-wrap::after {
+      height: 1px;
+      background-color: #e4e7ed;
+    }
+    .el-tabs__item {
+      height: 48px;
+      padding: 0 20px;
+      font-size: 15px;
+      font-weight: 400;
+      line-height: 48px;
+      color: #606266;
+      &.is-active {
+        font-weight: 500;
+        color: #409eff;
+        &::after {
+          position: absolute;
+          bottom: 0;
+          left: 50%;
+          width: 40px;
+          height: 3px;
+          content: "";
+          background-color: #409eff;
+          border-radius: 2px 2px 0 0;
+          transform: translateX(-50%);
+        }
+      }
+      &:hover {
+        color: #409eff;
+      }
+    }
+  }
+}
+
+// 主内容区
+.content-section {
+  display: flex;
+  flex: 1;
+
+  // align-items: center;
+  justify-content: center;
+  min-height: 400px;
+  background-color: #ffffff;
+  .content-wrapper {
+    display: flex;
+
+    // align-items: center;
+    justify-content: center;
+    width: 100%;
+    padding: 40px 24px;
+    .auth-button {
+      padding: 22px 35px;
+      font-size: 16px;
+      font-weight: 500;
+      background-color: #6c8ff8;
+      border: none;
+      border-radius: 6px;
+      transition: all 0.3s;
+    }
+  }
+  .password-form-wrapper {
+    width: 100%;
+    max-width: 500px;
+    padding: 40px;
+    background-color: #ffffff;
+    border: 1px solid red;
+    border-radius: 8px;
+    .password-input {
+      width: 100%;
+    }
+    .submit-button {
+      width: 100%;
+      padding: 12px;
+      margin-top: 20px;
+      font-size: 16px;
+      font-weight: 500;
+      background-color: #6c8ff8;
+      border: none;
+      border-radius: 6px;
+    }
+    :deep(.el-form-item__label) {
+      font-weight: 500;
+      color: #303133;
+    }
+  }
+  .password-form-wrapper-step {
+    width: 600px;
+    .form-wrapper {
+      width: 600px;
+      margin-top: 40px;
+    }
+    .forget-password {
+      font-size: 14px;
+      color: #6c8ff8;
+      text-align: right;
+      cursor: pointer;
+    }
+    :deep(.el-step__head.is-process .el-step__icon) {
+      color: #909399;
+      border-color: #909399 !important; /* 设置圆圈边框为灰色 */
+    }
+    :deep(.el-steps) {
+      .el-step__head {
+        .el-step__icon {
+          width: 30px;
+          height: 30px;
+          font-size: 16px;
+          font-weight: 600;
+        }
+      }
+    }
+  }
+}
+</style>

+ 6 - 5
src/views/home/components/go-examine.vue

@@ -53,6 +53,7 @@ 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";
+import { localGet } from "@/utils/index";
 // 数据(可根据实际接口替换)
 const storeName = ref("时间图书馆");
 const expireDate = ref("2027/10/29");
@@ -66,13 +67,13 @@ onMounted(() => {
   getInCome();
 });
 const getOrder = async () => {
-  const res = await getTodayOrderCount({ storeId: 120 });
-  if (res.success) {
+  const res: any = await getTodayOrderCount({ storeId: localGet("geeker-user").storeId });
+  if (res.code == 200) {
     todayOrders.value = res.data;
   }
 };
 const getInCome = async () => {
-  const res = await getTodayIncome({ storeId: 120 });
+  const res: any = await getTodayIncome({ storeId: localGet("geeker-user").storeId });
   if (res.success) {
     todayRevenue.value = res.data;
   }
@@ -80,8 +81,8 @@ const getInCome = async () => {
 const handleVerify = async () => {
   // 调用验券接口
   if (!voucherCode.value) return;
-  const res = await verifyOrder({ orderCode: voucherCode.value });
-  if (res.success) {
+  const res: any = await verifyOrder({ orderCode: voucherCode.value });
+  if (res.code == 200) {
     let i = {
       quanCode: voucherCode.value,
       storeId: 120

+ 53 - 29
src/views/home/components/go-flow.vue

@@ -106,15 +106,15 @@
                   <el-radio label="筹建中"> 筹建中 </el-radio>
                 </el-radio-group>
               </el-form-item>
-              <el-form-item label="经度" prop="storePositionLongitude">
+              <el-form-item label="经度" prop="storePositionLongitude" v-show="latShow">
                 <el-input disabled v-model="step2Form.storePositionLongitude" placeholder="请填写经度" clearable />
               </el-form-item>
-              <el-form-item label="纬度" prop="storePositionLatitude">
+              <el-form-item label="纬度" prop="storePositionLatitude" v-show="latShow">
                 <el-input disabled v-model="step2Form.storePositionLatitude" placeholder="请填写纬度" clearable />
               </el-form-item>
-              <el-form-item label="经纬度查询">
+              <el-form-item label="经纬度查询" prop="address">
                 <el-select
-                  v-model="address"
+                  v-model="step2Form.address"
                   filterable
                   placeholder="请输入地址进行查询"
                   remote
@@ -161,7 +161,7 @@
                 </el-upload>
               </el-form-item>
 
-              <el-form-item label="食品经营许可证" prop="foodLicenceImgList ">
+              <el-form-item label="食品经营许可证" prop="foodLicenceImgList">
                 <el-upload
                   v-model:file-list="step2Form.foodLicenceImgList"
                   :http-request="handleHttpUpload"
@@ -189,7 +189,9 @@
     <!-- 第三步: 等待审核-->
     <div v-if="currentStep === 3">
       <div class="button-container">
-        <el-button type="danger" size="large" class="register-btn" v-if="userInfo.status == 3"> 审核拒绝,重新入驻 </el-button>
+        <el-button type="danger" size="large" class="register-btn-red" @click="changeRefuse" v-if="storeApplicationStatus == 2">
+          审核拒绝,重新入驻
+        </el-button>
         <el-button type="primary" size="large" class="register-btn" v-else> 等待审核 </el-button>
       </div>
     </div>
@@ -208,20 +210,15 @@ import {
 } from "element-plus";
 import { Plus } from "@element-plus/icons-vue";
 
-import { verifyIdInfo, applyStore } from "@/api/modules/homeEntry.ts";
-import {
-  getBusinessSection,
-  getBusinessSectionTypes,
-  getInputPrompt,
-  getDistrict,
-  uploadImg
-} from "@/api/modules/newLoginApi.ts";
+import { verifyIdInfo, applyStore } from "@/api/modules/homeEntry";
+import { getBusinessSection, getBusinessSectionTypes, getInputPrompt, getDistrict, uploadImg } from "@/api/modules/newLoginApi";
 import { localGet } from "@/utils/index";
 const userInfo = localGet("geeker-user")?.userInfo || {};
-import { add } from "lodash";
+const latShow = ref(false);
 onMounted(() => {
   getBusinessSectionList();
-  getBusinessTypes();
+  getBusinessTypes(null);
+  callGetUserInfo();
 });
 const entryList = ref([
   {
@@ -245,7 +242,7 @@ const step2Rules: FormRules = {
   storeIntro: [{ required: true, message: "请输入门店简介", trigger: "blur" }],
   businessSection: [{ required: true, message: "请选择经营板块", trigger: "change" }],
   businessTypes: [{ required: true, message: "请选择经营种类", trigger: "change" }],
-  address: [{ required: true, message: "请输入经纬度", trigger: "change" }],
+  address: [{ required: true, message: "请输入经纬度", trigger: "blur" }],
   businessLicenseAddress: [{ required: true, message: "请上传营业执照", trigger: "change" }],
   contractImageList: [{ required: true, message: "请上传合同图片", trigger: "change" }],
   foodLicenceImgList: [{ required: true, message: "请上传食品经营许可证", trigger: "change" }]
@@ -255,27 +252,43 @@ const step2Rules: FormRules = {
 const addressList = ref<any[]>([]);
 //查询地址名称
 const queryAddress = ref<string>("");
-//地址名称
-const address = ref<string>("");
 
 const props = defineProps({
   currentStep: {
     type: Number,
     value: 0
+  },
+  storeApplicationStatus: {
+    type: Number,
+    value: 0
   }
 });
+const emit = defineEmits(["update:currentStep", "update:get-user-info"]);
 
-const emit = defineEmits(["update:currentStep"]);
+// 调用父组件的 getUserInfo 方法
+const callGetUserInfo = () => {
+  emit("update:get-user-info");
+};
 
 // 内部步骤状态,和父组件同步
 const currentStep = ref<number>(props.currentStep || 0);
+const storeApplicationStatus = ref<number>(props.storeApplicationStatus || 0);
+console.log(storeApplicationStatus);
 watch(
   () => props.currentStep,
   val => {
     if (typeof val === "number") currentStep.value = val;
   }
 );
-
+watch(
+  () => props.storeApplicationStatus,
+  val => {
+    if (typeof val === "number") storeApplicationStatus.value = val;
+  }
+);
+const changeRefuse = () => {
+  currentStep.value = 2;
+};
 const setStep = (val: number) => {
   currentStep.value = val;
   emit("update:currentStep", val);
@@ -314,7 +327,7 @@ const step2Form = reactive({
   administrativeRegionDistrictAdcode: "", //区
   storeAddress: "", //门店地址(完整地址)
   storeBlurb: "", //门店简介
-  businessSection: "3", //经营板块
+  businessSection: "", //经营板块
   businessSectionName: "KTV",
   businessTypes: [], //经营种类
   businessTypesList: [], //经营种类集合
@@ -325,7 +338,8 @@ const step2Form = reactive({
   storePositionLatitude: "", //纬度
   businessLicenseAddress: [] as UploadUserFile[], //营业执照地址
   contractImageList: [] as UploadUserFile[], //合同图片集合
-  foodLicenceImgList: [] as UploadUserFile[] //食品经营许可证
+  foodLicenceImgList: [] as UploadUserFile[], //食品经营许可证
+  address: ""
 });
 
 // 返回按钮
@@ -437,14 +451,15 @@ const getLonAndLat = async (keyword: string) => {
   }
 };
 const selectAddress = async (param: any) => {
-  let locationList = address.value.split(",");
+  let locationList = step2Form.address.split(",");
   addressList.value.forEach((item: any) => {
-    if (item.location == address.value) {
+    if (item.location == step2Form.address) {
       queryAddress.value = item.name;
     }
   });
   step2Form.storePositionLongitude = locationList[0];
   step2Form.storePositionLatitude = locationList[1];
+  latShow.value = true;
 };
 //文件上传
 const handleHttpUpload = async (options: UploadRequestOptions) => {
@@ -484,8 +499,8 @@ const handleNextStep = async () => {
         idCard: step1Form.idNumber,
         appType: 1
       };
-      const res = await verifyIdInfo(params);
-      if (res.code == "200") {
+      const res: any = await verifyIdInfo(params);
+      if (res && res.code == 200) {
         ElMessage.success(res.msg);
 
         setStep(2);
@@ -632,8 +647,8 @@ const handleSubmit = async () => {
       })
         .then(async () => {
           try {
-            const res = await applyStore(params);
-            if (res.code === "200") {
+            const res: any = await applyStore(params);
+            if (res && res.code == 200) {
               setStep(3); // 跳转到等待审核步骤
               ElMessage.success(res.msg);
             } else {
@@ -748,5 +763,14 @@ const handleExceed = () => {
     border-radius: 4px;
     outline: none;
   }
+  .register-btn-red {
+    width: 200px;
+    height: 44px;
+    font-size: 16px;
+    font-weight: 500;
+    border: 0;
+    border-radius: 4px;
+    outline: none;
+  }
 }
 </style>

+ 53 - 11
src/views/home/index.vue

@@ -1,34 +1,76 @@
 <template>
   <div id="home">
+    <!--已入驻-->
+    <go-examine v-if="isExaime" />
     <!-- 第一步  未入驻 -->
     <go-enter :current-step="currentStep" @update:current-step="handleUpdateCurrentStep" v-if="isEntry" />
 
-    <!--已入驻-->
-    <go-examine v-else />
-
     <!-- 第二步 -->
-    <go-flow :current-step="currentStep" @update:current-step="handleUpdateCurrentStep" />
+    <go-flow
+      :current-step="currentStep"
+      @update:current-step="handleUpdateCurrentStep"
+      @update:get-user-info="getUserInfo"
+      :store-application-status="storeApplicationStatus"
+    />
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref } from "vue";
-import { localGet, localSet } from "@/utils/index";
+import { onMounted, ref } from "vue";
+import { localGet } from "@/utils/index";
 import goEnter from "./components/go-enter.vue";
 import goFlow from "./components/go-flow.vue";
 import goExamine from "./components/go-examine.vue";
-const userInfo = ref(2);
+import { getMerchantByPhone, getDetail } from "@/api/modules/homeEntry";
 const isEntry = ref<boolean>(false);
-if (!localGet("businessSection") && !localGet("geeker-user").userInfo.businessSection) {
-  isEntry.value = true;
-}
+const isExaime = ref<boolean>(false);
+
+onMounted(() => {
+  getUserInfo();
+});
+
 // 当前步骤:0-首页,1-第一步,2-第二步
 const currentStep = ref(0);
-
+const storeId = ref<Number | undefined>(undefined);
 // 处理更新currentStep事件
 const handleUpdateCurrentStep = (step: number) => {
   currentStep.value = step;
 };
+let storeApplicationStatus = ref<number | undefined>(undefined);
+const getUserInfo = async () => {
+  try {
+    const geekerUser = localGet("geeker-user");
+    if (!geekerUser || !geekerUser.userInfo || !geekerUser.userInfo.phone) {
+      console.error("用户信息不存在");
+      return;
+    }
+    let param = {
+      phone: geekerUser.userInfo.phone
+    };
+    const res: any = await getMerchantByPhone(param);
+    storeId.value = res.data.storeId;
+    if (res && res.code == 200 && res.data && res.data.storeId) {
+      let param1 = {
+        id: res.data.storeId
+      };
+      const resStore: any = await getDetail(param1);
+      if (resStore && resStore.code == 200 && resStore.data) {
+        storeApplicationStatus.value = resStore.data.storeApplicationStatus;
+        if (storeApplicationStatus.value == 2) {
+          currentStep.value = 3;
+        }
+
+        if (resStore.data.storeApplicationStatus == 2 && res.data.storeId != null) {
+          isEntry.value = true;
+        } else {
+          isExaime.value = true;
+        }
+      }
+    }
+  } catch (error) {
+    console.error(error);
+  }
+};
 </script>
 
 <style scoped lang="scss"></style>

+ 33 - 18
src/views/home/notice.vue

@@ -23,14 +23,12 @@
             {{ item.title }}
           </h3>
           <div class="card-time-wrapper">
-            <span class="card-time">{{ item.time }}</span>
+            <span class="card-time">{{ item.createdTime }}</span>
             <span v-if="!item.isRead" class="unread-dot" />
           </div>
         </div>
         <div class="card-content">
-          {{ item.content }}
-        </div>
-        <div class="card-footer">
+          <div>{{ parseContext(item.context) }}</div>
           <el-button class="view-detail-btn" @click="handleViewDetail(item)"> 查看详情 </el-button>
         </div>
       </div>
@@ -52,7 +50,7 @@
     <!-- 详情对话框 -->
     <el-dialog v-model="dialogVisible" :title="currentNotice?.title" width="500px" :close-on-click-modal="false">
       <div class="dialog-content">
-        {{ currentNotice?.content }}
+        {{ parseContext(currentNotice?.context || currentNotice?.content) }}
       </div>
     </el-dialog>
   </div>
@@ -62,23 +60,23 @@
 import { ref, onMounted } from "vue";
 import { ElMessage } from "element-plus";
 import { CircleCheck } from "@element-plus/icons-vue";
-import { getNoticeList, markAllNoticesAsRead } from "@/api/modules/homeEntry.ts";
+import { getNoticeList, markAllNoticesAsRead } from "@/api/modules/homeEntry";
 import { useRouter } from "vue-router";
 const router = useRouter();
 import mittBus from "@/utils/mittBus";
 import { localGet } from "@/utils/index";
+import { get } from "lodash";
 
 interface NoticeItem {
   id: number;
   title: string;
   time: string;
   content: string;
+  context?: string;
   isRead: boolean;
 }
 
-onMounted(() => {
-  getList();
-});
+onMounted(() => {});
 // 返回按钮
 const handleBack = () => {
   router.back();
@@ -95,15 +93,18 @@ const getReceiverId = () => {
 };
 
 const getList = async () => {
-  const receiverId = getReceiverId();
-  let res: any = await getNoticeList({ pageNum: pageNum.value, pageSize: pageSize.value, receiverId });
-  console.log(res);
-  if (res.code == "200") {
+  let res: any = await getNoticeList({
+    pageNum: pageNum.value,
+    pageSize: pageSize.value,
+    receiverId: "store_" + getReceiverId(),
+    noticeType: 1
+  });
+  if (res.code == 200) {
     noticeList.value = res.data?.records || res.data?.list || [];
     total.value = res.data?.total || 0;
   }
 };
-
+getList();
 // 每页条数改变
 const handleSizeChange = (size: number) => {
   pageSize.value = size;
@@ -122,9 +123,8 @@ const currentNotice = ref<NoticeItem | null>(null);
 
 // 一键已读
 const handleMarkAllRead = async () => {
-  const receiverId = getReceiverId();
-  let res: any = await markAllNoticesAsRead({ receiverId });
-  if (res.code == "200") {
+  let res: any = await markAllNoticesAsRead({ receiverId: "store_" + getReceiverId(), noticeType: 1 });
+  if (res.code == 200) {
     ElMessage.success("操作成功");
     // 重置到第一页并刷新列表
     pageNum.value = 1;
@@ -136,6 +136,20 @@ const handleMarkAllRead = async () => {
   }
 };
 
+// 解析 context JSON 字符串,提取 message 字段
+const parseContext = (context: string | undefined): string => {
+  if (!context) return "";
+  try {
+    // 如果 context 是 JSON 字符串,先解析
+    const parsed = typeof context === "string" ? JSON.parse(context) : context;
+    // 提取 message 字段
+    return parsed?.message || context;
+  } catch (error) {
+    // 如果不是有效的 JSON,直接返回原字符串
+    return context;
+  }
+};
+
 // 查看详情
 const handleViewDetail = (item: NoticeItem) => {
   // 标记为已读
@@ -236,7 +250,8 @@ const handleViewDetail = (item: NoticeItem) => {
         }
       }
       .card-content {
-        margin-bottom: 16px;
+        display: flex;
+        justify-content: space-between;
         font-size: 14px;
         line-height: 1.6;
         color: #606266;