Преглед изворни кода

perf(组件): 优化下拉表格组件-SmartPulldownTable

shizhongming пре 2 година
родитељ
комит
64dbb38f4d

+ 1 - 0
src/components/Form/src/helper.ts

@@ -95,6 +95,7 @@ export const NO_AUTO_LINK_COMPONENTS: ComponentType[] = [
   'ImageUpload',
   'ApiSelect',
   'SmartApiSelectDict',
+  'SmartPulldownTable',
 ];
 
 export const simpleComponents = ['Divider', 'BasicTitle'];

+ 63 - 17
src/components/Form/src/smart-boot/components/SmartPulldownTable.tsx

@@ -1,10 +1,11 @@
-import { computed, defineComponent, ref, toRefs, unref, watch } from 'vue';
+import { computed, defineComponent, nextTick, onMounted, ref, toRefs, unref, watch } from 'vue';
 import { SmartTableProps, SmartTable } from '@/components/SmartTable';
 import { propTypes } from '@/utils/propTypes';
 import { type VxePulldownInstance, VxeGridInstance } from 'vxe-table';
 import { Icon } from '@/components/Icon';
 
 import './style/SmartPullownTable.less';
+import { useRuleFormItem } from '@/hooks/component/useFormItem';
 
 /**
  * 下拉表格
@@ -22,11 +23,18 @@ export default defineComponent({
     valueField: propTypes.string.isRequired,
     // 是否每次都加载
     alwaysLoad: propTypes.bool.def(false),
+    // 是否立即加载
+    immediate: propTypes.bool.def(true),
+    api: {
+      type: Function as PropType<() => Promise<any>>,
+    },
   },
-  emits: ['select', 'change'],
+  emits: ['select', 'change', 'update:value'],
   setup(props, { emit, slots, attrs }) {
     const { showField, dropdownWidth, value: valueRef } = toRefs(props);
     const pulldownRef = ref<VxePulldownInstance>();
+    const dataLoadingRef = ref<boolean>(false);
+    const tableDataRef = ref<Recordable[]>([]);
     const tableRef = ref();
     // 选中的行
     const selectRowRef = ref<Recordable | null>(null);
@@ -45,6 +53,34 @@ export default defineComponent({
       return selectRow[showFieldValue];
     });
 
+    /**
+     * 加载表格数据函数
+     */
+    const loadTableData = async () => {
+      if (props.api) {
+        try {
+          dataLoadingRef.value = true;
+          tableDataRef.value = await props.api();
+        } finally {
+          dataLoadingRef.value = false;
+        }
+      }
+    };
+    onMounted(async () => {
+      if (props.immediate) {
+        await loadTableData();
+      }
+    });
+
+    const emitData = ref<Recordable[]>([]);
+    const [state] = useRuleFormItem(props, 'value', 'change', emitData);
+    watch(
+      () => state.value,
+      (v) => {
+        emit('update:value', v);
+      },
+    );
+
     /**
      * 下拉容器样式
      */
@@ -54,22 +90,22 @@ export default defineComponent({
       };
     });
 
-    watch(valueRef, (value) => {
+    watch([valueRef, tableDataRef], ([value, tableData]) => {
       const tableInstance: VxeGridInstance = unref(tableRef)?.tableAction.getTableInstance();
-      let row = null;
-      if (!tableInstance) {
-        return false;
-      }
+      let row: Recordable | null = null;
       if (!value) {
-        tableInstance.clearCurrentRow();
+        tableInstance && tableInstance.clearCurrentRow();
+        selectRowRef.value = null;
+        return;
       }
-      const fullData = tableInstance.getTableData().fullData;
-      const selectRows = fullData.filter((item) => item[props.valueField] === value);
+      const selectRows = tableData.filter(
+        (item) => item[props.valueField].toString() === value.toString(),
+      );
       if (selectRows.length === 0) {
-        tableInstance.clearCurrentRow();
+        tableInstance && tableInstance.clearCurrentRow();
       } else {
         row = selectRows[0];
-        tableInstance.setCurrentRow(selectRows[0]);
+        tableInstance && tableInstance.setCurrentRow(selectRows[0]);
       }
       selectRowRef.value = row;
     });
@@ -77,11 +113,16 @@ export default defineComponent({
     /**
      * 显示弹窗
      */
-    const handleShow = () => {
+    const handleShow = async () => {
       unref(pulldownRef)?.showPanel();
       if (props.alwaysLoad) {
-        unref(tableRef)?.tableAction.query();
+        await loadTableData();
       }
+      nextTick(() => {
+        const tableInstance: VxeGridInstance = unref(tableRef)?.tableAction.getTableInstance();
+        const row = unref(selectRowRef);
+        row && tableInstance && tableInstance.setCurrentRow(row);
+      });
     };
 
     const dropdownTableProps = {
@@ -92,14 +133,19 @@ export default defineComponent({
         isCurrent: true,
       },
       onCellClick: ({ row }) => {
-        emit('select', row);
-        emit('change', row[props.valueField]);
+        changeValue(row);
         unref(pulldownRef)?.hidePanel();
       },
     };
 
+    const changeValue = (row?: Recordable) => {
+      emit('select', row);
+      state.value = row?.[props.valueField];
+    };
+
     const inputIconSlots = {
       addonAfter: () => <Icon onClick={handleShow} icon="ant-design:table-outlined" />,
+      clearIcon: () => <Icon onClick={() => changeValue()} icon="ant-design:close-circle-filled" />,
     };
 
     const pulldownSlots = {
@@ -110,7 +156,7 @@ export default defineComponent({
       ),
       dropdown: () => (
         <div style={unref(computedDropdownContainerStyle)}>
-          <SmartTable ref={tableRef} {...dropdownTableProps} />
+          <SmartTable data={unref(tableDataRef)} ref={tableRef} {...dropdownTableProps} />
         </div>
       ),
       ...slots,