Parcourir la source

1. 角色信息查询
2. 账号查询

ith5 il y a 6 mois
Parent
commit
ad92704833

+ 7 - 8
src/App.vue

@@ -1,15 +1,14 @@
 <script setup>
-  import cn from '@arco-design/web-vue/es/locale/lang/zh-cn'
-  import en from '@arco-design/web-vue/es/locale/lang/en-us'
-  import { ref } from 'vue'
-  import { useAppStore } from './store'
-  const appStore = useAppStore()
-  const lang = ref(appStore.language === 'zh_CN' ? cn : en)
-
+import cn from "@arco-design/web-vue/es/locale/lang/zh-cn";
+import en from "@arco-design/web-vue/es/locale/lang/en-us";
+import { ref } from "vue";
+import { useAppStore } from "./store";
+const appStore = useAppStore();
+const lang = ref(appStore.language === "zh_CN" ? cn : en);
 </script>
 
 <template>
   <a-config-provider :locale="lang" :update-at-scroll="true">
     <router-view />
   </a-config-provider>
-</template>
+</template>

+ 3 - 1
src/components/sa-table/index.vue

@@ -218,6 +218,7 @@
             </a-space>
           </a-col>
         </a-row>
+
         <div ref="crudContentRef">
           <slot name="crudContent" v-bind="tableData">
             <a-table
@@ -553,7 +554,7 @@ const props = defineProps({
   searchForm: { type: Object, default: () => {} },
 });
 
-const emit = defineEmits(["resetSearch"]);
+const emit = defineEmits(["resetSearch", "search"]);
 
 const searchFormRef = ref();
 const crudHeaderRef = ref();
@@ -811,6 +812,7 @@ const init = async () => {
 
 const refresh = async () => {
   await requestData();
+  emit("search");
   //tableRef.value?.selectAll(false)
 };
 

+ 15 - 6
src/layout/components/ma-workerArea.vue

@@ -1,11 +1,18 @@
 <template>
   <a-layout-content class="work-area customer-scrollbar relative">
-    <div class="h-full" :class="{ 'p-3': $route.path.indexOf('maIframe') === -1 }">
+    <div
+      class="h-full"
+      :class="{ 'p-3': $route.path.indexOf('maIframe') === -1 }"
+    >
       <a-watermark :content="appStore.waterMark ? appStore.waterContent : ''">
         <router-view v-slot="{ Component }">
           <transition :name="appStore.animation" mode="out-in">
             <keep-alive :include="keepStore.keepAlives">
-              <component :is="Component" :key="$route.fullPath" v-if="keepStore.show" />
+              <component
+                :is="Component"
+                :key="$route.fullPath"
+                v-if="keepStore.show"
+              />
             </keep-alive>
           </transition>
         </router-view>
@@ -16,8 +23,10 @@
 </template>
 
 <script setup>
-import { useAppStore, useKeepAliveStore } from '@/store'
-import IframeView from './components/iframe-view.vue'
-const appStore = useAppStore()
-const keepStore = useKeepAliveStore()
+import { useAppStore, useKeepAliveStore } from "@/store";
+import IframeView from "./components/iframe-view.vue";
+const appStore = useAppStore();
+const keepStore = useKeepAliveStore();
+console.log("keepAlives");
+console.log("keepAlives", keepStore.keepAlives);
 </script>

+ 23 - 1
src/views/v1/api/common.js

@@ -17,7 +17,7 @@ export default {
   },
 
   /**
-   * 获取子游戏options
+   * 获取子游戏options(有权限)
    * @param {Object} params
    * @returns
    */
@@ -28,4 +28,26 @@ export default {
       params,
     });
   },
+
+  /**
+   * 获取子游戏options(无权限)
+   */
+  getGameOptionsApiNoAuth(params = {}) {
+    return request({
+      url: "/v1/common/getGameOptionsNoAuth",
+      method: "get",
+      params,
+    });
+  },
+
+  /**
+   * 获取广告位options
+   */
+  getAgentSiteOptionsApi(params = {}) {
+    return request({
+      url: "/v1/common/getAgentSiteOptions",
+      method: "get",
+      params,
+    });
+  },
 };

+ 91 - 0
src/views/v1/api/customer/account.js

@@ -0,0 +1,91 @@
+import { request } from "@/utils/request.js";
+
+/**
+ * 账号信息 API接口
+ */
+export default {
+  /**
+   * 数据列表
+   * @returns
+   */
+  getPageList(params = {}) {
+    return request({
+      url: "/v1/customer/Account/index",
+      method: "get",
+      params,
+    });
+  },
+
+  /**
+   * 添加数据
+   * @returns
+   */
+  save(params = {}) {
+    return request({
+      url: "/v1/customer/Account/save",
+      method: "post",
+      data: params,
+    });
+  },
+
+  /**
+   * 更新数据
+   * @returns
+   */
+  update(id, data = {}) {
+    return request({
+      url: "/v1/customer/Account/update?id=" + id,
+      method: "put",
+      data,
+    });
+  },
+
+  /**
+   * 读取数据
+   * @returns
+   */
+  read(id) {
+    return request({
+      url: "/v1/customer/Account/read?id=" + id,
+      method: "get",
+    });
+  },
+
+  /**
+   * 删除数据
+   * @returns
+   */
+  destroy(data) {
+    return request({
+      url: "/v1/customer/Account/destroy",
+      method: "delete",
+      data,
+    });
+  },
+
+  /**
+   * 修改密码
+   * @returns
+   */
+  updatePwdApi(data) {
+    return request({
+      url: "/v1/customer/Account/updatePwd",
+      method: "post",
+      data,
+    });
+  },
+  updateMobileApi(data) {
+    return request({
+      url: "/v1/customer/Account/updateMobile",
+      method: "post",
+      data,
+    });
+  },
+  updateRealApi(data) {
+    return request({
+      url: "/v1/customer/Account/updateReal",
+      method: "post",
+      data,
+    });
+  },
+};

+ 67 - 0
src/views/v1/api/customer/roleData.js

@@ -0,0 +1,67 @@
+import { request } from '@/utils/request.js'
+
+/**
+ * 角色查询 API接口
+ */
+export default {
+
+  /**
+   * 数据列表
+   * @returns
+   */
+  getPageList(params = {}) {
+    return request({
+      url: '/v1/customer/RoleData/index',
+      method: 'get',
+      params
+    })
+  },
+
+  /**
+   * 添加数据
+   * @returns
+   */
+  save(params = {}) {
+    return request({
+      url: '/v1/customer/RoleData/save',
+      method: 'post',
+      data: params
+    })
+  },
+
+  /**
+   * 更新数据
+   * @returns
+   */
+  update(id, data = {}) {
+    return request({
+      url: '/v1/customer/RoleData/update?id=' + id,
+      method: 'put',
+      data
+    })
+  },
+
+  /**
+   * 读取数据
+   * @returns
+   */
+  read(id) {
+    return request({
+      url: '/v1/customer/RoleData/read?id=' + id,
+      method: 'get'
+    })
+  },
+
+  /**
+   * 删除数据
+   * @returns
+   */
+  destroy(data) {
+    return request({
+      url: '/v1/customer/RoleData/destroy',
+      method: 'delete',
+      data
+    })
+  },
+
+}

+ 151 - 0
src/views/v1/customer/account/edit.vue

@@ -0,0 +1,151 @@
+<template>
+  <component
+    is="a-modal"
+    :width="tool.getDevice() === 'mobile' ? '100%' : '600px'"
+    v-model:visible="visible"
+    :title="title"
+    :mask-closable="false"
+    :ok-loading="loading"
+    @cancel="close"
+    @before-ok="submit"
+  >
+    <!-- 表单信息 start -->
+    <a-form
+      ref="formRef"
+      :model="formData"
+      :rules="rules"
+      :auto-label-width="true"
+    >
+      {{ mode }}
+      <a-form-item label="用户真实名" field="real_name" v-if="mode === 'real'">
+        <a-input v-model="formData.real_name" placeholder="请输入用户真实名" />
+      </a-form-item>
+      <a-form-item label="证件号码" field="id_card" v-if="mode === 'real'">
+        <a-input v-model="formData.id_card" placeholder="请输入证件号码" />
+      </a-form-item>
+      <a-form-item label="手机" field="mobile" v-if="mode === 'mobile'">
+        <a-input v-model="formData.mobile" placeholder="请输入手机" />
+      </a-form-item>
+      <a-form-item label="密码" field="user_pwd" v-if="mode === 'pwd'">
+        <a-input-password
+          v-model="formData.user_pwd"
+          placeholder="请输入密码"
+        />
+      </a-form-item>
+    </a-form>
+    <!-- 表单信息 end -->
+  </component>
+</template>
+
+<script setup>
+import { ref, reactive, computed } from "vue";
+import tool from "@/utils/tool";
+import { Message, Modal } from "@arco-design/web-vue";
+import api from "../../api/customer/account";
+
+const emit = defineEmits(["success"]);
+// 引用定义
+const visible = ref(false);
+const loading = ref(false);
+const formRef = ref();
+const mode = ref("");
+
+let title = computed(() => {
+  return "账号信息" + (mode.value == "add" ? "-新增" : "-编辑");
+});
+
+// 表单初始值
+const initialFormData = {
+  uid: null,
+  user_pwd: "",
+  real_name: "",
+  id_card: "",
+  mobile: "",
+};
+
+// 表单信息
+const formData = reactive({ ...initialFormData });
+
+// 验证规则
+const rules = {
+  uid: [{ required: true, message: "用户UID必需填写" }],
+  user_name: [{ required: true, message: "用户名必需填写" }],
+  user_pwd: [{ required: true, message: "用户密码必需填写" }],
+  email: [{ required: true, message: "用户邮箱必需填写" }],
+  real_name: [
+    {
+      required: true,
+      match: /^[\u4e00-\u9fa5]{2,4}$/,
+      message: "用户真实名格式不正确",
+    },
+  ],
+  id_card: [
+    {
+      required: true,
+      match:
+        /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[0-1])\d{3}[0-9Xx]$/,
+      message: "证件号码格式不正确",
+    },
+  ],
+  mobile: [
+    { required: true, match: /^1[3-9]\d{9}$/, message: "手机格式不正确" },
+  ],
+};
+
+// 打开弹框
+const open = async (type = "add", data) => {
+  mode.value = type;
+  // 重置表单数据
+  Object.assign(formData, data);
+  formRef.value.clearValidate();
+  visible.value = true;
+  await initPage();
+};
+
+// 初始化页面数据
+const initPage = async () => {};
+
+// 设置数据
+const setFormData = async (data) => {
+  for (const key in formData) {
+    if (data[key] != null && data[key] != undefined) {
+      formData[key] = data[key];
+    }
+  }
+};
+
+// 数据保存
+const submit = async (done) => {
+  const validate = await formRef.value?.validate();
+  if (!validate) {
+    loading.value = true;
+    let data = { ...formData };
+    let result = {};
+
+    // 修改数据
+    if (mode.value === "pwd") {
+      result = await api.updatePwdApi(data);
+    } else if (mode.value === "mobile") {
+      result = await api.updateMobileApi(data);
+    } else if (mode.value === "real") {
+      result = await api.updateRealApi(data);
+    }
+
+    if (result.code === 200) {
+      Message.success("操作成功");
+      emit("success");
+      done(true);
+    }
+    // 防止连续点击提交
+    setTimeout(() => {
+      loading.value = false;
+    }, 500);
+  }
+  done(false);
+};
+
+// 关闭弹窗
+const close = () => (visible.value = false);
+
+defineExpose({ open, setFormData });
+</script>

+ 144 - 0
src/views/v1/customer/account/index.vue

@@ -0,0 +1,144 @@
+<template>
+  <div class="ma-content-block">
+    <sa-table
+      ref="crudRef"
+      :options="options"
+      :searchForm="searchForm"
+      @search="search"
+    >
+      <!-- 搜索区 tableSearch -->
+      <template #tableSearch>
+        <a-col :sm="8" :xs="24">
+          <a-form-item>
+            <a-input v-model="searchForm.val" placeholder="请输入" allow-clear>
+              <template #prepend>
+                <a-select v-model="searchForm.type">
+                  <a-option value="1">账号</a-option>
+                  <a-option value="2">UID</a-option>
+                </a-select>
+              </template>
+            </a-input>
+          </a-form-item>
+        </a-col>
+      </template>
+
+      <!-- Table 自定义渲染 -->
+      <template #crudContent>
+        <a-descriptions
+          direction="vertical"
+          size="large"
+          title="账号信息"
+          bordered
+        >
+          <a-descriptions-item label="账号">
+            {{ data[0]?.user_name }}
+          </a-descriptions-item>
+          <a-descriptions-item label="UID">
+            {{ data[0]?.uid }}
+          </a-descriptions-item>
+          <a-descriptions-item label="注册时间">
+            {{ data[0]?.reg_time }}
+          </a-descriptions-item>
+          <a-descriptions-item label="注册IP">
+            {{ data[0]?.reg_ip }}
+          </a-descriptions-item>
+          <a-descriptions-item label="最后登录IP">
+            {{ data[0]?.login_ip }}
+          </a-descriptions-item>
+          <a-descriptions-item label="最后登录时间">
+            {{ data[0]?.login_time }}
+          </a-descriptions-item>
+          <a-descriptions-item label="真实姓名">
+            {{ data[0]?.real_name }}
+          </a-descriptions-item>
+          <a-descriptions-item label="证件号码">
+            {{ data[0]?.id_card }}
+          </a-descriptions-item>
+          <a-descriptions-item label="手机">
+            {{ data[0]?.mobile }}
+          </a-descriptions-item>
+          <a-descriptions-item label="状态">
+            <a-tag color="green" v-if="data[0]?.status == 1">正常</a-tag>
+            <a-tag color="red" v-if="data[0]?.status == 0">禁用</a-tag>
+          </a-descriptions-item>
+          <a-descriptions-item label="操作">
+            <a-space v-if="data[0]?.status == 1">
+              <a-button
+                status="danger"
+                type="primary"
+                @click="edit('pwd', data[0])"
+                size="small"
+                >修改密码</a-button
+              >
+              <a-button
+                type="primary"
+                @click="edit('mobile', data[0])"
+                size="small"
+                >修改绑定手机号码</a-button
+              >
+              <a-button
+                status="warning"
+                type="primary"
+                @click="edit('real', data[0])"
+                size="small"
+                >修改实名信息</a-button
+              >
+            </a-space>
+          </a-descriptions-item>
+        </a-descriptions>
+      </template>
+    </sa-table>
+
+    <!-- 编辑表单 -->
+    <edit-form ref="editRef" @success="refresh" />
+  </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from "vue";
+// import { Message } from "@arco-design/web-vue";
+import EditForm from "./edit.vue";
+import api from "../../api/customer/account";
+
+// 引用定义
+const crudRef = ref();
+const editRef = ref();
+const viewRef = ref();
+const data = ref([]);
+
+// 搜索表单
+const searchForm = ref({
+  val: "",
+  type: "1",
+});
+
+// SaTable 基础配置
+const options = reactive({
+  api: api.getPageList,
+  pageSimple: true,
+});
+
+// 页面数据初始化
+const initPage = async () => {};
+
+// SaTable 数据请求
+const refresh = async () => {
+  crudRef.value?.refresh();
+  data.value = crudRef.value?.getTableData() || [];
+  console.log("===>", crudRef.value?.getTableData());
+};
+
+const edit = async (type, data) => {
+  editRef.value?.open(type, data);
+};
+
+const search = async () => {
+  data.value = crudRef.value?.getTableData() || [];
+};
+
+// 页面加载完成执行
+onMounted(async () => {
+  initPage();
+  // refresh();
+});
+</script>

+ 158 - 0
src/views/v1/customer/roleData/edit.vue

@@ -0,0 +1,158 @@
+<template>
+  <component
+    is="a-modal"
+    :width="tool.getDevice() === 'mobile' ? '100%' : '600px'"
+    v-model:visible="visible"
+    :title="title"
+    :mask-closable="false"
+    :ok-loading="loading"
+    @cancel="close"
+    @before-ok="submit"
+  >
+    <!-- 表单信息 start -->
+    <a-form
+      ref="formRef"
+      :model="formData"
+      :rules="rules"
+      :auto-label-width="true"
+    >
+      <a-form-item label="用户名" field="user_name">
+        <a-input
+          v-model="formData.user_name"
+          disabled
+          placeholder="请输入用户名"
+        />
+      </a-form-item>
+      <a-form-item label="服务器名" field="server_name">
+        <a-input
+          v-model="formData.server_name"
+          disabled
+          placeholder="请输入玩家所在服务器的名称"
+        />
+      </a-form-item>
+
+      <a-form-item label="角色名" field="role_name">
+        <a-input
+          v-model="formData.role_name"
+          disabled
+          placeholder="请输入角色名"
+        />
+      </a-form-item>
+      <a-form-item label="广告位ID" field="site_id">
+        <!-- <a-input v-model="formData.site_id" placeholder="请输入广告位ID" /> -->
+        <a-select v-model="formData.site_id" placeholder="请选择广告位">
+          <a-option
+            v-for="item in agentSiteOptions"
+            :key="item.id"
+            :value="item.id"
+            allow-search
+          >
+            [{{ item.id }}] {{ item.name }}
+          </a-option>
+        </a-select>
+      </a-form-item>
+    </a-form>
+    <!-- 表单信息 end -->
+  </component>
+</template>
+
+<script setup>
+import { ref, reactive, computed } from "vue";
+import tool from "@/utils/tool";
+import { Message, Modal } from "@arco-design/web-vue";
+import api from "../../api/customer/roleData";
+import commonApi from "../../api/common";
+
+const emit = defineEmits(["success"]);
+// 引用定义
+const visible = ref(false);
+const loading = ref(false);
+const formRef = ref();
+const mode = ref("");
+const agentSiteOptions = ref([]);
+
+let title = computed(() => {
+  return "角色查询" + (mode.value == "add" ? "-新增" : "-编辑");
+});
+
+// 表单初始值
+const initialFormData = {
+  id: null,
+  site_id: null,
+  server_name: "",
+  user_name: "",
+  role_name: "",
+  platform: "",
+};
+
+// 表单信息
+const formData = reactive({ ...initialFormData });
+
+// 验证规则
+const rules = {
+  site_id: [{ required: true, message: "广告位ID必需填写" }],
+};
+
+// 打开弹框
+const open = async (type = "add") => {
+  mode.value = type;
+  // 重置表单数据
+  Object.assign(formData, initialFormData);
+  formRef.value.clearValidate();
+  visible.value = true;
+  await initPage();
+};
+
+// 初始化页面数据
+const initPage = async () => {
+  await getAgentSiteOptions();
+};
+
+// 获取广告位options
+const getAgentSiteOptions = async () => {
+  const res = await commonApi.getAgentSiteOptionsApi();
+  agentSiteOptions.value = res.data;
+};
+
+// 设置数据
+const setFormData = async (data) => {
+  for (const key in formData) {
+    if (data[key] != null && data[key] != undefined) {
+      formData[key] = data[key];
+    }
+  }
+};
+
+// 数据保存
+const submit = async (done) => {
+  const validate = await formRef.value?.validate();
+  if (!validate) {
+    loading.value = true;
+    let data = { ...formData };
+    let result = {};
+    if (mode.value === "add") {
+      // 添加数据
+      data.id = undefined;
+      result = await api.save(data);
+    } else {
+      // 修改数据
+      result = await api.update(data.id, data);
+    }
+    if (result.code === 200) {
+      Message.success("操作成功");
+      emit("success");
+      done(true);
+    }
+    // 防止连续点击提交
+    setTimeout(() => {
+      loading.value = false;
+    }, 500);
+  }
+  done(false);
+};
+
+// 关闭弹窗
+const close = () => (visible.value = false);
+
+defineExpose({ open, setFormData });
+</script>

+ 166 - 0
src/views/v1/customer/roleData/index.vue

@@ -0,0 +1,166 @@
+<template>
+  <div class="ma-content-block">
+    <sa-table
+      ref="crudRef"
+      :options="options"
+      :columns="columns"
+      :searchForm="searchForm"
+    >
+      <!-- 搜索区 tableSearch -->
+      <template #tableSearch>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="游戏" field="game_id">
+            <a-select
+              v-model="searchForm.game_id"
+              placeholder="请选择游戏"
+              allow-clear
+            >
+              <a-option
+                v-for="item in allGameOptions"
+                :key="item.id"
+                :value="item.id"
+              >
+                [{{ item.id }}] {{ item.name }}
+              </a-option>
+            </a-select>
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="用户名" field="user_name">
+            <a-input
+              v-model="searchForm.user_name"
+              placeholder="请输入用户名"
+              allow-clear
+            />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="用户UID" field="uid">
+            <a-input
+              v-model="searchForm.uid"
+              placeholder="请输入用户UID"
+              allow-clear
+            />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="角色ID" field="role_id">
+            <a-input
+              v-model="searchForm.role_id"
+              placeholder="请输入角色ID"
+              allow-clear
+            />
+          </a-form-item>
+        </a-col>
+        <a-col :sm="8" :xs="24">
+          <a-form-item label="角色名" field="role_name">
+            <a-input
+              v-model="searchForm.role_name"
+              placeholder="请输入角色名"
+              allow-clear
+            />
+          </a-form-item>
+        </a-col>
+      </template>
+
+      <!-- Table 自定义渲染 -->
+      <template #game_id="{ record }">
+        <span>[{{ record.game_id }}] {{ record.game_name }}</span>
+      </template>
+      <template #media_id="{ record }">
+        <span>[{{ record.media_id }}] {{ record.media_name }}</span>
+      </template>
+      <template #agent_id="{ record }">
+        <span>[{{ record.agent_id }}] {{ record.agent_name }}</span>
+      </template>
+      <template #site_id="{ record }">
+        <span>[{{ record.site_id }}] {{ record.site_name }}</span>
+      </template>
+    </sa-table>
+
+    <!-- 编辑表单 -->
+    <edit-form ref="editRef" @success="refresh" />
+  </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from "vue";
+import { Message } from "@arco-design/web-vue";
+import EditForm from "./edit.vue";
+import api from "../../api/customer/roleData";
+import commonApi from "../../api/common";
+
+// 引用定义
+const crudRef = ref();
+const editRef = ref();
+const viewRef = ref();
+const allGameOptions = ref([]);
+
+// 搜索表单
+const searchForm = ref({
+  game_id: "",
+  user_name: "",
+  uid: "",
+  role_id: "",
+  role_name: "",
+});
+
+// SaTable 基础配置
+const options = reactive({
+  api: api.getPageList,
+  rowSelection: { showCheckedAll: true },
+
+  edit: {
+    show: true,
+    auth: ["/v1/customer/RoleData/update"],
+    func: async (record) => {
+      editRef.value?.open("edit");
+      editRef.value?.setFormData(record);
+    },
+  },
+});
+
+// SaTable 列配置
+const columns = reactive([
+  {
+    title: "游戏",
+    dataIndex: "game_id",
+    width: 180,
+  },
+  { title: "用户名", dataIndex: "user_name", width: 180 },
+  { title: "用户UID", dataIndex: "uid", width: 180 },
+  { title: "服务器名", dataIndex: "server_name", width: 180 },
+  { title: "角色ID", dataIndex: "role_id", width: 180 },
+  { title: "角色名", dataIndex: "role_name", width: 180 },
+  { title: "累计充值", dataIndex: "total_recharge", width: 180 },
+  { title: "媒体ID", dataIndex: "media_id", width: 180 },
+  { title: "渠道ID", dataIndex: "agent_id", width: 180 },
+  { title: "广告位ID", dataIndex: "site_id", width: 180 },
+  { title: "注册IP地址", dataIndex: "ip", width: 180 },
+  { title: "账号最后登录时间", dataIndex: "login_time", width: 220 },
+  { title: "角色最后充值时间", dataIndex: "last_recharge_time", width: 220 },
+  { title: "角色创建时间", dataIndex: "create_time", width: 180 },
+]);
+
+// 页面数据初始化
+const initPage = async () => {
+  await getGameOptions();
+};
+
+// 获取子游戏options
+const getGameOptions = async () => {
+  const res = await commonApi.getGameOptionsApiNoAuth();
+  allGameOptions.value = res.data;
+};
+
+// SaTable 数据请求
+const refresh = async () => {
+  crudRef.value?.refresh();
+};
+
+// 页面加载完成执行
+onMounted(async () => {
+  initPage();
+  refresh();
+});
+</script>