Преглед на файлове

feat: 指标数据开发中

haifeng.zhang преди 1 месец
родител
ревизия
d52a1d3f05

+ 19 - 0
src/routerList/index.ts

@@ -1,3 +1,11 @@
+/*
+ * @Author: zhanghaifeng
+ * @Date: 2024-11-27 15:44:12
+ * @LastEditors: zhanghaifeng
+ * @LastEditTime: 2025-01-03 14:05:55
+ * @Description:
+ * @FilePath: /hospital-project/src/routerList/index.ts
+ */
 // 最简代码,也就是这些字段必须有
 import server from "@/assets/icon-png/menuList/server (1).svg";
 import menuIndex from "@/assets/svg/layers.svg?component";
@@ -28,6 +36,17 @@ export default {
             // 是否继承父菜单显示,默认false
             showParent: true
           }
+        },
+        {
+          path: "/indexData/index",
+          name: "IndexData",
+          component: () => import("@/views/indexData/index.vue"),
+          meta: {
+            auths: [],
+            title: "指标数据",
+            // 是否继承父菜单显示,默认false
+            showParent: true
+          }
         }
       ]
     }

+ 12 - 0
src/views/background/framework/roles/rolePower.vue

@@ -96,6 +96,18 @@ const postPageRoleApi = async () => {
 // 查看角色组
 const bgColor = ref(null);
 onMounted(async () => {
+  // 用来手动调用接口新增权限
+  // postAddMenuList({
+  //   menuName: "指标数据",
+  //   menuType: "menu",
+  //   parentCode: "menu340262294435012608",
+  //   orderNum: 1,
+  //   url: "",
+  //   moduleUrl: "/indexData/index",
+  //   icon: "",
+  //   remar: "",
+  //   menuCode: ""
+  // });
   // 低网模式 等待 postPageRoleApi 完成
   await postPageRoleApi();
   // setTimeout(() => {

+ 183 - 0
src/views/indexData/components/addDialog.vue

@@ -0,0 +1,183 @@
+<script setup lang="ts">
+import { reactive, ref, onMounted } from "vue";
+import { ElMessage } from "element-plus";
+import { addQuota, getQuotaSourceList } from "@/api/indexDefine";
+import {
+  getSelectDictListtApi,
+  select,
+  getFromSelectDictListtApi
+} from "@/api/select";
+const emit = defineEmits(["closeDialog"]);
+const visible = ref(false);
+const ruleFormRef = ref(null);
+const form = reactive({
+  name: "",
+  categoryName: "",
+  define: "",
+  caliber: "",
+  source: "",
+  statue: null
+});
+const sourceDataList = ref([]);
+const getQuotaSourceListApi = async () => {
+  const { data, code } = await getQuotaSourceList();
+  console.log("1112132", data);
+  if (code == 200) {
+    sourceDataList.value = data;
+  }
+};
+onMounted(() => {
+  getQuotaSourceListApi();
+  getSelectDictListtApi();
+  getFromSelectDictListtApi();
+});
+const msgName = ref("");
+const addQuotaApi = async () => {
+  ruleFormRef.value.validate(async (valid: boolean) => {
+    if (valid) {
+      const { code, msg } = await addQuota(form);
+      if (code === 200) {
+        ElMessage({
+          message: "添加成功",
+          type: "success"
+        });
+        close(ruleFormRef.value);
+      }
+      if (code === 10027) {
+        msgName.value = msg;
+      }
+    }
+  });
+};
+const rules = reactive({
+  name: [{ required: true, message: "请填写指标名称", trigger: "blur" }],
+  define: [{ required: true, message: "请填写指标分类", trigger: "blur" }],
+  categoryName: [
+    { required: true, message: "请填写指标定义", trigger: "blur" }
+  ],
+  caliber: [{ required: true, message: "请填写指标口径", trigger: "blur" }],
+  source: [{ required: true, message: "来源", trigger: "blur" }],
+  statue: [{ required: true, message: "请填写选择状态", trigger: "blur" }]
+});
+const close = (formEl: FormInstance | undefined) => {
+  visible.value = false;
+  formEl.resetFields();
+  emit("closeDialog");
+};
+const save = () => {
+  addQuotaApi();
+};
+const open = () => {
+  console.log(1111);
+  getQuotaSourceListApi();
+  // 打开弹框
+  Object.assign(form, {
+    name: "",
+    categoryName: "",
+    define: "",
+    caliber: "",
+    source: "",
+    statue: null
+  });
+  msgName.value = "";
+  visible.value = true;
+};
+defineExpose({
+  open
+});
+const handleClose = (done: () => void) => {
+  close(ruleFormRef.value);
+  done();
+};
+</script>
+
+<template>
+  <el-dialog
+    v-model="visible"
+    title="新建指标"
+    width="480"
+    :close-on-click-modal="false"
+    :before-close="handleClose"
+  >
+    <div class="m-auto w-full">
+      <el-form
+        ref="ruleFormRef"
+        :model="form"
+        label-position="right"
+        label-width="auto"
+        :rules="rules"
+        style="max-width: 600px"
+      >
+        <el-form-item label="指标名称" prop="name">
+          <el-input
+            v-model="form.name"
+            autocomplete="off"
+            placeholder="请输入"
+          />
+          <el-text v-if="msgName" class="absolute top-6 msgName" type="warning">
+            指标名称已存在,请更换一个名称
+          </el-text>
+        </el-form-item>
+        <el-form-item label="指标分类">
+          <el-select
+            v-model="form.categoryName"
+            filterable
+            placeholder="请选择"
+          >
+            <el-option
+              v-for="(item, index) in select"
+              :key="index"
+              :label="item.dictValue"
+              :value="item.dictValue"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="指标定义" prop="define">
+          <el-input
+            v-model="form.define"
+            type="textarea"
+            autocomplete="off"
+            placeholder="请输入"
+          />
+        </el-form-item>
+        <el-form-item label="指标口径" prop="caliber">
+          <el-input
+            v-model="form.caliber"
+            type="textarea"
+            autocomplete="off"
+            placeholder="请输入"
+          />
+        </el-form-item>
+        <el-form-item label="来源">
+          <el-select v-model="form.source" placeholder="请选择" clearable>
+            <el-option
+              v-for="item in sourceDataList"
+              :key="item.id"
+              :label="item.sourceValue"
+              :value="item.sourceValue"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="状态" prop="statue">
+          <el-select v-model="form.statue" placeholder="请选择">
+            <el-option label="草稿" value="0" />
+            <el-option label="上架" value="1" />
+            <el-option label="下架" value="2" />
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </div>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="close(ruleFormRef)">取消</el-button>
+        <el-button type="primary" @click="save">保存</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<style lang="scss" scope>
+.msgName {
+  font-size: 10px;
+}
+</style>

+ 196 - 0
src/views/indexData/components/editDrawer.vue

@@ -0,0 +1,196 @@
+<script setup lang="ts">
+import { ref, reactive, onMounted } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import type { DrawerProps, FormItemProps, FormProps } from "element-plus";
+import { postUpdateDept, getQuotaSourceList } from "@/api/indexDefine";
+import {
+  getSelectDictListtApi,
+  select,
+  getFromSelectDictListtApi
+} from "@/api/select";
+const emit = defineEmits(["closeEditDialog"]);
+const formRef = ref();
+const drawer = ref(false);
+const disabledShow = ref<any>(true);
+onMounted(() => {
+  getSelectDictListtApi();
+  getFromSelectDictListtApi();
+});
+const direction = ref<DrawerProps["direction"]>("rtl");
+const formLabelAlign = reactive({
+  id: "",
+  name: "",
+  categoryName: "",
+  define: "",
+  caliber: "",
+  source: "",
+  statue: null
+});
+const rules = reactive<FormProps["rules"]>({
+  name: [{ required: true, message: "请输入指标名称", trigger: "blur" }],
+  define: { required: true, message: "请输入指标定义", trigger: "blur" },
+  caliber: { required: true, message: "请输入指标口径", trigger: "blur" },
+  statue: { required: true, message: "请选择指标状态", trigger: "blur" }
+});
+const handleClose = (done: () => void) => {
+  if (disabledShow.value) {
+    disabledShow.value = true;
+    drawer.value = false;
+  } else {
+    ElMessageBox.confirm("配置项未保存,确认关闭", {
+      type: "warning"
+    }).then(() => {
+      formRef.value.clearValidate(); // 清除验证错误
+      formRef.value.resetFields(); // 重置表单字段
+      disabledShow.value = true;
+      drawer.value = false;
+    });
+  }
+};
+function cancelClick() {
+  formRef.value.validate(valid => {
+    if (valid) {
+      disabledShow.value = true;
+    }
+  });
+}
+// 确认
+const postUpdateDeptApi = async () => {
+  const { code, msg } = await postUpdateDept(formLabelAlign);
+  if (code === 200) {
+    ElMessage({
+      message: "修改成功",
+      type: "success"
+    });
+    disabledShow.value = true;
+    drawer.value = false;
+    emit("closeEditDialog");
+  } else {
+    ElMessage.error(msg);
+  }
+};
+function confirmClick() {
+  formRef.value.validate(valid => {
+    if (valid) {
+      postUpdateDeptApi();
+    }
+  });
+}
+const open = row => {
+  Object.assign(formLabelAlign, row);
+  getQuotaSourceListApi();
+  drawer.value = true;
+};
+// 编辑
+const editClick = () => {
+  disabledShow.value = false;
+};
+// 来源
+const sourceDataList = ref([]);
+const getQuotaSourceListApi = async () => {
+  const { data, code } = await getQuotaSourceList();
+  console.log("1112132", data);
+  if (code == 200) {
+    sourceDataList.value = data;
+  }
+};
+defineExpose({
+  open
+});
+</script>
+
+<template>
+  <div>
+    <el-drawer
+      v-model="drawer"
+      :direction="direction"
+      :before-close="handleClose"
+    >
+      <template #header>
+        <h4>指标详情</h4>
+      </template>
+      <template #default>
+        <div>
+          <el-form
+            ref="formRef"
+            label-position="top"
+            label-width="auto"
+            :rules="rules"
+            :model="formLabelAlign"
+          >
+            <el-form-item label="指标名称" label-position="top" prop="name">
+              <el-input
+                v-model="formLabelAlign.name"
+                :disabled="disabledShow"
+              />
+            </el-form-item>
+            <el-form-item label="指标分类" label-position="top">
+              <el-select
+                :key="formLabelAlign.categoryName"
+                v-model="formLabelAlign.categoryName"
+                :disabled="disabledShow"
+                placeholder="请选择状态"
+              >
+                <el-option
+                  v-for="(item, index) in select"
+                  :key="index"
+                  :label="item.dictValue"
+                  :value="item.dictValue"
+                />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="指标定义" label-position="top" prop="define">
+              <el-input
+                v-model="formLabelAlign.define"
+                :disabled="disabledShow"
+                type="textarea"
+              />
+            </el-form-item>
+            <el-form-item label="指标口径" label-position="top" prop="caliber">
+              <el-input
+                v-model="formLabelAlign.caliber"
+                :disabled="disabledShow"
+                type="textarea"
+              />
+            </el-form-item>
+            <el-form-item label="来源" label-position="top">
+              <el-select
+                v-model="formLabelAlign.source"
+                :disabled="disabledShow"
+                clearable
+                placeholder="请选择来源"
+              >
+                <el-option
+                  v-for="item in sourceDataList"
+                  :key="item.id"
+                  :label="item.sourceValue"
+                  :value="item.sourceValue"
+              /></el-select>
+            </el-form-item>
+            <el-form-item label="状态" label-position="top" prop="statue">
+              <el-select
+                :key="formLabelAlign.statue"
+                v-model="formLabelAlign.statue"
+                :disabled="disabledShow"
+                placeholder="请选择状态"
+              >
+                <el-option label="草稿" :value="0" />
+                <el-option label="发布" :value="1" />
+                <el-option label="下架" :value="2" />
+              </el-select>
+            </el-form-item>
+          </el-form>
+        </div>
+      </template>
+      <template #footer>
+        <el-button v-if="disabledShow" type="warning" @click="editClick"
+          >编辑</el-button
+        >
+        <div v-else>
+          <el-button @click="cancelClick">取消</el-button>
+          <el-button type="primary" @click="confirmClick">确认</el-button>
+        </div>
+      </template>
+    </el-drawer>
+  </div>
+</template>

+ 163 - 0
src/views/indexData/components/indexImport.vue

@@ -0,0 +1,163 @@
+<script setup lang="ts">
+defineOptions({
+  name: "IndexDefineImport"
+});
+import { ref } from "vue";
+import { postUpdateDeptApi, getListTable } from "@/api/download";
+import { ElMessage } from "element-plus";
+import { useRouter } from "vue-router";
+const $router = useRouter();
+const emit = defineEmits(["handleImport"]);
+const uploadShow = ref(true);
+const fileDocument = ref<File | null>(null); // 存储文件
+const backupUrl =
+  import.meta.env.VITE_BACKUP_URL + "/download/指标导入模板.xlsx";
+// 上传文件函数
+// 上传文件函数
+const uploadFile = async () => {
+  if (!fileDocument.value) {
+    ElMessage.error("请先上传文件");
+    return;
+  }
+
+  try {
+    const formData = new FormData();
+    // 将生成的文件添加到 FormData 中
+    formData.append("file", fileDocument.value);
+    // 获取文件并执行上传
+    const fileToSend = formData.get("file");
+    // 调用 API 上传文件
+    const { data } = await postUpdateDeptApi({ file: fileToSend });
+    // const { data } = await postUpdateDeptApi({ file: formData });
+    if (data.code === 200) {
+      // 根据后端返回的 code 判断是否成功
+      ElMessage.success("文件上传并导入成功");
+      // 重置上传状态
+      backDefine();
+      $router.push("/indexDefine/children/define");
+      tableHeaders.value = []; // 清空表头
+    } else {
+      ElMessage.error(data.msg);
+    }
+  } catch (error) {
+    ElMessage.error("上传失败,请重试");
+    console.error(error);
+  }
+};
+
+const tableHeaders = ref<any>([]);
+const tableData = ref<any>([]);
+
+const backDefine = () => {
+  emit("handleImport");
+};
+
+// 处理文件上传并解析 Excel 内容
+const handleUploadChange = async (file: File) => {
+  fileDocument.value = file; // 保存文件
+  const reader = new FileReader();
+  let fileType = file.name.slice(-4);
+  if (fileType == "xlsx") {
+    const formData = new FormData();
+    formData.append("file", fileDocument.value); // 将文件添加到表单数据
+    // 调用 API 上传文件
+    const { data } = await getListTable(formData);
+    if (data.code === 200) {
+      tableData.value = data.data;
+    }
+    uploadShow.value = false; // 隐藏上传区域,显示数据表
+  } else {
+    ElMessage.error("请上传xlsx文件");
+  }
+
+  reader.readAsArrayBuffer(file); // 读取文件为 ArrayBuffer
+};
+
+const stateDone = state => {
+  const arr = ["草稿", "发布", "下架"];
+  return arr[state];
+};
+</script>
+
+<template>
+  <div>
+    <div class="w-3/4 m-auto mt-4">
+      <div class="w-full bg p-3">
+        <h5>1.下载导入模板</h5>
+        <p class="text-xs mt-2 text">根据提升信息完善表格内容</p>
+        <el-button class="mt-2">
+          <el-icon> <Download /> </el-icon
+          ><a :href="backupUrl" download="指标导入模板.xlsx"
+            >下载空的模板表格</a
+          >
+        </el-button>
+      </div>
+      <div class="w-full mt-4 bg p-3">
+        <h5>2.上传完善后的模板</h5>
+        <p class="text-xs mt-2 text mb-2">
+          更新信息的模板中,如有空的数据列,则相应字段信息会被清空,请谨慎填写
+        </p>
+        <div v-if="uploadShow">
+          <el-upload
+            class="upload-demo"
+            drag
+            multiple
+            :before-upload="file => handleUploadChange(file)"
+            :show-file-list="false"
+          >
+            <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+            <div class="el-upload__text">
+              点击<em>图标选择上传</em>或者将文件拖拽到此区域
+            </div>
+          </el-upload>
+        </div>
+        <div v-else class="mb-2">
+          <el-table
+            :data="tableData"
+            border
+            style="width: 100%"
+            max-height="250"
+          >
+            <el-table-column prop="name" label="指标名称" />
+            <el-table-column prop="define" label="指标定义" />
+            <el-table-column prop="caliber" label="指标口径" />
+            <el-table-column prop="categoryName" label="指标分类" />
+            <el-table-column prop="source" label="来源" />
+            <el-table-column prop="statue" label="状态">
+              <template #default="scope">
+                {{ stateDone(scope.row.statue) }}
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+        <div class="float-right">
+          <el-button @click="backDefine">取消</el-button>
+          <el-button type="primary" @click="uploadFile">确认</el-button>
+        </div>
+        <p class="h-11 no-select">.</p>
+      </div>
+    </div>
+  </div>
+</template>
+<style lang="scss" scoped>
+.bg {
+  background-color: #f8f9fa;
+}
+
+.text {
+  color: #999;
+}
+
+.upoload {
+  float: right;
+}
+
+.no-select {
+  color: rgb(255 255 255 / 0%);
+  user-select: none;
+}
+
+.float-right {
+  margin-top: 10px;
+}
+</style>

+ 82 - 0
src/views/indexData/components/logDrawer.vue

@@ -0,0 +1,82 @@
+<!--
+ * @Author: zhanghaifeng
+ * @Date: 2025-01-03 16:46:09
+ * @LastEditors: zhanghaifeng
+ * @LastEditTime: 2025-01-03 17:10:33
+ * @Description:
+ * @FilePath: /hospital-project/src/views/indexData/components/logDrawer.vue
+-->
+<script setup lang="ts">
+import { ref } from "vue";
+import type { DrawerProps } from "element-plus";
+import { getQuotaLogInfo } from "@/api/indexDefine";
+import dayjs from "dayjs";
+const drawer = ref(false);
+const quotaId = ref();
+const direction = ref<DrawerProps["direction"]>("rtl");
+const logList = ref([]);
+const getQuotaLogInfoApi = async () => {
+  const { code, data } = await getQuotaLogInfo(quotaId.value);
+  console.log(data);
+  if (code === 200) {
+    logList.value = data;
+  }
+};
+function cancelClick() {
+  drawer.value = false;
+}
+const open = row => {
+  quotaId.value = row.id;
+  getQuotaLogInfoApi();
+  drawer.value = true;
+};
+defineExpose({
+  open
+});
+</script>
+
+<template>
+  <div>
+    <el-drawer v-model="drawer" :direction="direction">
+      <template #header>
+        <h4>指标日志</h4>
+      </template>
+      <template #default>
+        <div>
+          <div v-for="(item, index) in logList" :key="index" class="w-full">
+            <div>
+              <el-text class="font-semibold">操作用户</el-text>
+              <div
+                class="bg-gray-100 pl-3 pb-2 pt-2 rounded text-sm text-gray-500"
+              >
+                {{ item.updateUser }}
+              </div>
+            </div>
+            <div class="mt-4">
+              <el-text class="font-semibold">更新时间</el-text>
+              <div
+                class="bg-gray-100 pl-3 pb-2 pt-2 rounded text-sm text-gray-500"
+              >
+                {{ dayjs(item.updateTime).format("YYYY-MM-DD HH:mm:ss") }}
+              </div>
+            </div>
+            <div class="mt-4">
+              <el-text class="font-semibold">更新内容</el-text>
+              <div
+                class="bg-gray-100 pl-3 pr-3 pb-2 pt-2 rounded text-sm text-gray-500"
+              >
+                {{ item.updateContent }}
+              </div>
+              <el-divider />
+            </div>
+          </div>
+        </div>
+      </template>
+      <template #footer>
+        <div>
+          <el-button @click="cancelClick">关闭</el-button>
+        </div>
+      </template>
+    </el-drawer>
+  </div>
+</template>

+ 222 - 0
src/views/indexData/index.vue

@@ -0,0 +1,222 @@
+<!--
+ * @Author: zhanghaifeng
+ * @Date: 2025-01-03 13:57:58
+ * @LastEditors: zhanghaifeng
+ * @LastEditTime: 2025-01-03 17:13:59
+ * @Description: 指标数据
+ * @FilePath: /hospital-project/src/views/indexData/index.vue
+-->
+<script setup>
+defineOptions({
+  name: "IndexData"
+});
+import { ref, reactive, onMounted } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import dayjs from "dayjs";
+import IndexImport from "./components/indexImport.vue";
+import addDialog from "./components/addDialog.vue";
+import editDrawer from "./components/editDrawer.vue";
+import logDrawer from "./components/logDrawer.vue";
+
+// 状态
+const params = reactive({
+  params: {
+    pageNumber: 1,
+    pageSize: 10,
+    param: ""
+  },
+  records: [],
+  total: 0
+});
+
+// 获取列表数据
+const getList = async () => {
+  // const { code, data } = await getQuotaPageList(params.params);
+  // if (code === 200) {
+  //   params.records = data.records;
+  //   params.total = data.totalRow;
+  // }
+};
+const handleSizeChange = val => {
+  params.params.pageSize = val;
+  getList();
+};
+const handleCurrentChange = val => {
+  params.params.pageNumber = val;
+  getList();
+};
+onMounted(() => {
+  getList();
+});
+
+// 批量导入
+const sizeImport = ref(false);
+const bulkImport = () => {
+  sizeImport.value = !sizeImport.value;
+};
+
+// 添加
+const dialogShow = ref(null);
+const showAddData = () => {
+  dialogShow.value && dialogShow.value.open();
+};
+
+// 编辑/详情
+const editdrawerShow = ref(null);
+const setEdit = row => {
+  editdrawerShow.value && editdrawerShow.value.open(row);
+};
+
+// 日志
+const logDrawerRef = ref(null);
+const showLogs = row => {
+  logDrawerRef.value && logDrawerRef.value.open(row);
+};
+</script>
+
+<template>
+  <div class="page-container">
+    <!-- 批量导入 -->
+    <IndexImport v-if="sizeImport" @handleImport="bulkImport" />
+    <div v-else>
+      <div class="w-[100%]">
+        <div class="mb-2 flex gap-2 justify-between flex-wrap">
+          <div class="flex mt-2">
+            <div class="flex mr-2">
+              <el-input
+                v-model="params.params.param"
+                style="width: 500px"
+                :prefix-icon="Search"
+                clearable
+                placeholder="搜索指标名称、部门、员工"
+                @change="getList"
+              />
+            </div>
+          </div>
+          <div class="flex pt-2 mr-6">
+            <el-button class="mr-2" @click="bulkImport">批量导入</el-button>
+            <el-button type="primary" class="mr-2" @click="showAddData">
+              添加数据
+            </el-button>
+          </div>
+        </div>
+      </div>
+      <div class="mt-8">
+        <el-table :data="params.records" style="z-index: 0; width: 100%">
+          <el-table-column
+            prop="name"
+            label="指标名称"
+            show-overflow-tooltip
+            fixed="left"
+          />
+          <el-table-column
+            prop="deptName"
+            label="部门名称"
+            show-overflow-tooltip
+          />
+          <el-table-column prop="userName" label="员工名称" />
+          <el-table-column prop="hospitalCode" label="工号" />
+          <el-table-column prop="molecule" label="分子" />
+          <el-table-column prop="denominator" label="分母" />
+          <el-table-column prop="value" label="值" />
+          <el-table-column prop="dataTime" label="数据时间">
+            <template #default="{ row }">
+              {{
+                row.dataTime
+                  ? dayjs(row.dataTime).format("YYYY-MM-DD HH:mm:ss")
+                  : "无效日期"
+              }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="updateTime" label="更新时间">
+            <template #default="{ row }">
+              {{
+                row.updateTime
+                  ? dayjs(row.updateTime).format("YYYY-MM-DD HH:mm:ss")
+                  : "无效日期"
+              }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="creator" label="创建人" />
+          <el-table-column label="操作">
+            <template #default="{ row }">
+              <el-dropdown trigger="click">
+                <span class="el-dropdown-link navbar-bg-hover select-none pt-1">
+                  <el-icon @click="setEdit(row)">
+                    <Edit />
+                  </el-icon>
+                </span>
+              </el-dropdown>
+              <el-dropdown class="ml-2" trigger="click">
+                <span class="el-dropdown-link navbar-bg-hover select-none pt-1">
+                  <el-icon>
+                    <More />
+                  </el-icon>
+                </span>
+                <template #dropdown>
+                  <el-dropdown-menu class="setting">
+                    <el-dropdown-item @click="setDelete(row)">
+                      <el-text type="danger">删除</el-text>
+                    </el-dropdown-item>
+                    <el-dropdown-item @click="showLogs(row)"
+                      >日志</el-dropdown-item
+                    >
+                  </el-dropdown-menu>
+                </template>
+              </el-dropdown>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="flex justify-between item-center">
+        <div class="float-left mt-5 ml-2 total">共{{ params.total }}条数据</div>
+        <div class="float-right mt-5 mr-8">
+          <el-pagination
+            v-model:current-page="params.params.pageNumber"
+            v-model:page-size="params.params.pageSize"
+            background
+            layout="prev, pager, next"
+            :total="params.total"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+          />
+        </div>
+      </div>
+      <!-- 编辑/详情 -->
+      <editDrawer ref="editdrawerShow" @closeEditDialog="getList" />
+      <!-- 新建 -->
+      <addDialog ref="dialogShow" @closeDialog="getList" />
+      <!-- 日志 -->
+      <logDrawer ref="logDrawerRef" />
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.total {
+  font-size: 14px;
+  font-weight: 400;
+  line-height: 22px;
+  color: #0009;
+  letter-spacing: 0;
+}
+
+.header {
+  display: flex;
+  width: 100%;
+  line-height: 100%;
+  border: 1px solid red;
+}
+
+::v-deep .el-table .el-table__header th {
+  background-color: #f2f3f5;
+}
+
+::v-deep .el-table .el-table__cell {
+  z-index: 99;
+}
+
+.setting {
+  font-size: 12px;
+}
+</style>