Procházet zdrojové kódy

perf: 优化岗位管理demo

xiaoxian521 před 3 roky
rodič
revize
dc219ed11a

+ 4 - 0
src/plugins/element-plus/index.ts

@@ -57,6 +57,8 @@ import {
   ElTree,
   ElTreeV2,
   ElPopconfirm,
+  ElCheckbox,
+  ElCheckboxGroup,
   // 指令
   ElLoading,
   ElInfiniteScroll
@@ -112,6 +114,8 @@ const components = [
   ElTree,
   ElTreeV2,
   ElPopconfirm,
+  ElCheckbox,
+  ElCheckboxGroup,
   ElTable,
   ElTableColumn,
   ElLink,

+ 153 - 57
src/views/system/job/index.vue

@@ -6,9 +6,11 @@ export default {
 
 <script setup lang="ts">
 import dayjs from "dayjs";
+import { loadingSvg } from "./load";
 import { getJobList } from "/@/api/system";
 import { FormInstance } from "element-plus";
 import { Switch } from "@pureadmin/components";
+import { successMessage } from "/@/utils/message";
 import { reactive, ref, onMounted, computed } from "vue";
 import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
 import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
@@ -18,19 +20,19 @@ const form = reactive({
   user: "",
   status: ""
 });
+const buttonRef = ref();
+const tooltipRef = ref();
 let jobList = ref([]);
-let loading = ref(false);
-const totalPage = ref(0);
 let pageSize = ref(10);
+let totalPage = ref(0);
+let checkList = ref([]);
+let loading = ref(true);
+let visible = ref(false);
 let size = ref("default");
+let switchLoadMap = ref({});
 
 const formRef = ref<FormInstance>();
 
-const resetForm = (formEl: FormInstance | undefined) => {
-  if (!formEl) return;
-  formEl.resetFields();
-};
-
 const getDropdownItemStyle = computed(() => {
   return s => {
     return {
@@ -56,14 +58,48 @@ function handleSizeChange(val: number) {
   console.log(`${val} items per page`);
 }
 
-function onChange(checked, val) {
-  console.log(checked, val);
+function onCheckChange(val) {
+  console.log("onCheckChange", val);
+}
+
+function handleSelectionChange(val) {
+  console.log("handleSelectionChange", val);
 }
 
-onMounted(async () => {
+function onChange(checked, { $index, row }) {
+  switchLoadMap.value[$index] = Object.assign({}, switchLoadMap.value[$index], {
+    loading: true
+  });
+  setTimeout(() => {
+    switchLoadMap.value[$index] = Object.assign(
+      {},
+      switchLoadMap.value[$index],
+      {
+        loading: false
+      }
+    );
+    successMessage("已成功修改岗位状态");
+  }, 300);
+}
+
+async function onSearch() {
+  loading.value = true;
   let { data } = await getJobList();
   jobList.value = data.list;
   totalPage.value = data.total;
+  setTimeout(() => {
+    loading.value = false;
+  }, 500);
+}
+
+const resetForm = (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  formEl.resetFields();
+  onSearch();
+};
+
+onMounted(() => {
+  onSearch();
 });
 </script>
 
@@ -75,13 +111,13 @@ onMounted(async () => {
       :model="form"
       class="bg-white w-99/100 pl-8 pt-4"
     >
-      <el-form-item label="岗位编码:">
+      <el-form-item label="岗位编码:" prop="code">
         <el-input v-model="form.code" placeholder="请输入" clearable />
       </el-form-item>
-      <el-form-item label="岗位名称:">
+      <el-form-item label="岗位名称:" prop="user">
         <el-input v-model="form.user" placeholder="请输入" clearable />
       </el-form-item>
-      <el-form-item label="状态:">
+      <el-form-item label="状态:" prop="status">
         <el-select v-model="form.status" placeholder="请选择" clearable>
           <el-option label="开启" value="1" />
           <el-option label="关闭" value="0" />
@@ -91,13 +127,23 @@ onMounted(async () => {
         <el-button :icon="useRenderIcon('refresh')" @click="resetForm(formRef)"
           >重置</el-button
         >
-        <el-button type="primary" :icon="useRenderIcon('search')"
-          >搜索</el-button
+        <el-button
+          type="primary"
+          :icon="useRenderIcon('search')"
+          :loading="loading"
+          @click="onSearch"
+        >
+          搜索</el-button
         >
       </el-form-item>
     </el-form>
 
-    <div class="w-99/100 mt-6 pb-4 bg-white">
+    <div
+      class="w-99/100 mt-6 pb-4 bg-white"
+      v-loading="loading"
+      :element-loading-svg="loadingSvg"
+      element-loading-svg-view-box="-10, -10, 50, 50"
+    >
       <div class="flex justify-between w-full h-60px p-4">
         <p class="font-bold">岗位列表</p>
         <div class="w-200px flex items-center justify-around">
@@ -108,59 +154,108 @@ onMounted(async () => {
           <el-button type="warning" :icon="useRenderIcon('export')"
             >导出</el-button
           > -->
-          <IconifyIconOffline
-            class="cursor-pointer"
-            icon="refresh-right"
-            width="20"
-            color="#606266"
-          />
-
-          <el-dropdown id="header-translation" trigger="click">
+          <el-tooltip effect="dark" content="刷新" placement="top">
             <IconifyIconOffline
-              class="cursor-pointer"
-              icon="density"
+              class="cursor-pointer outline-none"
+              icon="refresh-right"
               width="20"
               color="#606266"
+              @click="onSearch"
             />
-            <template #dropdown>
-              <el-dropdown-menu class="translation">
-                <el-dropdown-item
-                  :style="getDropdownItemStyle('large')"
-                  @click="size = 'large'"
-                >
-                  松散
-                </el-dropdown-item>
-                <el-dropdown-item
-                  :style="getDropdownItemStyle('default')"
-                  @click="size = 'default'"
-                >
-                  默认
-                </el-dropdown-item>
-                <el-dropdown-item
-                  :style="getDropdownItemStyle('small')"
-                  @click="size = 'small'"
-                >
-                  紧凑
-                </el-dropdown-item>
-              </el-dropdown-menu>
+          </el-tooltip>
+
+          <el-tooltip effect="dark" content="密度" placement="top">
+            <el-dropdown id="header-translation" trigger="click">
+              <IconifyIconOffline
+                class="cursor-pointer outline-none"
+                icon="density"
+                width="20"
+                color="#606266"
+              />
+              <template #dropdown>
+                <el-dropdown-menu class="translation">
+                  <el-dropdown-item
+                    :style="getDropdownItemStyle('large')"
+                    @click="size = 'large'"
+                  >
+                    松散
+                  </el-dropdown-item>
+                  <el-dropdown-item
+                    :style="getDropdownItemStyle('default')"
+                    @click="size = 'default'"
+                  >
+                    默认
+                  </el-dropdown-item>
+                  <el-dropdown-item
+                    :style="getDropdownItemStyle('small')"
+                    @click="size = 'small'"
+                  >
+                    紧凑
+                  </el-dropdown-item>
+                </el-dropdown-menu>
+              </template>
+            </el-dropdown>
+          </el-tooltip>
+
+          <el-popover :width="200" trigger="click">
+            <template #reference>
+              <IconifyIconOffline
+                class="cursor-pointer outline-none"
+                icon="setting"
+                width="20"
+                color="#606266"
+                @mouseover="e => (buttonRef = e.currentTarget)"
+                @mouseenter="visible = true"
+                @mouseleave="visible = false"
+              />
             </template>
-          </el-dropdown>
-
-          <IconifyIconOffline
-            class="cursor-pointer"
-            icon="setting"
-            width="20"
-            color="#606266"
-          />
+            <el-checkbox-group v-model="checkList" @change="onCheckChange">
+              <el-checkbox label="序号列" />
+              <el-checkbox label="勾选列" />
+            </el-checkbox-group>
+          </el-popover>
         </div>
+
+        <el-tooltip
+          ref="tooltipRef"
+          v-model:visible="visible"
+          :popper-options="{
+            modifiers: [
+              {
+                name: 'computeStyles',
+                options: {
+                  adaptive: false,
+                  enabled: false
+                }
+              }
+            ]
+          }"
+          placement="top"
+          :virtual-ref="buttonRef"
+          virtual-triggering
+          trigger="click"
+          content="列设置"
+        />
       </div>
       <el-table
         border
         :size="size"
-        v-loading="loading"
         :data="jobList"
         :header-cell-style="{ background: '#fafafa', color: '#606266' }"
+        @selection-change="handleSelectionChange"
       >
+        <el-table-column
+          v-if="checkList.includes('勾选列')"
+          type="selection"
+          width="55"
+        />
+        <el-table-column
+          v-if="checkList.includes('序号列')"
+          type="index"
+          label="序号"
+          align="center"
+          width="60"
+        />
         <el-table-column label="岗位编号" align="center" prop="id" />
         <el-table-column label="岗位编码" align="center" prop="code" />
         <el-table-column label="岗位名称" align="center" prop="name" />
@@ -169,12 +264,13 @@ onMounted(async () => {
           <template #default="scope">
             <Switch
               :size="size === 'small' ? 'small' : 'default'"
+              :loading="switchLoadMap[scope.$index]?.loading"
               v-model:checked="scope.row.status"
               :checkedValue="1"
               :unCheckedValue="0"
               checked-children="已开启"
               un-checked-children="已关闭"
-              @change="checked => onChange(checked, scope.row)"
+              @change="checked => onChange(checked, scope)"
             />
           </template>
         </el-table-column>

+ 10 - 0
src/views/system/job/load.ts

@@ -0,0 +1,10 @@
+export const loadingSvg = `
+        <path class="path" d="
+          M 30 15
+          L 28 17
+          M 25.61 25.61
+          A 15 15, 0, 0, 1, 15 30
+          A 15 15, 0, 1, 1, 27.99 7.5
+          L 15 15
+        " style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"/>
+      `;