醉梦人间三千年 6 months ago
parent
commit
8f1a775f6b

+ 3 - 3
.env.dev

@@ -4,7 +4,7 @@ NODE_ENV=production
 VITE_DEV=true
 
 # 请求路径
-VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
+VITE_BASE_URL='https://api.xiaoding.niusenyun.com'
 
 # 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
 VITE_UPLOAD_TYPE=server
@@ -12,7 +12,7 @@ VITE_UPLOAD_TYPE=server
 VITE_UPLOAD_URL='http://api-dashboard.yudao.iocoder.cn/admin-api/infra/file/upload'
 
 # 接口地址
-VITE_API_URL=/admin-api
+VITE_API_URL=
 
 # 是否删除debugger
 VITE_DROP_DEBUGGER=false
@@ -33,4 +33,4 @@ VITE_OUT_DIR=dist
 VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
 
 # 验证码的开关
-VITE_APP_CAPTCHA_ENABLE=true
+VITE_APP_CAPTCHA_ENABLE=false

+ 1 - 1
.env.local

@@ -9,7 +9,7 @@ VITE_BASE_URL='http://127.0.0.1:8000'
 # 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
 VITE_UPLOAD_TYPE=server
 # 上传路径
-VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
+VITE_UPLOAD_URL='http://127.0.0.1:8000/infra/file/upload'
 
 # 接口地址
 VITE_API_URL=

+ 6 - 2
.env.prod

@@ -4,7 +4,7 @@ NODE_ENV=production
 VITE_DEV=false
 
 # 请求路径
-VITE_BASE_URL='http://localhost:48080'
+VITE_BASE_URL='https://api.xiaoding.niusenyun.com'
 
 # 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
 VITE_UPLOAD_TYPE=server
@@ -12,7 +12,7 @@ VITE_UPLOAD_TYPE=server
 VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
 
 # 接口地址
-VITE_API_URL=/admin-api
+VITE_API_URL=
 
 # 是否删除debugger
 VITE_DROP_DEBUGGER=true
@@ -31,3 +31,7 @@ VITE_OUT_DIR=dist-prod
 
 # 商城H5会员端域名
 VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
+
+
+# 验证码的开关
+VITE_APP_CAPTCHA_ENABLE=false

+ 2 - 1
package.json

@@ -47,9 +47,10 @@
     "driver.js": "^1.3.1",
     "echarts": "^5.5.0",
     "echarts-wordcloud": "^2.1.0",
-    "element-plus": "2.7.0",
+    "element-plus": "^2.8.3",
     "fast-xml-parser": "^4.3.2",
     "highlight.js": "^11.9.0",
+    "iconify-icon": "^2.1.0",
     "jsencrypt": "^3.3.2",
     "lodash-es": "^4.17.21",
     "markdown-it": "^14.1.0",

+ 15 - 5
pnpm-lock.yaml

@@ -75,14 +75,17 @@ importers:
         specifier: ^2.1.0
         version: 2.1.0(echarts@5.5.1)
       element-plus:
-        specifier: 2.7.0
-        version: 2.7.0(vue@3.4.21(typescript@5.3.3))
+        specifier: ^2.8.3
+        version: 2.8.3(vue@3.4.21(typescript@5.3.3))
       fast-xml-parser:
         specifier: ^4.3.2
         version: 4.4.1
       highlight.js:
         specifier: ^11.9.0
         version: 11.10.0
+      iconify-icon:
+        specifier: ^2.1.0
+        version: 2.1.0
       jsencrypt:
         specifier: ^3.3.2
         version: 3.3.2
@@ -3046,8 +3049,8 @@ packages:
   electron-to-chromium@1.5.11:
     resolution: {integrity: sha512-R1CccCDYqndR25CaXFd6hp/u9RaaMcftMkphmvuepXr5b1vfLkRml6aWVeBhXJ7rbevHkKEMJtz8XqPf7ffmew==}
 
-  element-plus@2.7.0:
-    resolution: {integrity: sha512-WAiaFLavuWFxof9qwkC27jvkh9nRcNnB506g1vvJSiVaVqjCBWUFCIyJKeN11M1qcv2cS5VV5PfSLjTIkrw87A==}
+  element-plus@2.8.3:
+    resolution: {integrity: sha512-BXQOyDf0s7JHyNEV8iaO+iaOzTZPsBXVKMzMI967vLCodUBDLrtiY5vglAn1YEebQcUOEUMhGcttTpIvEkcBjQ==}
     peerDependencies:
       vue: ^3.2.0
 
@@ -3576,6 +3579,9 @@ packages:
   i18next@20.6.1:
     resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==}
 
+  iconify-icon@2.1.0:
+    resolution: {integrity: sha512-lto4XU3bwTQnb+D/CsJ4dWAo0aDe+uPMxEtxyOodw9l7R9QnJUUab3GCehlw2M8mDHdeUu/ufx8PvRQiJphhXg==}
+
   iconv-lite@0.6.3:
     resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
     engines: {node: '>=0.10.0'}
@@ -8828,7 +8834,7 @@ snapshots:
 
   electron-to-chromium@1.5.11: {}
 
-  element-plus@2.7.0(vue@3.4.21(typescript@5.3.3)):
+  element-plus@2.8.3(vue@3.4.21(typescript@5.3.3)):
     dependencies:
       '@ctrl/tinycolor': 3.6.1
       '@element-plus/icons-vue': 2.3.1(vue@3.4.21(typescript@5.3.3))
@@ -9499,6 +9505,10 @@ snapshots:
     dependencies:
       '@babel/runtime': 7.25.0
 
+  iconify-icon@2.1.0:
+    dependencies:
+      '@iconify/types': 2.0.0
+
   iconv-lite@0.6.3:
     dependencies:
       safer-buffer: 2.1.2

+ 56 - 0
src/api/coach/user/index.ts

@@ -0,0 +1,56 @@
+import request from '@/config/axios'
+import {UnwrapRef} from "vue";
+
+export interface User {
+  id: number
+  avatar: string | undefined
+  birthday: number | undefined
+  createTime: number | undefined
+  loginDate: number | undefined
+  loginIp: string
+  mark: string
+  mobile: string
+  name: string | undefined
+  nickname: string | undefined
+  registerIp: string
+  sex: number
+  status: number
+  areaId: number | undefined
+  areaName: string | undefined
+  levelName: string | null
+  point: number | undefined | null
+  totalPoint: number | undefined | null
+  experience: number | null | undefined
+}
+
+// 查询会员用户列表
+export const getUserPage = async (params) => {
+  return await request.get({url: `/coach/user`, params})
+}
+
+// 查询技工申请详情
+export const getUserApply = async (id: number) => {
+  return await request.get({url: `/coach/user/apply/` + id})
+}
+
+// 授权审核
+export const updateUserApply = async (data: UnwrapRef<{ id: undefined; verifyText: undefined; status: number }>, id: UnwrapRef<undefined>) => {
+  return await request.put({url: `/coach/user/apply/${id}`, data})
+}
+
+// 重新授权
+export const updateUserReapply = async (data: UnwrapRef<{ id: undefined; verifyText: undefined; status: number }>, id: UnwrapRef<undefined>) => {
+  return await request.put({url: `/coach/user/reapply/${id}`, data})
+}
+
+// 认证审核
+export const updateUserAuth = async (data: UnwrapRef<{ id: undefined; authText: undefined; authStatus: number }>, id: UnwrapRef<undefined>) => {
+  return await request.put({url: `/coach/user/auth/${id}`, data})
+}
+
+// 查询技工认证详情
+export const getUserAuth = async (id: number) => {
+  return await request.get({url: `/coach/user/auth/` + id})
+}
+
+

+ 2 - 2
src/api/service/category/index.ts

@@ -10,8 +10,8 @@ export interface Category {
 }
 
 // 查询菜单(精简)列表
-export const getSimpleMenusList = () => {
-  return request.get({ url: '/system/menu/simple-list' })
+export const getSimpleCategoryList = () => {
+  return request.get({ url: '/service/category/simple' })
 }
 
 // 查询菜单列表

+ 3 - 0
src/utils/dict.ts

@@ -112,6 +112,9 @@ export enum DICT_TYPE {
   COMMON_STATUS = 'common_status',
   TERMINAL = 'terminal', // 终端
   DATE_INTERVAL = 'date_interval', // 数据间隔
+  // ========== COACH 模块 ==========
+  COACH_AUTH_STATUS = 'coach_auth_status',
+  COACH_APPLY_STATUS = 'coach_apply_status',
 
   // ========== SYSTEM 模块 ==========
   SYSTEM_USER_SEX = 'system_user_sex',

+ 285 - 0
src/views/coach/user/UserApplyUpdateForm.vue

@@ -0,0 +1,285 @@
+<template>
+  <Dialog :title="title" v-model="dialogVisible" width="600">
+
+    <el-descriptions direction="vertical" :column="3" border>
+      <el-descriptions-item
+          :rowspan="3"
+          :width="140"
+          label="头像"
+          align="center"
+      >
+        <el-image
+            style="width: 100px; height: 100px"
+            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+        />
+      </el-descriptions-item>
+      <el-descriptions-item label="姓名">{{ formData.name }}</el-descriptions-item>
+      <el-descriptions-item label="手机">{{ formData.mobile }}</el-descriptions-item>
+      <el-descriptions-item label="昵称"> {{ formData.nickname }}</el-descriptions-item>
+      <el-descriptions-item label="性别">
+        <el-tag size="small" v-if="formData.workTime === 0">男</el-tag>
+        <el-tag size="small" type="danger" v-if="formData.workTime === 1">女</el-tag>
+      </el-descriptions-item>
+      <el-descriptions-item label="从业年份">
+        {{ formData.workTime }}
+      </el-descriptions-item>
+      <el-descriptions-item label="意向工作城市">
+        {{ formData.city }}
+      </el-descriptions-item>
+      <el-descriptions-item label="出生日期" v-if="formData.birthday || formData.idCode">
+        {{ formData.birthday }}
+      </el-descriptions-item>
+      <el-descriptions-item label="身份证号码" :span="2" v-if="formData.birthday || formData.idCode">
+        {{ formData.idCode }}
+      </el-descriptions-item>
+      <el-descriptions-item
+          label="身份证活体认证图片"
+          align="center"
+          :span="3"
+          v-if="formData.idCard"
+      >
+        <el-image
+            style="width: 100px; height: 100px"
+            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+        />
+        <el-image
+            style="width: 100px; height: 100px"
+            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+        />
+        <el-image
+            style="width: 100px; height: 100px"
+            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+        />
+      </el-descriptions-item>
+      <el-descriptions-item
+          label="工作照"
+          align="center"
+          v-if="formData.workImg || formData.license"
+      >
+        <el-image
+            style="width: 100px; height: 100px"
+            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+        />
+      </el-descriptions-item>
+      <el-descriptions-item
+          :span="2"
+          label="证书照"
+          align="center"
+          v-if="formData.workImg || formData.license"
+      >
+        <el-image
+            style="width: 100px; height: 100px"
+            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+        />
+        <el-image
+            style="width: 100px; height: 100px"
+            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+        />
+        <el-image
+            style="width: 100px; height: 100px"
+            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+        />
+      </el-descriptions-item>
+      <el-descriptions-item
+          :span="3"
+          label="生活照"
+          align="center"
+          v-if="formData.selfImg"
+      >
+        <el-image
+            style="width: 100px; height: 100px"
+            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+        />
+        <el-image
+            style="width: 100px; height: 100px"
+            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+        />
+        <el-image
+            style="width: 100px; height: 100px"
+            src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+        />
+      </el-descriptions-item>
+
+      <el-descriptions-item label="所在地址" :span="3" v-if="formData.address">
+        {{ formData.address }}
+      </el-descriptions-item>
+      <el-descriptions-item label="简介" :span="3" v-if="formData.brief">
+        {{ formData.brief }}
+      </el-descriptions-item>
+    </el-descriptions>
+
+    <el-form
+        ref="formRef"
+        :model="verifyFormData"
+        :rules="formRules"
+        label-width="100px"
+        v-loading="formLoading"
+    >
+
+
+      <el-form-item label="身份证号" v-if="formData.idCode">
+        <el-input
+            v-model="formData.idCode"
+            placeholder="请输入用户昵称"
+            class="!w-240px"
+            disabled
+        />
+      </el-form-item>
+      <el-form-item label="身份证正反面" v-if="formData.idCard">
+        <el-input
+            v-model="formData.idCard"
+            placeholder="请输入用户昵称"
+            class="!w-240px"
+            disabled
+        />
+      </el-form-item>
+      <el-form-item label="工作形象照" v-if="formData.workImg">
+        <el-input
+            v-model="formData.workImg"
+            placeholder="请输入用户昵称"
+            class="!w-240px"
+            disabled
+        />
+      </el-form-item>
+      <el-divider/>
+      <el-form-item label="审核结果" prop="status">
+        <el-radio-group v-model="verifyFormData.status" v-if="openType==='apply'||openType==='reapply'">
+          <el-radio :label="1">通过</el-radio>
+          <el-radio :label="3">驳回</el-radio>
+        </el-radio-group>
+        <el-radio-group v-model="authFormData.authStatus" v-if="openType==='auth'">
+          <el-radio :label="2">通过</el-radio>
+          <el-radio :label="3">驳回</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="审核意见" prop="reason">
+        <el-input type="textarea" v-model="verifyFormData.verifyText" placeholder="请输入审核意见"
+                  v-if="openType==='apply'"/>
+        <el-input type="textarea" v-model="authFormData.authText" placeholder="请输入审核意见"
+                  v-if="openType==='auth'"/>
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import * as UserApi from '@/api/coach/user'
+import MemberLevelSelect from '@/views/member/level/components/MemberLevelSelect.vue'
+import {getUserApply, updateUserApply} from "@/api/coach/user";
+import {WarningFilled} from '@element-plus/icons-vue'
+
+const {t} = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+const title = ref('申请详情');
+const dialogVisible = ref(false) // 弹窗的是否展示
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formData = ref({
+  id: undefined,
+  user_id: undefined,
+  name: undefined,
+  idCode: undefined,
+  idCard: undefined,
+  nickname: undefined,
+  sex: undefined,
+  mobile: undefined,
+  workImg: undefined,
+})
+const openType = ref();
+const verifyFormData = ref({
+  id: undefined,
+  status: 1,
+  verifyText: undefined
+})
+const authFormData = ref({
+  id: undefined,
+  authStatus: 2,
+  authText: undefined
+})
+const formRules = reactive({
+  status: [{required: true, trigger: 'blur'}]
+})
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const open = async (id?: number, type?: string) => {
+  dialogVisible.value = true
+  openType.value = type ?? 'apply';
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      if (openType.value === 'apply' || openType.value === 'reapply') {
+        title.value = '申请详情'
+        formData.value = await UserApi.getUserApply(id)
+
+      }
+      if (openType.value === 'auth') {
+        title.value = '认证详情'
+        formData.value = await UserApi.getUserAuth(id)
+      }
+
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({open}) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  formLoading.value = true
+
+  try {
+    if (openType.value === 'apply')
+      await UserApi.updateUserApply(verifyFormData.value, formData.value.id)
+    if (openType.value === 'auth')
+      await UserApi.updateUserAuth(authFormData.value, formData.value.id)
+    if (openType.value === 'reapply')
+      await UserApi.updateUserReapply(verifyFormData.value, formData.value.coach_id)
+
+    message.success(t('common.updateSuccess'))
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined,
+    user_id: undefined,
+    name: undefined,
+    idCode: undefined,
+    idCard: undefined,
+    nickname: undefined,
+    sex: undefined,
+    mobile: undefined,
+    workImg: undefined,
+
+  }
+  verifyFormData.value = {
+    id: undefined,
+    status: 1,
+    verifyText: undefined
+  }
+  authFormData.value = {
+    id: undefined,
+    authStatus: 2,
+    authText: undefined
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 1 - 1
src/views/coach/user/UserLevelUpdateForm.vue

@@ -1,5 +1,5 @@
 <template>
-  <Dialog title="修改用户等级" v-model="dialogVisible" width="600">
+  <Dialog title="修改用户等级1" v-model="dialogVisible" width="600">
     <el-form
       ref="formRef"
       :model="formData"

+ 113 - 97
src/views/coach/user/index.vue

@@ -2,57 +2,57 @@
   <ContentWrap>
     <!-- 搜索工作栏 -->
     <el-form
-      ref="queryFormRef"
-      :inline="true"
-      :model="queryParams"
-      class="-mb-15px"
-      label-width="68px"
+        ref="queryFormRef"
+        :inline="true"
+        :model="queryParams"
+        class="-mb-15px"
+        label-width="68px"
     >
       <el-form-item label="技工姓名" prop="nickname">
         <el-input
-          v-model="queryParams.nickname"
-          class="!w-240px"
-          clearable
-          placeholder="请输入技工姓名"
-          @keyup.enter="handleQuery"
+            v-model="queryParams.nickname"
+            class="!w-240px"
+            clearable
+            placeholder="请输入技工姓名"
+            @keyup.enter="handleQuery"
         />
       </el-form-item>
       <el-form-item label="手机号" prop="mobile">
         <el-input
-          v-model="queryParams.mobile"
-          class="!w-240px"
-          clearable
-          placeholder="请输入手机号"
-          @keyup.enter="handleQuery"
+            v-model="queryParams.mobile"
+            class="!w-240px"
+            clearable
+            placeholder="请输入手机号"
+            @keyup.enter="handleQuery"
         />
       </el-form-item>
       <el-form-item label="经纪人" prop="tagIds">
-        <MemberTagSelect v-model="queryParams.tagIds" />
+        <MemberTagSelect v-model="queryParams.tagIds"/>
       </el-form-item>
       <el-form-item label="代理商" prop="levelId">
-        <MemberLevelSelect v-model="queryParams.levelId" />
+        <MemberLevelSelect v-model="queryParams.levelId"/>
       </el-form-item>
       <el-form-item label="认证状态" prop="groupId">
-        <MemberGroupSelect v-model="queryParams.groupId" />
+        <MemberGroupSelect v-model="queryParams.groupId"/>
       </el-form-item>
       <el-form-item label="申请时间" prop="createTime">
         <el-date-picker
-          v-model="queryParams.createTime"
-          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          class="!w-240px"
-          end-placeholder="结束日期"
-          start-placeholder="开始日期"
-          type="daterange"
-          value-format="YYYY-MM-DD HH:mm:ss"
+            v-model="queryParams.createTime"
+            :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+            class="!w-240px"
+            end-placeholder="结束日期"
+            start-placeholder="开始日期"
+            type="daterange"
+            value-format="YYYY-MM-DD HH:mm:ss"
         />
       </el-form-item>
       <el-form-item>
         <el-button @click="handleQuery">
-          <Icon class="mr-5px" icon="ep:search" />
+          <Icon class="mr-5px" icon="ep:search"/>
           搜索
         </el-button>
         <el-button @click="resetQuery">
-          <Icon class="mr-5px" icon="ep:refresh" />
+          <Icon class="mr-5px" icon="ep:refresh"/>
           重置
         </el-button>
         <el-button v-hasPermi="['promotion:coupon:send']" @click="openCoupon">发送优惠券</el-button>
@@ -63,98 +63,96 @@
   <!-- 列表 -->
   <ContentWrap>
     <el-table
-      v-loading="loading"
-      :data="list"
-      :show-overflow-tooltip="true"
-      :stripe="true"
-      @selection-change="handleSelectionChange"
+        v-loading="loading"
+        :data="list"
+        :show-overflow-tooltip="true"
+        :stripe="true"
+        @selection-change="handleSelectionChange"
     >
-      <el-table-column type="selection" width="55" />
-      <el-table-column align="center" label="用户编号" prop="id" width="120px" />
+      <el-table-column type="selection" width="55"/>
+      <el-table-column align="center" label="用户编号" prop="id" width="120px"/>
       <el-table-column align="center" label="头像" prop="avatar" width="80px">
         <template #default="scope">
-          <img :src="scope.row.avatar" style="width: 40px" />
+          <img :src="scope.row.avatar" style="width: 40px"/>
         </template>
       </el-table-column>
-      <el-table-column align="center" label="姓名" prop="name" width="80px" />
-      <el-table-column align="center" label="手机号" prop="mobile" width="120px" />
+      <el-table-column align="center" label="姓名" prop="name" width="80px"/>
+      <el-table-column align="center" label="手机号" prop="mobile" width="120px"/>
       <el-table-column
-        :formatter="dateFormatter"
-        align="center"
-        label="申请时间"
-        prop="createTime"
-        width="180px"
+          :formatter="dateFormatter"
+          align="center"
+          label="申请时间"
+          prop="createTime"
+          width="180px"
       />
-      <el-table-column align="center" label="申请来源" prop="levelName" width="100px" />
-      <el-table-column align="center" label="是否绑定" prop="groupName" width="100px" />
+      <el-table-column align="center" label="申请来源" prop="levelName" width="100px"/>
+      <el-table-column align="center" label="是否绑定" prop="user_id" width="100px">
+        <template #default="scope">
+          <el-tag v-if="scope.row.user_id">是</el-tag>
+          <el-tag type="danger" v-else>否</el-tag>
+        </template>
+      </el-table-column>
       <el-table-column
-        :show-overflow-tooltip="false"
-        align="center"
-        label="认证状态"
-        prop="tagNames"
+          :show-overflow-tooltip="false"
+          align="center"
+          label="认证状态"
+          prop="authStatus"
       >
         <template #default="scope">
-          <el-tag v-for="(tagName, index) in scope.row.tagNames" :key="index" class="mr-5px">
-            {{ tagName }}
-          </el-tag>
+          <dict-tag :type="DICT_TYPE.COACH_AUTH_STATUS" :value="scope.row.authStatus"/>
         </template>
       </el-table-column>
       <el-table-column align="center" label="状态" prop="status" width="100px">
         <template #default="scope">
-          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
+          <dict-tag :type="DICT_TYPE.COACH_APPLY_STATUS" :value="scope.row.status"/>
         </template>
       </el-table-column>
-      <el-table-column align="center" label="所属经纪人" prop="point" width="100px" />
-      <el-table-column align="center" label="所属代理商" prop="point" width="100px" />
-      <el-table-column align="center" label="挂靠门店" prop="point" width="100px" />
+      <el-table-column align="center" label="所属经纪人" prop="point" width="100px"/>
+      <el-table-column align="center" label="所属代理商" prop="point" width="100px"/>
+      <el-table-column align="center" label="挂靠门店" prop="point" width="100px"/>
       <el-table-column
-        :show-overflow-tooltip="false"
-        align="center"
-        fixed="right"
-        label="操作"
-        width="100px"
+          :show-overflow-tooltip="false"
+          align="center"
+          fixed="right"
+          label="操作"
+          width="100px"
       >
         <template #default="scope">
           <div class="flex items-center justify-center">
-            <el-button link type="primary" @click="openDetail(scope.row.id)">详情</el-button>
+            <el-button link type="primary" @click="openDetail(scope.row.id)">编辑</el-button>
             <el-dropdown
-              v-hasPermi="[
-                'member:user:update',
-                'member:user:update-level',
-                'member:user:update-point',
-                'member:user:update-balance'
-              ]"
-              @command="(command) => handleCommand(command, scope.row)"
+                @command="(command) => handleCommand(command, scope.row)"
             >
               <el-button link type="primary">
-                <Icon icon="ep:d-arrow-right" />
+                <Icon icon="ep:d-arrow-right"/>
                 更多
               </el-button>
               <template #dropdown>
                 <el-dropdown-menu>
                   <el-dropdown-item
-                    v-if="checkPermi(['member:user:update'])"
-                    command="handleUpdate"
+                      command="handleUpdate"
                   >
-                    编辑
+                    设置代理商
                   </el-dropdown-item>
                   <el-dropdown-item
-                    v-if="checkPermi(['member:user:update-level'])"
-                    command="handleUpdateLevel"
+                      command="handleUpdateApply"
+                      v-if="scope.row.status === 0"
                   >
-                    修改等级
+                    授权申请
                   </el-dropdown-item>
+
                   <el-dropdown-item
-                    v-if="checkPermi(['member:user:update-point'])"
-                    command="handleUpdatePoint"
+                      command="handleUpdateAuth"
+                      v-if="scope.row.authStatus === 1"
                   >
-                    修改积分
+                    认证审核
                   </el-dropdown-item>
+
                   <el-dropdown-item
-                    v-if="checkPermi(['member:user:update-balance'])"
-                    command="handleUpdateBlance"
+                      command="handleUpdateReapply"
+                      v-if="scope.row.verify.status === 0"
                   >
-                    修改余额(WIP)
+                    重新审核
                   </el-dropdown-item>
                 </el-dropdown-menu>
               </template>
@@ -165,36 +163,41 @@
     </el-table>
     <!-- 分页 -->
     <Pagination
-      v-model:limit="queryParams.pageSize"
-      v-model:page="queryParams.pageNo"
-      :total="total"
-      @pagination="getList"
+        v-model:limit="queryParams.pageSize"
+        v-model:page="queryParams.pageNo"
+        :total="total"
+        @pagination="getList"
     />
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->
-  <UserForm ref="formRef" @success="getList" />
+  <UserForm ref="formRef" @success="getList"/>
   <!-- 修改用户等级弹窗 -->
-  <UserLevelUpdateForm ref="updateLevelFormRef" @success="getList" />
+  <UserLevelUpdateForm ref="updateLevelFormRef" @success="getList"/>
   <!-- 修改用户积分弹窗 -->
-  <UserPointUpdateForm ref="updatePointFormRef" @success="getList" />
+  <UserPointUpdateForm ref="updatePointFormRef" @success="getList"/>
   <!-- 发送优惠券弹窗 -->
-<!--  <CouponSendForm ref="couponSendFormRef" />-->
+  <!--  <CouponSendForm ref="couponSendFormRef" />-->
+
+  <!-- 修改用户申请弹窗 -->
+  <UserApplyUpdateForm ref="updateApplyFormRef" @success="getList"/>
 </template>
 <script lang="ts" setup>
-import { dateFormatter } from '@/utils/formatTime'
-import * as UserApi from '@/api/member/user'
-import { DICT_TYPE } from '@/utils/dict'
+import {dateFormatter} from '@/utils/formatTime'
+import * as UserApi from '@/api/coach/user'
+import {DICT_TYPE} from '@/utils/dict'
 import UserForm from './UserForm.vue'
 import MemberTagSelect from '@/views/member/tag/components/MemberTagSelect.vue'
 import MemberLevelSelect from '@/views/member/level/components/MemberLevelSelect.vue'
 import MemberGroupSelect from '@/views/member/group/components/MemberGroupSelect.vue'
 import UserLevelUpdateForm from './UserLevelUpdateForm.vue'
 import UserPointUpdateForm from './UserPointUpdateForm.vue'
+import UserApplyUpdateForm from './UserApplyUpdateForm.vue'
 // import { CouponSendForm } from '@/views/mall/promotion/coupon/components'
-import { checkPermi } from '@/utils/permission'
+import {checkPermi} from '@/utils/permission'
+import {getUserPage} from "@/api/coach/user";
 
-defineOptions({ name: 'MemberUser' })
+defineOptions({name: 'MemberUser'})
 
 const message = useMessage() // 消息弹窗
 
@@ -215,6 +218,9 @@ const queryParams = reactive({
 const queryFormRef = ref() // 搜索的表单
 const updateLevelFormRef = ref() // 修改会员等级表单
 const updatePointFormRef = ref() // 修改会员积分表单
+
+const updateApplyFormRef = ref() // 修改会员申请表单
+
 const selectedIds = ref<number[]>([]) // 表格的选中 ID 数组
 
 /** 查询列表 */
@@ -242,9 +248,9 @@ const resetQuery = () => {
 }
 
 /** 打开会员详情 */
-const { push } = useRouter()
+const {push} = useRouter()
 const openDetail = (id: number) => {
-  push({ name: 'MemberUserDetail', params: { id } })
+  push({name: 'MemberUserDetail', params: {id}})
 }
 
 /** 添加/修改操作 */
@@ -269,8 +275,18 @@ const openCoupon = () => {
 }
 
 /** 操作分发 */
-const handleCommand = (command: string, row: UserApi.UserVO) => {
+const handleCommand = (command: string, row: UserApi.User) => {
   switch (command) {
+    case 'handleUpdateAuth':
+      updateApplyFormRef.value.open(row.id, 'auth')
+      break;
+    case 'handleUpdateApply':
+      updateApplyFormRef.value.open(row.id, 'apply')
+      break;
+    case 'handleUpdateReapply':
+      console.log('hahaha',row)
+      updateApplyFormRef.value.open(row.id, 'reapply')
+      break;
     case 'handleUpdate':
       openForm('update', row.id)
       break

+ 38 - 30
src/views/service/project/UserForm.vue

@@ -1,11 +1,11 @@
 <template>
   <Dialog :title="dialogTitle" v-model="dialogVisible">
     <el-form
-      ref="formRef"
-      :model="formData"
-      :rules="formRules"
-      label-width="80px"
-      v-loading="formLoading"
+        ref="formRef"
+        :model="formData"
+        :rules="formRules"
+        label-width="80px"
+        v-loading="formLoading"
     >
       <el-row>
         <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
@@ -18,17 +18,17 @@
             <el-input v-model="formData.title" maxlength="15" show-word-limit
                       placeholder="请输入服务名称"/>
           </el-form-item>
-          <el-form-item label="副标题" prop="sub_title">
+          <el-form-item label="副标题" prop="subTitle">
             <el-input v-model="formData.subTitle" maxlength="30" show-word-limit
                       placeholder="请输入服务名称"/>
           </el-form-item>
           <el-form-item label="所属分类" prop="category">
-            <el-select v-model="formData.category" clearable placeholder="请选择所属分类">
+            <el-select v-model="formData.category" multiple clearable collapse-tags placeholder="请选择所属分类">
               <el-option
-                v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
-                :key="dict.value"
-                :label="dict.label"
-                :value="dict.value"
+                  v-for="cate in categoryList"
+                  :key="cate.id"
+                  :label="cate.title"
+                  :value="cate.id"
               />
             </el-select>
           </el-form-item>
@@ -48,7 +48,7 @@
           </el-form-item>
         </el-col>
         <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
-          <el-form-item label="服务原价" prop="init_price">
+          <el-form-item label="服务原价" prop="initPrice">
             <el-input v-model="formData.initPrice" placeholder="请输入服务原价">
               <template #append>元</template>
             </el-input>
@@ -103,17 +103,17 @@
         <el-input-number v-model="formData.sort" :min="0" clearable controls-position="right"/>
       </el-form-item>
       <el-form-item label="项目介绍" prop="introduce">
-        <Editor :model-value="formData.introduce" height="150px"/>
+        <Editor v-model="formData.introduce"  height="150px" :editor-config="editorConfig"/>
       </el-form-item>
       <el-form-item label="禁忌说明" prop="explain">
-        <Editor :model-value="formData.explain" height="150px"/>
+        <Editor v-model="formData.explain" height="150px"/>
       </el-form-item>
       <el-form-item label="下单须知" prop="notice">
-        <Editor :model-value="formData.notice" height="150px"/>
+        <Editor v-model="formData.notice" height="150px"/>
       </el-form-item>
-<!--      <el-form-item label="关联技工" prop="coach">-->
-<!--        <Editor :model-value="formData.coach" height="150px"/>-->
-<!--      </el-form-item>-->
+      <!--      <el-form-item label="关联技工" prop="coach">-->
+      <!--        <Editor :model-value="formData.coach" height="150px"/>-->
+      <!--      </el-form-item>-->
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
@@ -122,8 +122,9 @@
   </Dialog>
 </template>
 <script setup lang="ts">
-import {DICT_TYPE, getIntDictOptions} from '@/utils/dict'
 import * as ProjectApi from '@/api/service/project'
+import {getSimpleCategoryList} from "@/api/service/category"
+import { createEditorConfig } from './editor-config'
 
 const {t} = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
@@ -145,18 +146,25 @@ const formData = ref({
   timeLong: undefined,
   comBalance: undefined,
   sort: undefined,
-  isStore: undefined,
-  isDoor: undefined,
-  isAdd: undefined,
-  introduce: undefined,
-  explain: undefined,
-  notice: undefined
+  isStore: true,
+  isDoor: true,
+  isAdd: false,
+  introduce: '',
+  explain: '',
+  notice: ''
 })
 const formRules = reactive({
   title: [{required: true, message: '服务名称不能为空', trigger: 'blur'}],
+  subTitle: [{required: true, message: '服务副标题不能为空', trigger: 'blur'}],
 })
 const formRef = ref() // 表单 Ref
-const areaList = ref([]) // 地区列表
+const categoryList = ref([]) // 地区列表
+
+const accountId = inject<number>('accountId')
+
+// ========== 文件上传 ==========
+const UPLOAD_URL = import.meta.env.VITE_BASE_URL + '/admin-api/mp/material/upload-permanent' // 上传永久素材的地址
+const editorConfig = createEditorConfig(UPLOAD_URL, accountId)
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
@@ -174,7 +182,7 @@ const open = async (type: string, id?: number) => {
     }
   }
   // 获得地区列表
-  // areaList.value = await AreaApi.getAreaTree()
+  categoryList.value = await getSimpleCategoryList()
 }
 defineExpose({open}) // 提供 open 方法,用于打开弹窗
 
@@ -222,9 +230,9 @@ const resetForm = () => {
     isStore: true,
     isDoor: true,
     isAdd: false,
-    introduce: undefined,
-    explain: undefined,
-    notice: undefined
+    introduce: '',
+    explain: '',
+    notice: ''
   }
   formRef.value?.resetFields()
 }

+ 75 - 0
src/views/service/project/editor-config.ts

@@ -0,0 +1,75 @@
+import { IEditorConfig } from '@wangeditor/editor'
+import { getAccessToken, getTenantId } from '@/utils/auth'
+
+const message = useMessage()
+
+type InsertFnType = (url: string, alt: string, href: string) => void
+
+export const createEditorConfig = (
+  server: string,
+  accountId: number | undefined
+): Partial<IEditorConfig> => {
+  return {
+    MENU_CONF: {
+      ['uploadImage']: {
+        server,
+        // 单个文件的最大体积限制,默认为 2M
+        maxFileSize: 5 * 1024 * 1024,
+        // 最多可上传几个文件,默认为 100
+        maxNumberOfFiles: 10,
+        // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
+        allowedFileTypes: ['image/*'],
+
+        // 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
+        meta: {
+          accountId: accountId,
+          type: 'image'
+        },
+        // 将 meta 拼接到 url 参数中,默认 false
+        metaWithUrl: true,
+
+        // 自定义增加 http  header
+        headers: {
+          Accept: '*',
+          Authorization: 'Bearer ' + getAccessToken(),
+          'tenant-id': getTenantId()
+        },
+
+        // 跨域是否传递 cookie ,默认为 false
+        withCredentials: true,
+
+        // 超时时间,默认为 10 秒
+        timeout: 5 * 1000, // 5 秒
+
+        // form-data fieldName,后端接口参数名称,默认值wangeditor-uploaded-image
+        fieldName: 'file',
+
+        // 上传之前触发
+        onBeforeUpload(file: File) {
+          console.log(file)
+          return file
+        },
+        // 上传进度的回调函数
+        onProgress(progress: number) {
+          // progress 是 0-100 的数字
+          console.log('progress', progress)
+        },
+        onSuccess(file: File, res: any) {
+          console.log('onSuccess', file, res)
+        },
+        onFailed(file: File, res: any) {
+          message.alertError(res.message)
+          console.log('onFailed', file, res)
+        },
+        onError(file: File, err: any, res: any) {
+          message.alertError(err.message)
+          console.error('onError', file, err, res)
+        },
+        // 自定义插入图片
+        customInsert(res: any, insertFn: InsertFnType) {
+          insertFn(res.data.url, 'image', res.data.url)
+        }
+      }
+    }
+  }
+}

+ 81 - 124
src/views/service/project/index.vue

@@ -2,40 +2,40 @@
   <ContentWrap>
     <!-- 搜索工作栏 -->
     <el-form
-      ref="queryFormRef"
-      :inline="true"
-      :model="queryParams"
-      class="-mb-15px"
-      label-width="68px"
+        ref="queryFormRef"
+        :inline="true"
+        :model="queryParams"
+        class="-mb-15px"
+        label-width="68px"
     >
       <el-form-item label="服务名称" prop="title">
         <el-input
-          v-model="queryParams.title"
-          class="!w-240px"
-          clearable
-          placeholder="请输入服务名称"
-          @keyup.enter="handleQuery"
+            v-model="queryParams.title"
+            class="!w-240px"
+            clearable
+            placeholder="请输入服务名称"
+            @keyup.enter="handleQuery"
         />
       </el-form-item>
       <el-form-item label="状态" prop="status">
         <el-select v-model="queryParams.status" class="!w-240px" clearable placeholder="请选择状态">
           <el-option
-            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
-            :key="dict.value"
-            :label="dict.label"
-            :value="dict.value"
+              v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
           />
         </el-select>
       </el-form-item>
       <el-form-item label="注册时间" prop="createTime">
         <el-date-picker
-          v-model="queryParams.createTime"
-          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          class="!w-240px"
-          end-placeholder="结束日期"
-          start-placeholder="开始日期"
-          type="daterange"
-          value-format="YYYY-MM-DD HH:mm:ss"
+            v-model="queryParams.createTime"
+            :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+            class="!w-240px"
+            end-placeholder="结束日期"
+            start-placeholder="开始日期"
+            type="daterange"
+            value-format="YYYY-MM-DD HH:mm:ss"
         />
       </el-form-item>
       <el-form-item>
@@ -49,10 +49,10 @@
         </el-button>
 
         <el-button
-          v-hasPermi="['system:role:create']"
-          plain
-          type="primary"
-          @click="openForm('create')"
+            v-hasPermi="['system:role:create']"
+            plain
+            type="primary"
+            @click="openForm('create')"
         >
           <Icon class="mr-5px" icon="ep:plus"/>
           新增
@@ -67,11 +67,11 @@
   <!-- 列表 -->
   <ContentWrap>
     <el-table
-      v-loading="loading"
-      :data="list"
-      :show-overflow-tooltip="true"
-      :stripe="true"
-      @selection-change="handleSelectionChange"
+        v-loading="loading"
+        :data="list"
+        :show-overflow-tooltip="true"
+        :stripe="true"
+        @selection-change="handleSelectionChange"
     >
       <el-table-column type="selection" width="55"/>
       <el-table-column align="center" label="编号" prop="id"/>
@@ -82,13 +82,13 @@
       </el-table-column>
       <el-table-column align="center" label="服务名称" prop="title"/>
       <el-table-column align="center" label="价格" prop="price">
-        <template #default="scope">¥ {{ roundFormatter(scope.row.price / 100) }}</template>
+        <template #default="scope">¥ {{ scope.row.price }}</template>
       </el-table-column>
-      <el-table-column align="center" label="原价" prop="initPrice" >
-        <template #default="scope">¥ {{ roundFormatter(scope.row.initPrice / 100) }}</template>
+      <el-table-column align="center" label="原价" prop="initPrice">
+        <template #default="scope">¥ {{ scope.row.initPrice  }}</template>
       </el-table-column>
       <el-table-column align="center" label="物料费" prop="materialPrice">
-        <template #default="scope">¥ {{ roundFormatter(scope.row.materialPrice / 100) }}</template>
+        <template #default="scope">¥ {{ scope.row.materialPrice }}</template>
       </el-table-column>
       <el-table-column align="center" label="服务时长" prop="timeLong">
         <template #default="scope">{{ scope.row.timeLong }} 分钟</template>
@@ -97,82 +97,55 @@
       <el-table-column align="center" label="状态" prop="status">
         <template #default="scope">
           <el-switch
-            v-model="scope.row.status"
-            :active-value="0"
-            :inactive-value="1"
-            @change="handleStatusChange(scope.row)"
+              v-model="scope.row.status"
+              :active-value="0"
+              :inactive-value="1"
+              @change="handleStatusChange(scope.row)"
           />
         </template>
       </el-table-column>
       <el-table-column
-        :formatter="dateFormatter"
-        align="center"
-        label="创建时间"
-        prop="createTime"
-        width="180px"
+          :formatter="dateFormatter"
+          align="center"
+          label="创建时间"
+          prop="createTime"
+          width="180px"
       />
-      <el-table-column
-        :show-overflow-tooltip="false"
-        align="center"
-        fixed="right"
-        label="操作"
-        width="100px"
-      >
+      <el-table-column :show-overflow-tooltip="false" label="操作" align="center" width="160">
         <template #default="scope">
           <div class="flex items-center justify-center">
-            <el-button link type="primary" @click="openDetail(scope.row.id)">详情</el-button>
-            <el-dropdown
-              v-hasPermi="[
-                'member:user:update',
-                'member:user:update-level',
-                'member:user:update-point',
-                'member:user:update-balance'
-              ]"
-              @command="(command) => handleCommand(command, scope.row)"
+            <el-button
+                type="primary"
+                link
+                @click="openForm('update', scope.row.id)"
+            >
+              修改
+            </el-button>
+            <el-button
+                type="primary"
+                link
+                @click="openForm('update', scope.row.id)"
             >
-              <el-button link type="primary">
-                <Icon icon="ep:d-arrow-right"/>
-                更多
-              </el-button>
-              <template #dropdown>
-                <el-dropdown-menu>
-                  <el-dropdown-item
-                    v-if="checkPermi(['member:user:update'])"
-                    command="handleUpdate"
-                  >
-                    编辑
-                  </el-dropdown-item>
-                  <el-dropdown-item
-                    v-if="checkPermi(['member:user:update-level'])"
-                    command="handleUpdateLevel"
-                  >
-                    修改等级
-                  </el-dropdown-item>
-                  <el-dropdown-item
-                    v-if="checkPermi(['member:user:update-point'])"
-                    command="handleUpdatePoint"
-                  >
-                    修改积分
-                  </el-dropdown-item>
-                  <el-dropdown-item
-                    v-if="checkPermi(['member:user:update-balance'])"
-                    command="handleUpdateBlance"
-                  >
-                    修改余额(WIP)
-                  </el-dropdown-item>
-                </el-dropdown-menu>
-              </template>
-            </el-dropdown>
+              开通技工
+            </el-button>
+            <el-button
+                v-hasPermi="['system:role:delete']"
+                link
+                type="danger"
+                @click="handleDelete(scope.row.id)"
+            >
+              删除
+            </el-button>
           </div>
         </template>
       </el-table-column>
     </el-table>
     <!-- 分页 -->
     <Pagination
-      v-model:limit="queryParams.pageSize"
-      v-model:page="queryParams.pageNo"
-      :total="total"
-      @pagination="getList"
+        v-model:limit="queryParams.pageSize"
+        v-model:page="queryParams.pageNo"
+        :total="total"
+        @pagination="getList"
     />
   </ContentWrap>
 
@@ -195,6 +168,7 @@ import {checkPermi} from '@/utils/permission'
 defineOptions({name: 'MemberUser'})
 
 const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
 
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
@@ -235,12 +209,6 @@ const resetQuery = () => {
   handleQuery()
 }
 
-/** 打开会员详情 */
-const {push} = useRouter()
-const openDetail = (id: number) => {
-  push({name: 'MemberUserDetail', params: {id}})
-}
-
 /** 添加/修改操作 */
 const formRef = ref()
 const openForm = (type: string, id?: number) => {
@@ -252,31 +220,20 @@ const handleSelectionChange = (rows: ProjectApi.Project[]) => {
   selectedIds.value = rows.map((row) => row.id)
 }
 
-/** 操作分发 */
-const handleCommand = (command: string, row: ProjectApi.Project) => {
-  switch (command) {
-    case 'handleUpdate':
-      openForm('update', row.id)
-      break
-    case 'handleUpdateLevel':
-      updateLevelFormRef.value.open(row.id)
-      break
-    case 'handleUpdatePoint':
-      updatePointFormRef.value.open(row.id)
-      break
-    case 'handleUpdateBlance':
-      // todo @jason:增加一个【修改余额】
-      break
-    default:
-      break
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await ProjectApi.deleteProject(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {
   }
 }
 
-// 保留两位小数
-const roundFormatter = (cellValue) => {
-  return cellValue.toFixed(2); // 四舍五入保留两位小数
-}
-
 /** 初始化 **/
 onMounted(() => {
   getList()