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

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

congxuesong 1 месяц назад
Родитель
Сommit
b8250ec966

+ 1 - 1
src/languages/modules/zh.ts

@@ -23,7 +23,7 @@ export default {
     fullScreen: "全屏",
     exitFullScreen: "退出全屏",
     personalData: "个人信息",
-    changePassword: "修改密码",
+    changePassword: "修改登录密码",
     logout: "退出登录"
   }
 };

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

@@ -1,5 +1,5 @@
 <template>
-  <el-dialog v-model="dialogVisible" title="个人信息" width="500px" draggable>
+  <el-dialog v-model="dialogVisible" title="个人信息111" width="500px" draggable>
     <span>This is userInfo</span>
     <template #footer>
       <span class="dialog-footer">

+ 145 - 0
src/views/home/components/go-enter.vue

@@ -0,0 +1,145 @@
+<template>
+  <!-- 首页:流程概览 -->
+  <div v-if="currentStep === 0" class="home-entry">
+    <h3 class="title">免费入驻店铺</h3>
+    <div class="steps-container">
+      <el-steps align-center>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">个人实名</span>
+              <span class="step-time">约3分钟</span>
+            </div>
+          </template>
+          <template #description>
+            <div class="step-desc">填写店铺经营者姓名、身份证号等</div>
+          </template>
+        </el-step>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">填写信息</span>
+              <span class="step-time">约30分钟</span>
+            </div>
+          </template>
+          <template #description>
+            <div class="step-desc">上传营业执照及填写店铺信息等</div>
+          </template>
+        </el-step>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">等待审核</span>
+              <span class="step-time">约1-3个工作日</span>
+            </div>
+          </template>
+          <template #description>
+            <div class="step-desc">平台进行资质审核</div>
+          </template>
+        </el-step>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">入驻成功</span>
+            </div>
+          </template>
+          <template #description>
+            <div class="step-desc">入驻成功后即可管理您的店铺</div>
+          </template>
+        </el-step>
+      </el-steps>
+    </div>
+    <div class="button-container">
+      <el-button type="primary" size="large" class="register-btn" @click="handleRegister"> 去入驻 </el-button>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+const props = defineProps({
+  currentStep: {
+    type: Number,
+    default: 0
+  }
+});
+
+const emit = defineEmits(["update:currentStep"]);
+
+// 处理入驻按钮
+const handleRegister = () => {
+  emit("update:currentStep", 1);
+};
+</script>
+
+<style scoped lang="scss">
+// 首页样式
+.home-entry {
+  padding: 30px 40px;
+  background: #ffffff;
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
+  .title {
+    margin: 0 0 30px;
+    font-size: 20px;
+    font-weight: 600;
+    color: #333333;
+    text-align: center;
+  }
+  .steps-container {
+    margin-bottom: 40px;
+    :deep(.el-steps) {
+      .el-step__head {
+        .el-step__icon {
+          width: 30px;
+          height: 30px;
+          font-size: 16px;
+          font-weight: 600;
+        }
+      }
+      .el-step__title {
+        .step-title-wrapper {
+          display: flex;
+          flex-direction: column;
+          gap: 8px;
+          align-items: center;
+          .step-title {
+            font-size: 16px;
+            font-weight: 600;
+            line-height: 1.5;
+            color: #303133;
+          }
+          .step-time {
+            display: inline-block;
+            padding: 4px 12px;
+            font-size: 12px;
+            color: #909399;
+            white-space: nowrap;
+            background: #f5f7fa;
+            border-radius: 12px;
+          }
+        }
+      }
+      .el-step__description {
+        .step-desc {
+          margin-top: 8px;
+          font-size: 14px;
+          line-height: 1.5;
+          color: #606266;
+        }
+      }
+    }
+  }
+  .button-container {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    .register-btn {
+      width: 200px;
+      height: 44px;
+      font-size: 16px;
+      font-weight: 500;
+      border-radius: 4px;
+    }
+  }
+}
+</style>

+ 117 - 0
src/views/home/components/go-examine.vue

@@ -0,0 +1,117 @@
+<template>
+  <div class="go-examine">
+    <div class="panel">
+      <div class="panel-header">
+        <div class="store-name">
+          {{ storeName }}
+        </div>
+        <div class="expire">店铺到期时间:{{ expireDate }}</div>
+      </div>
+      <div class="verify-row">
+        <el-input v-model="voucherCode" placeholder="请输入劵码" class="verify-input" clearable />
+        <el-button type="primary" class="verify-btn" @click="handleVerify"> 验券 </el-button>
+      </div>
+    </div>
+
+    <div class="stats">
+      <div class="stat-card">
+        <div class="stat-title">店铺钱包(元)</div>
+        <div class="stat-value">
+          {{ walletAmount.toFixed(2) }}
+        </div>
+      </div>
+      <div class="stat-card">
+        <div class="stat-title">今日订单量(单)</div>
+        <div class="stat-value">
+          {{ todayOrders }}
+        </div>
+      </div>
+      <div class="stat-card">
+        <div class="stat-title">今日收益(元)</div>
+        <div class="stat-value">
+          {{ todayRevenue }}
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref } from "vue";
+
+// 数据(可根据实际接口替换)
+const storeName = ref("时间图书馆");
+const expireDate = ref("2027/10/29");
+const voucherCode = ref("");
+
+const walletAmount = ref(0);
+const todayOrders = ref(0);
+const todayRevenue = ref(0);
+
+const handleVerify = () => {
+  // 调用验券接口
+  if (!voucherCode.value) return;
+  // TODO: 接入后端验券逻辑
+  console.log("verify voucher:", voucherCode.value);
+};
+</script>
+
+<style scoped lang="scss">
+.go-examine {
+  .panel {
+    padding: 16px;
+    margin-bottom: 16px;
+    background: #ffffff;
+    border: 1px solid #e4e7ed;
+    border-radius: 6px;
+    .panel-header {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin-bottom: 14px;
+      .store-name {
+        font-size: 16px;
+        font-weight: 600;
+        color: #303133;
+      }
+      .expire {
+        font-size: 13px;
+        color: #606266;
+      }
+    }
+    .verify-row {
+      display: flex;
+      gap: 12px;
+      align-items: center;
+      .verify-input {
+        flex: 1;
+      }
+      .verify-btn {
+        width: 96px;
+      }
+    }
+  }
+  .stats {
+    display: grid;
+    grid-template-columns: repeat(3, 1fr);
+    gap: 20px;
+    .stat-card {
+      padding: 26px 12px;
+      text-align: center;
+      background: #ffffff;
+      border: 1px solid #e4e7ed;
+      border-radius: 6px;
+      .stat-title {
+        margin-bottom: 14px;
+        font-size: 14px;
+        color: #606266;
+      }
+      .stat-value {
+        font-size: 22px;
+        font-weight: 600;
+        color: #303133;
+      }
+    }
+  }
+}
+</style>

+ 470 - 0
src/views/home/components/go-flow.vue

@@ -0,0 +1,470 @@
+<template>
+  <!-- 第一步:个人实名 -->
+  <div v-if="currentStep === 1" class="form-container">
+    <el-button class="back-btn" @click="handleBack"> 返回 </el-button>
+
+    <!-- 进度条 -->
+    <div class="progress-container">
+      <el-steps align-center>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">个人实名</span>
+              <span class="step-time">约3分钟</span>
+            </div>
+          </template>
+        </el-step>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">填写信息</span>
+              <span class="step-time">约30分钟</span>
+            </div>
+          </template>
+        </el-step>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">等待审核</span>
+              <span class="step-time">约1-3个工作日</span>
+            </div>
+          </template>
+        </el-step>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">入驻成功</span>
+            </div>
+          </template>
+        </el-step>
+      </el-steps>
+    </div>
+
+    <!-- 表单 -->
+    <div class="form-content">
+      <el-form :model="step1Form" :rules="step1Rules" ref="step1FormRef" label-width="120px">
+        <el-form-item label="姓名" prop="name">
+          <el-input v-model="step1Form.name" placeholder="请输入姓名" style="width: 400px" />
+        </el-form-item>
+        <el-form-item label="身份证号码" prop="idNumber">
+          <el-input v-model="step1Form.idNumber" placeholder="请输入身份证号码" style="width: 400px" />
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 按钮 -->
+    <div class="form-actions">
+      <el-button type="primary" size="large" @click="handleNextStep"> 下一步 </el-button>
+    </div>
+  </div>
+  <!-- 第二步:填写信息 -->
+  <div v-if="currentStep === 2" class="form-container">
+    <el-button class="back-btn" @click="handleBack"> 返回 </el-button>
+
+    <!-- 进度条 -->
+    <div class="progress-container">
+      <el-steps :active="currentStep - 1" align-center>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">个人实名</span>
+              <span class="step-time">约3分钟</span>
+            </div>
+          </template>
+        </el-step>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">填写信息</span>
+              <span class="step-time">约30分钟</span>
+            </div>
+          </template>
+        </el-step>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">等待审核</span>
+              <span class="step-time">约1-3个工作日</span>
+            </div>
+          </template>
+        </el-step>
+        <el-step>
+          <template #title>
+            <div class="step-title-wrapper">
+              <span class="step-title">入驻成功</span>
+            </div>
+          </template>
+        </el-step>
+      </el-steps>
+    </div>
+
+    <!-- 表单内容 -->
+    <div class="form-content step2-form">
+      <el-form :model="step2Form" :rules="step2Rules" ref="step2FormRef" label-width="125px">
+        <div class="form-row">
+          <!-- 左列 -->
+          <div class="form-col">
+            <el-form-item label="店铺名称" prop="storeName">
+              <el-input v-model="step2Form.storeName" placeholder="请输入店铺名称" />
+            </el-form-item>
+
+            <el-form-item label="容纳人数" prop="capacity">
+              <el-input-number v-model="step2Form.capacity" :min="1" :max="9999" />
+            </el-form-item>
+
+            <el-form-item label="门店电话" prop="storePhone">
+              <el-input v-model="step2Form.storePhone" placeholder="请输入门店电话" />
+            </el-form-item>
+
+            <el-form-item label="门店面积" prop="storeArea">
+              <el-radio-group v-model="step2Form.storeArea">
+                <el-radio label="小于20平米"> 小于20平米 </el-radio>
+                <el-radio label="20-50平米"> 20-50平米 </el-radio>
+                <el-radio label="50-100平米"> 50-100平米 </el-radio>
+                <el-radio label="100-300平米"> 100-300平米 </el-radio>
+                <el-radio label="300-500平米"> 300-500平米 </el-radio>
+                <el-radio label="500-1000平米"> 500-1000平米 </el-radio>
+                <el-radio label="大于1000平米"> 大于1000平米 </el-radio>
+              </el-radio-group>
+            </el-form-item>
+
+            <el-form-item label="所在地区" prop="location">
+              <el-select v-model="step2Form.province" placeholder="请选择" style="width: 150px; margin-right: 10px">
+                <el-option label="省份" value="province" />
+              </el-select>
+              <el-select v-model="step2Form.city" placeholder="请选择" style="width: 150px; margin-right: 10px">
+                <el-option label="城市" value="city" />
+              </el-select>
+              <el-select v-model="step2Form.district" placeholder="请选择" style="width: 150px">
+                <el-option label="区县" value="district" />
+              </el-select>
+            </el-form-item>
+
+            <el-form-item label="详细地址" prop="detailedAddress">
+              <el-input v-model="step2Form.detailedAddress" type="textarea" :rows="3" placeholder="请输入" />
+            </el-form-item>
+
+            <el-form-item label="门店简介" prop="storeIntro">
+              <el-input v-model="step2Form.storeIntro" type="textarea" :rows="3" placeholder="请输入" />
+            </el-form-item>
+
+            <el-form-item label="经营板块" prop="businessSector">
+              <el-radio-group v-model="step2Form.businessSector">
+                <el-radio label="美食"> 美食 </el-radio>
+                <el-radio label="酒店/民宿"> 酒店/民宿 </el-radio>
+                <el-radio label="KTV"> KTV </el-radio>
+                <el-radio label="洗浴汗蒸"> 洗浴汗蒸 </el-radio>
+                <el-radio label="按摩足疗"> 按摩足疗 </el-radio>
+                <el-radio label="丽人美发"> 丽人美发 </el-radio>
+                <el-radio label="运动健身"> 运动健身 </el-radio>
+                <el-radio label="医美医疗"> 医美医疗 </el-radio>
+              </el-radio-group>
+            </el-form-item>
+
+            <el-form-item label="经营种类" prop="businessType">
+              <el-checkbox-group v-model="step2Form.businessType">
+                <el-checkbox label="小吃快餐"> 小吃快餐 </el-checkbox>
+                <el-checkbox label="鱼鲜海鲜"> 鱼鲜海鲜 </el-checkbox>
+                <el-checkbox label="烧烤烤串"> 烧烤烤串 </el-checkbox>
+                <el-checkbox label="自助餐"> 自助餐 </el-checkbox>
+                <el-checkbox label="面包蛋糕甜品"> 面包蛋糕甜品 </el-checkbox>
+                <el-checkbox label="火锅"> 火锅 </el-checkbox>
+                <el-checkbox label="水果生鲜"> 水果生鲜 </el-checkbox>
+                <el-checkbox label="特色菜"> 特色菜 </el-checkbox>
+                <el-checkbox label="中餐"> 中餐 </el-checkbox>
+                <el-checkbox label="西餐"> 西餐 </el-checkbox>
+                <el-checkbox label="烤肉"> 烤肉 </el-checkbox>
+                <el-checkbox label="韩式料理"> 韩式料理 </el-checkbox>
+                <el-checkbox label="地方菜系"> 地方菜系 </el-checkbox>
+                <el-checkbox label="日式料理"> 日式料理 </el-checkbox>
+                <el-checkbox label="轻食"> 轻食 </el-checkbox>
+              </el-checkbox-group>
+            </el-form-item>
+          </div>
+
+          <!-- 右列 -->
+          <div class="form-col">
+            <el-form-item label="门店营业状态" prop="businessStatus">
+              <el-radio-group v-model="step2Form.businessStatus">
+                <el-radio label="正常营业"> 正常营业 </el-radio>
+                <el-radio label="暂停营业"> 暂停营业 </el-radio>
+                <el-radio label="筹建中"> 筹建中 </el-radio>
+              </el-radio-group>
+            </el-form-item>
+
+            <el-form-item label="经纬度查询" prop="coordinates">
+              <el-input v-model="step2Form.coordinates" placeholder="请输入经纬度" />
+            </el-form-item>
+
+            <el-form-item label="营业执照" prop="businessLicense">
+              <el-upload
+                v-model:file-list="step2Form.businessLicenseFiles"
+                action="#"
+                list-type="picture-card"
+                :limit="1"
+                :on-exceed="handleExceed"
+              >
+                <el-icon><Plus /></el-icon>
+                <template #tip>
+                  <div class="el-upload__tip">(0/1)</div>
+                </template>
+              </el-upload>
+            </el-form-item>
+
+            <el-form-item label="合同图片" prop="contractImages">
+              <el-upload
+                v-model:file-list="step2Form.contractImageFiles"
+                action="#"
+                list-type="picture-card"
+                :limit="20"
+                :on-exceed="handleExceed"
+              >
+                <el-icon><Plus /></el-icon>
+                <template #tip>
+                  <div class="el-upload__tip">(0/20)</div>
+                </template>
+              </el-upload>
+            </el-form-item>
+
+            <el-form-item label="食品经营许可证" prop="foodLicense">
+              <el-upload
+                v-model:file-list="step2Form.foodLicenseFiles"
+                action="#"
+                list-type="picture-card"
+                :limit="1"
+                :on-exceed="handleExceed"
+              >
+                <el-icon><Plus /></el-icon>
+                <template #tip>
+                  <div class="el-upload__tip">(0/1)</div>
+                </template>
+              </el-upload>
+            </el-form-item>
+          </div>
+        </div>
+      </el-form>
+    </div>
+
+    <!-- 按钮 -->
+    <div class="form-actions">
+      <el-button size="large" @click="handlePrevStep"> 上一步 </el-button>
+      <el-button type="primary" size="large" @click="handleSubmit"> 提交 </el-button>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import { ref, reactive, watch } from "vue";
+import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from "element-plus";
+import { Plus } from "@element-plus/icons-vue";
+
+const props = defineProps({
+  currentStep: {
+    type: Number,
+    value: 0
+  }
+});
+
+const emit = defineEmits(["update:currentStep"]);
+
+// 内部步骤状态,和父组件同步
+const currentStep = ref<number>(props.currentStep || 0);
+watch(
+  () => props.currentStep,
+  val => {
+    if (typeof val === "number") currentStep.value = val;
+  }
+);
+
+const setStep = (val: number) => {
+  currentStep.value = val;
+  emit("update:currentStep", val);
+};
+
+// 第一步表单
+const step1FormRef = ref<FormInstance>();
+const step1Form = reactive({
+  name: "朱丽",
+  idNumber: "231084199304282927"
+});
+
+const step1Rules: FormRules = {
+  name: [{ required: true, message: "请输入姓名", trigger: "blur" }],
+  idNumber: [
+    { 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 step2FormRef = ref<FormInstance>();
+const step2Form = reactive({
+  storeName: "",
+  capacity: 1,
+  storePhone: "",
+  storeArea: "小于20平米",
+  province: "",
+  city: "",
+  district: "",
+  detailedAddress: "",
+  storeIntro: "",
+  businessSector: "美食",
+  businessType: ["小吃快餐", "火锅"],
+  businessStatus: "正常营业",
+  coordinates: "",
+  businessLicenseFiles: [],
+  contractImageFiles: [],
+  foodLicenseFiles: []
+});
+
+const step2Rules: FormRules = {
+  storeName: [{ required: true, message: "请输入店铺名称", trigger: "blur" }],
+  storePhone: [{ required: true, message: "请输入门店电话", trigger: "blur" }],
+  storeArea: [{ required: true, message: "请选择门店面积", trigger: "change" }],
+  storeIntro: [{ required: true, message: "请输入门店简介", trigger: "blur" }],
+  businessSector: [{ required: true, message: "请选择经营板块", trigger: "change" }],
+  businessType: [{ required: true, message: "请选择经营种类", trigger: "change" }],
+  coordinates: [{ required: true, message: "请输入经纬度", trigger: "blur" }],
+  businessLicense: [{ required: true, message: "请上传营业执照", trigger: "change" }],
+  contractImages: [{ required: true, message: "请上传合同图片", trigger: "change" }],
+  foodLicense: [{ required: true, message: "请上传食品经营许可证", trigger: "change" }]
+};
+
+// 返回按钮
+const handleBack = () => {
+  if (currentStep.value === 1) {
+    setStep(0);
+  } else if (currentStep.value === 2) {
+    setStep(1);
+  }
+};
+
+// 下一步
+const handleNextStep = async () => {
+  if (!step1FormRef.value) return;
+
+  await step1FormRef.value.validate(valid => {
+    if (valid) {
+      setStep(2);
+    } else {
+      ElMessage.error("请完善表单信息");
+    }
+  });
+};
+
+// 上一步
+const handlePrevStep = () => {
+  setStep(1);
+};
+
+// 提交
+const handleSubmit = async () => {
+  if (!step2FormRef.value) return;
+
+  await step2FormRef.value.validate(valid => {
+    if (valid) {
+      ElMessageBox.confirm("确认提交入驻申请吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      })
+        .then(() => {
+          // 这里可以调用API提交数据
+          ElMessage.success("提交成功,等待审核");
+          setStep(3); // 跳转到等待审核步骤
+        })
+        .catch(() => {
+          // 取消提交
+        });
+    } else {
+      ElMessage.error("请完善表单信息");
+    }
+  });
+};
+
+// 文件上传超出限制
+const handleExceed = () => {
+  ElMessage.warning("文件数量超出限制");
+};
+</script>
+
+<style scoped lang="scss">
+// 表单页面样式
+.form-container {
+  min-height: calc(100vh - 100px);
+  padding: 30px;
+  background: #ffffff;
+  border-radius: 8px;
+  .back-btn {
+    margin-bottom: 30px;
+    color: #606266;
+    border-color: #dcdfe6;
+  }
+  .progress-container {
+    padding: 0 100px;
+    margin-bottom: 40px;
+    :deep(.el-steps) {
+      .el-step__head {
+        .el-step__icon {
+          width: 30px;
+          height: 30px;
+          font-size: 16px;
+          font-weight: 600;
+        }
+      }
+      .el-step__title {
+        .step-title-wrapper {
+          display: flex;
+          flex-direction: column;
+          gap: 8px;
+          align-items: center;
+          .step-title {
+            font-size: 16px;
+            font-weight: 600;
+            color: #303133;
+          }
+          .step-time {
+            display: inline-block;
+            padding: 4px 12px;
+            font-size: 12px;
+            color: #909399;
+            white-space: nowrap;
+            background: #f5f7fa;
+            border-radius: 12px;
+          }
+        }
+      }
+    }
+  }
+  .form-content {
+    max-width: 800px;
+    margin: 0 auto;
+    &.step2-form {
+      max-width: 1400px;
+      .form-row {
+        display: flex;
+        gap: 40px;
+        .form-col {
+          flex: 1;
+        }
+      }
+    }
+  }
+  .form-actions {
+    display: flex;
+    gap: 20px;
+    justify-content: center;
+    padding-top: 30px;
+    margin-top: 40px;
+    border-top: 1px solid #e4e7ed;
+    .el-button {
+      width: 150px;
+      height: 44px;
+      font-size: 16px;
+    }
+  }
+}
+</style>

+ 0 - 12
src/views/home/index.scss

@@ -1,12 +0,0 @@
-.home {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  width: 100%;
-  height: 100%;
-  .home-bg {
-    width: 70%;
-    max-width: 1200px;
-    margin-bottom: 20px;
-  }
-}

+ 29 - 4
src/views/home/index.vue

@@ -1,11 +1,36 @@
 <template>
-  <div class="home card">
-    <img class="home-bg" src="@/assets/images/welcome.png" alt="welcome" />
+  <div id="home">
+    <!-- 第一步  未入驻 -->
+    <go-enter :current-step="currentStep" @update:current-step="handleUpdateCurrentStep" v-if="userInfo == 0" />
+
+    <!--已入驻-->
+    <go-examine v-if="userInfo == 1" />
+
+    <!-- 第二步 -->
+    <go-flow :current-step="currentStep" @update:current-step="handleUpdateCurrentStep" />
   </div>
 </template>
 
-<script setup lang="ts" name="home"></script>
+<script setup lang="ts">
+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(1);
+
+// 当前步骤:0-首页,1-第一步,2-第二步
+const currentStep = ref(0);
+
+// 处理更新currentStep事件
+const handleUpdateCurrentStep = (step: number) => {
+  currentStep.value = step;
+};
+</script>
 
 <style scoped lang="scss">
-@import "./index";
+#home {
+  min-height: calc(100vh - 100px);
+  padding: 20px;
+}
 </style>

+ 0 - 157
src/views/home/toDoItem/components/curve.vue

@@ -1,157 +0,0 @@
-<template>
-  <div class="echarts">
-    <ECharts :option="option" />
-  </div>
-</template>
-
-<script setup lang="ts" name="cure">
-import { ECOption } from "@/components/ECharts/config";
-import ECharts from "@/components/ECharts/index.vue";
-
-const curveData = [
-  { value: 30, spotName: "掘金" },
-  { value: 90, spotName: "CSDN" },
-  { value: 10, spotName: "Gitee" },
-  { value: 70, spotName: "GitHub" },
-  { value: 20, spotName: "知乎" },
-  { value: 60, spotName: "MyBlog" },
-  { value: 55, spotName: "简书" },
-  { value: 80, spotName: "StackOverFlow" },
-  { value: 50, spotName: "博客园" }
-];
-
-const option: ECOption = {
-  tooltip: {
-    trigger: "axis",
-    backgroundColor: "transparent",
-    axisPointer: {
-      type: "none"
-    },
-    padding: 0,
-    formatter: (p: any) => {
-      let dom = `<div style="width:100%; height: 70px !important; display:flex;flex-direction: column;justify-content: space-between;padding:10px;box-sizing: border-box;
-      color:#fff; background: #6B9DFE;border-radius: 4px;font-size:14px; ">
-        <div style="display: flex; align-items: center;"> <div style="width:5px;height:5px;background:#ffffff;border-radius: 50%;margin-right:5px"></div>平台 :  ${p[0].name}</div>
-        <div style="display: flex;align-items: center;"><div style="width:5px;height:5px;background:#ffffff;border-radius: 50%;margin-right:5px"></div>数据量 :  ${p[0].value}</div>
-      </div>`;
-      return dom;
-    }
-  },
-  toolbox: {
-    show: true,
-    orient: "horizontal"
-  },
-  grid: {
-    left: "0",
-    right: "0"
-  },
-  dataZoom: [
-    {
-      show: false,
-      height: 10,
-      xAxisIndex: [0],
-      bottom: 0,
-      startValue: 0,
-      endValue: 9,
-      handleStyle: {
-        color: "#6b9dfe"
-      },
-      textStyle: {
-        color: "transparent"
-      }
-    },
-    {
-      type: "inside",
-      show: true,
-      height: 0,
-      zoomLock: true
-    }
-  ],
-  xAxis: [
-    {
-      type: "category",
-      data: curveData.map((val: any) => {
-        return {
-          value: val.spotName
-        };
-      }),
-      axisTick: {
-        show: false
-      },
-      axisLabel: {
-        margin: 20,
-        interval: 0,
-        color: "#a1a1a1",
-        fontSize: 14,
-        formatter: function (name: string) {
-          undefined;
-          return name.length > 8 ? name.slice(0, 8) + "..." : name;
-        }
-      },
-      axisLine: {
-        lineStyle: {
-          color: "#c0c0c0"
-        }
-      }
-    }
-  ],
-  yAxis: [
-    {
-      min: 0,
-      axisLine: {
-        show: false
-      },
-      axisTick: {
-        show: false
-      },
-      splitLine: {
-        show: true,
-        lineStyle: {
-          color: "#c0c0c0"
-        }
-      },
-      axisLabel: {
-        color: "#a1a1a1",
-        fontSize: 16,
-        fontWeight: 400,
-        formatter: function (value: number) {
-          if (value === 0) {
-            return value + "";
-          } else if (value >= 10000) {
-            return value / 10000 + "w";
-          }
-          return value + "";
-        }
-      }
-    }
-  ],
-  series: [
-    {
-      name: "Direct",
-      type: "bar",
-      data: curveData.map((val: any) => {
-        return {
-          value: val.value
-        };
-      }),
-      barWidth: "45px",
-      itemStyle: {
-        color: "#C5D8FF",
-        borderRadius: [12, 12, 0, 0]
-      },
-      emphasis: {
-        itemStyle: {
-          color: "#6B9DFE"
-        }
-      }
-    }
-  ]
-};
-</script>
-
-<style lang="scss" scoped>
-.echarts {
-  width: 100%;
-  height: 100%;
-}
-</style>

+ 0 - 131
src/views/home/toDoItem/components/pie.vue

@@ -1,131 +0,0 @@
-<template>
-  <div class="echarts">
-    <ECharts :option="option" />
-  </div>
-</template>
-
-<script setup lang="ts" name="pie">
-import { ECOption } from "@/components/ECharts/config";
-import ECharts from "@/components/ECharts/index.vue";
-
-const pieData = [
-  { value: 5000, name: "Gitee 访问量" },
-  { value: 5000, name: "GitHub 访问量" }
-];
-
-const option: ECOption = {
-  title: {
-    text: "Gitee / GitHub",
-    subtext: "访问占比",
-    left: "56%",
-    top: "45%",
-    textAlign: "center",
-    textStyle: {
-      fontSize: 18,
-      color: "#767676"
-    },
-    subtextStyle: {
-      fontSize: 15,
-      color: "#a1a1a1"
-    }
-  },
-  tooltip: {
-    trigger: "item"
-  },
-  legend: {
-    top: "4%",
-    left: "2%",
-    orient: "vertical",
-    icon: "circle", //图例形状
-    align: "left",
-    itemGap: 20,
-    textStyle: {
-      fontSize: 13,
-      color: "#a1a1a1",
-      fontWeight: 500
-    },
-    formatter: function (name: string) {
-      let dataCopy = "";
-      for (let i = 0; i < pieData.length; i++) {
-        if (pieData[i].name == name && pieData[i].value >= 10000) {
-          dataCopy = (pieData[i].value / 10000).toFixed(2);
-          return name + "      " + dataCopy + "w";
-        } else if (pieData[i].name == name) {
-          dataCopy = pieData[i].value + "";
-          return name + "      " + dataCopy;
-        }
-      }
-      return "";
-    }
-  },
-  series: [
-    {
-      type: "pie",
-      radius: ["70%", "40%"],
-      center: ["57%", "52%"],
-      silent: true,
-      clockwise: true,
-      startAngle: 150,
-      data: pieData,
-      labelLine: {
-        length: 80,
-        length2: 30,
-        lineStyle: {
-          width: 1
-        }
-      },
-      label: {
-        position: "outside",
-        show: true,
-        formatter: "{d}%",
-        fontWeight: 400,
-        fontSize: 19,
-        color: "#a1a1a1"
-      },
-      color: [
-        {
-          type: "linear",
-          x: 0,
-          y: 0,
-          x2: 0.5,
-          y2: 1,
-          colorStops: [
-            {
-              offset: 0,
-              color: "#feb791" // 0% 处的颜色
-            },
-            {
-              offset: 1,
-              color: "#fe8b4c" // 100% 处的颜色
-            }
-          ]
-        },
-        {
-          type: "linear",
-          x: 0,
-          y: 0,
-          x2: 1,
-          y2: 0.5,
-          colorStops: [
-            {
-              offset: 0,
-              color: "#b898fd" // 0% 处的颜色
-            },
-            {
-              offset: 1,
-              color: "#8347fd" // 100% 处的颜色
-            }
-          ]
-        }
-      ]
-    }
-  ]
-};
-</script>
-
-<style lang="scss" scoped>
-.echarts {
-  width: 100%;
-  height: 100%;
-}
-</style>

BIN
src/views/home/toDoItem/images/1-bg.png


BIN
src/views/home/toDoItem/images/2-bg.png


BIN
src/views/home/toDoItem/images/3-bg.png


BIN
src/views/home/toDoItem/images/4-bg.png


BIN
src/views/home/toDoItem/images/add_person.png


BIN
src/views/home/toDoItem/images/add_team.png


BIN
src/views/home/toDoItem/images/book-bg.png


BIN
src/views/home/toDoItem/images/book-sum.png


BIN
src/views/home/toDoItem/images/book_sum.png


BIN
src/views/home/toDoItem/images/today.png


+ 0 - 154
src/views/home/toDoItem/index.scss

@@ -1,154 +0,0 @@
-.dataVisualize-box {
-  .top-box {
-    box-sizing: border-box;
-    padding: 25px 40px 0;
-    margin-bottom: 10px;
-    .top-title {
-      margin-bottom: 10px;
-      font-family: DIN;
-      font-size: 18px;
-      font-weight: bold;
-    }
-    .top-content {
-      margin-top: 10px;
-      .item-left {
-        box-sizing: border-box;
-        height: 100%;
-        padding: 40px 0 30px 30px;
-        overflow: hidden;
-        color: #ffffff;
-        background: url("./images/book-bg.png");
-        background-position: 50%;
-        background-size: cover;
-        border-radius: 20px;
-        .left-title {
-          font-family: DIN;
-          font-size: 20px;
-        }
-        .img-box {
-          display: flex;
-          align-items: center;
-          justify-content: center;
-          width: 90px;
-          height: 90px;
-          margin: 40px 0 20px;
-          background-color: #ffffff;
-          border-radius: 20px;
-          box-shadow: 0 10px 20px rgb(0 0 0 / 14%);
-          img {
-            width: 60px;
-            height: 65px;
-          }
-        }
-        .left-number {
-          overflow: hidden;
-          font-family: DIN;
-          font-size: 62px;
-        }
-      }
-      .item-center {
-        display: flex;
-        place-content: center space-around;
-        height: 100%;
-        .traffic-box {
-          box-sizing: border-box;
-          display: flex;
-          flex-direction: column;
-          width: 47%;
-          height: 48%;
-          padding: 25px;
-          margin: 10px 20px;
-          border-radius: 30px;
-          .traffic-img {
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            width: 70px;
-            height: 70px;
-            margin-bottom: 10px;
-            background-color: #ffffff;
-            border-radius: 19px;
-          }
-        }
-        img {
-          width: 33px;
-          height: 33px;
-        }
-        .item-value {
-          margin-bottom: 4px;
-          font-family: DIN;
-          font-size: 28px;
-          font-weight: bold;
-          color: #1a1a37;
-        }
-        .traffic-name {
-          overflow: hidden;
-          font-family: DIN;
-          font-size: 15px;
-          color: #1a1a37;
-          white-space: nowrap;
-        }
-        .gitee-traffic {
-          background: url("./images/1-bg.png");
-          background-color: #e8faea;
-          background-size: 100% 100%;
-        }
-        .gitHub-traffic {
-          background: url("./images/2-bg.png");
-          background-color: #e7e1fb;
-          background-size: 100% 100%;
-        }
-        .today-traffic {
-          background: url("./images/3-bg.png");
-          background-color: #fdf3e9;
-          background-size: 100% 100%;
-        }
-        .yesterday-traffic {
-          background: url("./images/4-bg.png");
-          background-color: #f0f5fb;
-          background-size: 100% 100%;
-        }
-      }
-      .item-right {
-        box-sizing: border-box;
-        display: flex;
-        flex-direction: column;
-        width: 100%;
-        height: 430px;
-        border: 1px solid var(--el-border-color);
-        border-radius: 25px;
-        .echarts-title {
-          padding: 15px 20px;
-          font-family: DIN;
-          font-size: 18px;
-          font-weight: bold;
-          border-bottom: 1px solid var(--el-border-color);
-        }
-        .book-echarts {
-          flex: 1;
-          width: 100%;
-        }
-      }
-    }
-  }
-  .bottom-box {
-    position: relative;
-    padding: 20px 0 0;
-    .bottom-title {
-      position: absolute;
-      top: 75px;
-      left: 50px;
-      font-family: DIN;
-      font-size: 18px;
-      font-weight: bold;
-    }
-    .bottom-tabs {
-      padding: 0 50px;
-    }
-    .curve-echarts {
-      box-sizing: border-box;
-      height: 400px;
-      padding: 0 50px;
-    }
-  }
-}

+ 0 - 442
src/views/home/toDoItem/index.vue

@@ -1,442 +0,0 @@
-<template>
-  <div class="dataVisualize-box">
-    <div class="card top-box">
-      <div class="top-title">工作台</div>
-      <div class="top-content">
-        <div class="item-center">
-          <div class="gitee-traffic traffic-box">
-            <div class="traffic-img">
-              <img src="./images/add_person.png" alt="" />
-            </div>
-            <span class="item-value">{{ auditSums["店铺入驻"] || 0 }}</span>
-            <span class="traffic-name sle">待审核商铺</span>
-          </div>
-          <div class="today-traffic traffic-box">
-            <div class="traffic-img">
-              <img src="./images/today.png" alt="" />
-            </div>
-            <span class="item-value">{{ auditSums["商家申诉"] || 0 }}</span>
-            <span class="traffic-name sle">待审核商家申诉</span>
-          </div>
-          <div class="yesterday-traffic traffic-box">
-            <div class="traffic-img">
-              <img src="./images/book_sum.png" alt="" />
-            </div>
-            <span class="item-value">{{ auditSums["套餐"] || 0 }}</span>
-            <span class="traffic-name sle">待审核套餐</span>
-          </div>
-          <div class="gitHub-traffic traffic-box">
-            <div class="traffic-img">
-              <img src="./images/add_team.png" alt="" />
-            </div>
-            <span class="item-value">{{ auditSums["代金券"] || 0 }}</span>
-            <span class="traffic-name sle">代金券审核</span>
-          </div>
-          <div class="yesterday-traffic traffic-box">
-            <div class="traffic-img">
-              <img src="./images/book_sum.png" alt="" />
-            </div>
-            <span class="item-value">{{ auditSums["经营许可证"] || 0 }}</span>
-            <span class="traffic-name sle">待食品许可证审批</span>
-          </div>
-        </div>
-      </div>
-    </div>
-
-    <div class="card top-box">
-      <el-tabs v-model="tabActive" class="demo-tabs">
-        <el-tab-pane v-for="item in tab" :key="item.name" :label="item.label" :name="item.name" />
-      </el-tabs>
-      <div class="card top-box">
-        <el-table :data="tableData" height="250">
-          <el-table-column type="index" label="序号" width="80" />
-          <el-table-column prop="content" label="内容" />
-          <el-table-column prop="type" label="类型" />
-          <el-table-column prop="createdTime" label="提交时间" />
-          <el-table-column prop="status" label="状态" />
-          <el-table-column label="操作" fixed="right" width="120">
-            <template #default="scope">
-              <el-button type="primary" link @click="handleAudit(scope.row)"> 通过 </el-button>
-              <el-button type="primary" link @click="handleAudit2(scope.row)"> 拒绝 </el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-      </div>
-      <!-- 分页组件 -->
-      <div class="pagination-container">
-        <el-pagination
-          v-if="total > 0"
-          :current-page="currentPage"
-          :page-size="pageSize"
-          :total="total"
-          :page-sizes="[5, 10, 15, 20]"
-          @current-change="handlePageChange"
-          @size-change="handleSizeChange"
-          background
-          layout="total, sizes, prev, pager, next, jumper"
-        />
-      </div>
-    </div>
-    <!-- 拒接弹出框 -->
-    <el-dialog v-model="dialogFormVisible" title="审核拒接" width="500">
-      <el-form :model="form">
-        <el-form-item>
-          <el-input v-model="form.reason" autocomplete="off" style="width: 500px" type="textarea" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button @click="dialogFormVisible = false"> 取消 </el-button>
-          <el-button type="primary" @click="handleOk"> 确定 </el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup lang="tsx" name="useProTable">
-import { ref, reactive, onMounted, onActivated, watch } from "vue";
-import { useRoute, useRouter } from "vue-router";
-import { Audit } from "@/api/interface";
-import { ElMessage, ElMessageBox } from "element-plus";
-import { getAuditList, getAuditSum } from "@/api/modules/audit";
-import { approveStoreInfo } from "@/api/modules/groupPackageManagement";
-import { consentComplaintFun, rejectClaimFun } from "@/api/modules/storeCommentAppeal";
-import { updateStatus } from "@/api/modules/groupPackage";
-import { changeStatus } from "@/api/modules/groupPackage";
-import { updatefoodLicenceImageStatus } from "@/api/modules/groupPackageManagement";
-
-const dialogFormVisible = ref(false);
-const router = useRouter();
-const tabActive = ref(1);
-const form = ref({
-  reason: ""
-});
-// 分页相关响应式数据
-const currentPage = ref(1);
-const pageSize = ref(10);
-const total = ref(0);
-
-const route = useRoute();
-
-const tab = [
-  { label: "商铺入驻", name: 1, type: "1" },
-  { label: "审核商家申诉", name: 4, type: "3" },
-  { label: "审核套餐", name: 5, type: "4" },
-  { label: "代金券审核", name: 7, type: "6" },
-
-  // { label: "审核活动", name: 6, type: "5" }
-  { label: "食品许可证审批", name: 8, type: "7" }
-];
-
-const tableData = ref<any[]>([]);
-const auditSums = ref<{
-  [key: string]: number;
-}>({});
-
-// 封装参数处理函数
-const processParams = (params: any) => {
-  let newParams = JSON.parse(JSON.stringify(params));
-  delete newParams.createTime;
-  delete newParams.pageNum;
-  delete newParams.pageSize;
-  newParams.status = newParams.status || "";
-  newParams.type = newParams.type || "";
-  newParams.page = newParams.page || 1;
-  newParams.size = newParams.size || 10;
-  newParams.classBigType = newParams.classBigType || "";
-  newParams.classTeacher = newParams.classTeacher || "";
-  newParams.className = newParams.className || "";
-  return newParams;
-};
-
-const getTableList = async (params: any) => {
-  const newParams = processParams(params);
-  try {
-    const res = await getAuditList(newParams);
-    return res;
-  } catch (error) {
-    console.error("getTableList - 获取审核列表失败:", error);
-    return { records: [], total: 0 };
-  }
-};
-
-// 统一数据加载方法
-const loadData = async () => {
-  try {
-    // 获取当前标签页的类型
-    const currentTab = tab.find(item => item.name === tabActive.value);
-    const type = currentTab ? currentTab.type : "1";
-
-    const res = await getTableList({
-      page: currentPage.value,
-      size: pageSize.value,
-      type: type
-    });
-
-    // 检查响应数据格式
-    if (res.data && res.data.current && res.data.size && res.data.total) {
-      // 更新分页数据
-      currentPage.value = res.data.current;
-      pageSize.value = res.data.size;
-      total.value = res.data.total;
-
-      // 更新表格数据
-      tableData.value = res.data.records || [];
-    } else {
-      console.error("loadData - 响应数据格式不正确:", res);
-      tableData.value = [];
-      total.value = 0;
-    }
-  } catch (error) {
-    console.error("loadData - 获取审核列表失败:", error);
-    tableData.value = [];
-    total.value = 0;
-  }
-};
-
-// 页码变化处理
-const handlePageChange = (newPage: number) => {
-  currentPage.value = newPage;
-  loadData();
-};
-
-// 每页数量变化处理
-const handleSizeChange = (newSize: number) => {
-  pageSize.value = newSize;
-  currentPage.value = 1;
-  loadData();
-};
-
-const getTobList = async () => {
-  try {
-    // 初始化所有类型为0
-    auditSums.value = {
-      店铺入驻: 0,
-      商家申诉: 0,
-      套餐: 0,
-      代金券: 0,
-      食品许可证审批: 0
-    };
-    const resp = await getAuditSum({});
-    // 检查响应数据格式
-    if (resp.code === 200 && resp.data) {
-      resp.data.forEach(item => {
-        const type = item.type;
-        const typeSum = parseInt(item.typeSum, 10);
-        auditSums.value[type] = typeSum;
-      });
-    } else {
-      console.error("getTobList - 响应数据格式不正确:", resp);
-      ElMessage.error("获取审核统计数据失败,响应数据格式不正确");
-    }
-    return resp;
-  } catch (error) {}
-};
-
-// 审核通过操作
-const handleAudit = (row: any) => {
-  ElMessageBox.confirm("确定要通过该审核吗?", "审核确认", {
-    confirmButtonText: "确定",
-    cancelButtonText: "取消",
-    type: "warning"
-  })
-    .then(() => {
-      // 同意
-      // 商铺入驻
-      if (tabActive.value == 1) {
-        approveStoreInfo({
-          id: row.storeInfoId,
-          approvalStatus: 1
-        }).then(res => {
-          if (res.code === 200) {
-            ElMessage.success("审核通过成功");
-            loadData();
-            getTobList();
-          }
-        });
-      } else if (tabActive.value == 4) {
-        //  审核商家申诉
-        consentComplaintFun({
-          id: row.storeCommentAppealId,
-          appealStatus: "2"
-        }).then(res => {
-          if (res.code === 200) {
-            ElMessage.success("审核通过成功");
-            loadData();
-            getTobList();
-          }
-        });
-      } else if (tabActive.value == 5) {
-        // 审核套餐
-        updateStatus({
-          id: row.lifeGroupPackageId,
-          status: 2,
-          approvalComments: ""
-        }).then(res => {
-          if (res.code === 200) {
-            ElMessage.success("审核通过成功");
-            loadData();
-            getTobList();
-          }
-        });
-      } else if (tabActive.value == 7) {
-        // 代金券审核
-        changeStatus({
-          id: row.couponId,
-          status: 5,
-          comment: "",
-          type: 1
-        }).then(res => {
-          if (res.code === 200) {
-            ElMessage.success("审核通过成功");
-            loadData();
-            getTobList();
-          }
-        });
-      } else if (tabActive.value == 8) {
-        // 许可证审核
-        updatefoodLicenceImageStatus({
-          id: row.storeInfoId,
-          foodLicenceStatus: 1,
-          foodLicenceReason: ""
-        }).then(res => {
-          if (res.code === 200) {
-            ElMessage.success("审核通过成功");
-            loadData();
-            getTobList();
-          }
-        });
-      }
-    })
-    .catch(() => {
-      ElMessage.info("已取消操作");
-    });
-};
-const rowValue = ref({});
-// 驳回操作
-const handleOk = () => {
-  if (form.value.reason) {
-    dialogFormVisible.value = false;
-    if (tabActive.value == 1) {
-      approveStoreInfo({
-        id: rowValue.value.storeInfoId,
-        approvalStatus: 2,
-        reason: form.value.reason
-      }).then(res => {
-        if (res.code === 200) {
-          handleCs();
-          loadData();
-          getTobList();
-        }
-      });
-    } else if (tabActive.value == 4) {
-      //  审核商家申诉
-      rejectClaimFun({
-        id: rowValue.value.storeCommentAppealId,
-        appealStatus: "1",
-        logRemark: form.value.reason
-      }).then(res => {
-        if (res.code === 200) {
-          handleCs();
-          loadData();
-          getTobList();
-        }
-      });
-    } else if (tabActive.value == 5) {
-      // 审核套餐
-      updateStatus({
-        id: rowValue.value.lifeGroupPackageId,
-        status: 3,
-        approvalComments: form.value.reason
-      }).then(res => {
-        if (res.code === 200) {
-          handleCs();
-          loadData();
-          getTobList();
-        }
-      });
-    } else if (tabActive.value == 7) {
-      // 代金券审核
-      changeStatus({
-        id: rowValue.value.couponId,
-        status: 3,
-        comment: form.value.reason,
-        type: 1
-      }).then(res => {
-        if (res.code === 200) {
-          handleCs();
-          loadData();
-          getTobList();
-        }
-      });
-    } else if (tabActive.value == 8) {
-      // 许可证审核
-      updatefoodLicenceImageStatus({
-        id: rowValue.value.storeInfoId,
-        foodLicenceStatus: 3,
-        foodLicenceReason: form.value.reason
-      }).then(res => {
-        if (res.code === 200) {
-          ElMessage.success("审核通过成功");
-          loadData();
-          getTobList();
-        }
-      });
-    }
-  } else {
-    ElMessage.error("请填写审核拒绝原因!");
-  }
-};
-const handleCs = () => {
-  ElMessage.success("审核拒接成功!");
-  form.value.reason = "";
-};
-// 审核拒绝操作
-const handleAudit2 = (row: any) => {
-  rowValue.value = row;
-  dialogFormVisible.value = true;
-};
-
-// 监听 tabActive 变化
-watch(tabActive, async (newVal, oldVal) => {
-  if (newVal !== oldVal) {
-    // 重置分页状态
-    currentPage.value = 1;
-    total.value = 0;
-
-    // 加载新数据
-    getTobList();
-    await loadData();
-  }
-});
-
-// 页面加载时触发查询
-onMounted(async () => {
-  await loadData();
-  await getTobList();
-});
-
-// 从其他页面返回时触发查询
-onActivated(async () => {
-  await loadData();
-});
-
-// 表格配置项
-const columns = reactive<ColumnProps<Audit.ResAuditList>[]>([
-  { prop: "index", label: "序号", type: "index", width: 100 },
-  { prop: "content", label: "内容", search: { el: "input" } },
-  { prop: "type", label: "类型" },
-  { prop: "createdTime", label: "提交时间" },
-  { prop: "status", label: "状态" },
-  { prop: "operation", label: "操作", fixed: "right", width: 120 }
-]);
-</script>
-<style scoped lang="scss">
-@import "./index";
-.pagination-container {
-  display: flex;
-  justify-content: flex-end;
-  padding: 20px;
-}
-</style>

+ 111 - 0
src/views/home/userInfo.vue

@@ -0,0 +1,111 @@
+<template>
+  <div class="user-info-page">
+    <div class="top-bar">
+      <el-button size="small" @click="handleBack"> 返回 </el-button>
+      <div class="title">个人信息</div>
+    </div>
+
+    <div class="form-wrap">
+      <el-form :model="form" :rules="rules" ref="formRef" label-width="72px">
+        <el-form-item label="头像">
+          <el-upload
+            class="avatar-uploader"
+            action="#"
+            list-type="picture-card"
+            :limit="1"
+            :on-exceed="onExceed"
+            v-model:file-list="form.avatarList"
+          >
+            <el-icon><Plus /></el-icon>
+          </el-upload>
+        </el-form-item>
+
+        <el-form-item label="昵称" prop="nickname">
+          <el-input v-model="form.nickname" placeholder="请输入昵称" />
+        </el-form-item>
+
+        <el-form-item label="简介" prop="intro">
+          <el-input v-model="form.intro" type="textarea" :rows="6" placeholder="请输入简介" />
+        </el-form-item>
+
+        <div class="actions">
+          <el-button type="primary" class="save-btn" @click="handleSave"> 保存 </el-button>
+        </div>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive } from "vue";
+import { ElMessage, type FormInstance, type FormRules } from "element-plus";
+import { Plus } from "@element-plus/icons-vue";
+
+const formRef = ref<FormInstance>();
+const form = reactive({
+  avatarList: [] as any[],
+  nickname: "重庆老火锅",
+  intro: "这——家优秀的火锅店"
+});
+
+const rules: FormRules = {
+  nickname: [{ required: true, message: "请输入昵称", trigger: "blur" }],
+  intro: [{ required: true, message: "请输入简介", trigger: "blur" }]
+};
+
+const onExceed = () => {
+  ElMessage.warning("仅允许上传一张头像");
+};
+
+const handleBack = () => {
+  history.back();
+};
+
+const handleSave = async () => {
+  if (!formRef.value) return;
+  await formRef.value.validate(valid => {
+    if (!valid) return;
+    // TODO: 接口保存
+    ElMessage.success("保存成功");
+  });
+};
+</script>
+
+<style scoped lang="scss">
+.user-info-page {
+  padding: 16px;
+  .top-bar {
+    display: flex;
+    gap: 12px;
+    align-items: center;
+    .title {
+      flex: 1;
+      margin-right: 48px; // 平衡左侧返回按钮的宽度
+      font-size: 18px;
+      font-weight: 600;
+      color: #303133;
+      text-align: center;
+    }
+  }
+  .form-wrap {
+    max-width: 640px;
+    margin-top: 16px;
+    .avatar-uploader {
+      :deep(.el-upload--picture-card) {
+        width: 96px;
+        height: 96px;
+      }
+    }
+    :deep(.el-form-item__label) {
+      color: #303133;
+    }
+    .actions {
+      margin-top: 24px;
+      text-align: center;
+      .save-btn {
+        width: 140px;
+      }
+    }
+  }
+}
+</style>