Przeglądaj źródła

perf(component): optimize tree and upload components

Vben 3 lat temu
rodzic
commit
3f6920f7a9

+ 1 - 1
src/components/Tree/index.ts

@@ -2,4 +2,4 @@ import BasicTree from './src/Tree.vue';
 
 export { BasicTree };
 export type { ContextMenuItem } from '/@/hooks/web/useContextMenu';
-export * from './src/types';
+export * from './src/typing';

+ 2 - 2
src/components/Tree/src/Tree.vue

@@ -1,5 +1,5 @@
 <script lang="tsx">
-  import type { ReplaceFields, Keys, CheckKeys, TreeActionType, TreeItem } from './types';
+  import type { ReplaceFields, Keys, CheckKeys, TreeActionType, TreeItem } from './typing';
 
   import {
     defineComponent,
@@ -30,7 +30,7 @@
   import { basicProps } from './props';
   import { CreateContextOptions } from '/@/components/ContextMenu';
 
-  import { CheckEvent } from './types';
+  import { CheckEvent } from './typing';
 
   interface State {
     expandedKeys: Keys;

+ 8 - 1
src/components/Tree/src/TreeHeader.vue

@@ -43,7 +43,14 @@
   import { useI18n } from '/@/hooks/web/useI18n';
   import { useDebounceFn } from '@vueuse/core';
 
-  import { ToolbarEnum } from './enum';
+  enum ToolbarEnum {
+    SELECT_ALL,
+    UN_SELECT_ALL,
+    EXPAND_ALL,
+    UN_EXPAND_ALL,
+    CHECK_STRICTLY,
+    CHECK_UN_STRICTLY,
+  }
 
   interface MenuInfo {
     key: ToolbarEnum;

+ 0 - 8
src/components/Tree/src/enum.ts

@@ -1,8 +0,0 @@
-export enum ToolbarEnum {
-  SELECT_ALL,
-  UN_SELECT_ALL,
-  EXPAND_ALL,
-  UN_EXPAND_ALL,
-  CHECK_STRICTLY,
-  CHECK_UN_STRICTLY,
-}

+ 1 - 1
src/components/Tree/src/props.ts

@@ -1,5 +1,5 @@
 import type { PropType } from 'vue';
-import type { ReplaceFields, ActionItem, Keys, CheckKeys, ContextMenuOptions } from './types';
+import type { ReplaceFields, ActionItem, Keys, CheckKeys, ContextMenuOptions } from './typing';
 import type { ContextMenuItem } from '/@/hooks/web/useContextMenu';
 import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree';
 import { propTypes } from '/@/utils/propTypes';

+ 0 - 0
src/components/Tree/src/types.ts → src/components/Tree/src/typing.ts


+ 1 - 1
src/components/Tree/src/useTree.ts

@@ -1,4 +1,4 @@
-import type { InsertNodeParams, Keys, ReplaceFields } from './types';
+import type { InsertNodeParams, Keys, ReplaceFields } from './typing';
 import type { Ref, ComputedRef } from 'vue';
 import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree';
 

+ 4 - 1
src/components/Upload/index.ts

@@ -1 +1,4 @@
-export { default as BasicUpload } from './src/BasicUpload.vue';
+import { withInstall } from '/@/utils';
+import basicUpload from './src/BasicUpload.vue';
+
+export const BasicUpload = withInstall(basicUpload);

+ 22 - 19
src/components/Upload/src/BasicUpload.vue

@@ -7,14 +7,14 @@
       <Tooltip placement="bottom" v-if="showPreview">
         <template #title>
           {{ t('component.upload.uploaded') }}
-          <template v-if="fileListRef.length">
-            {{ fileListRef.length }}
+          <template v-if="fileList.length">
+            {{ fileList.length }}
           </template>
         </template>
         <a-button @click="openPreviewModal">
           <Icon icon="bi:eye" />
-          <template v-if="fileListRef.length && showPreviewNumber">
-            {{ fileListRef.length }}
+          <template v-if="fileList.length && showPreviewNumber">
+            {{ fileList.length }}
           </template>
         </a-button>
       </Tooltip>
@@ -22,13 +22,14 @@
 
     <UploadModal
       v-bind="bindValue"
-      :previewFileList="fileListRef"
+      :previewFileList="fileList"
       @register="registerUploadModal"
       @change="handleChange"
+      @delete="handleDelete"
     />
 
     <UploadPreviewModal
-      :value="fileListRef"
+      :value="fileList"
       @register="registerPreviewModal"
       @list-change="handlePreviewChange"
     />
@@ -36,14 +37,11 @@
 </template>
 <script lang="ts">
   import { defineComponent, ref, watch, unref, computed } from 'vue';
-
   import UploadModal from './UploadModal.vue';
   import UploadPreviewModal from './UploadPreviewModal.vue';
-  import Icon from '/@/components/Icon';
+  import { Icon } from '/@/components/Icon';
   import { Tooltip } from 'ant-design-vue';
-
   import { useModal } from '/@/components/Modal';
-
   import { uploadContainerProps } from './props';
   import { omit } from 'lodash-es';
   import { useI18n } from '/@/hooks/web/useI18n';
@@ -52,7 +50,7 @@
     name: 'BasicUpload',
     components: { UploadModal, UploadPreviewModal, Icon, Tooltip },
     props: uploadContainerProps,
-    emits: ['change'],
+    emits: ['change', 'delete'],
 
     setup(props, { emit, attrs }) {
       const { t } = useI18n();
@@ -62,12 +60,12 @@
       //   预览modal
       const [registerPreviewModal, { openModal: openPreviewModal }] = useModal();
 
-      const fileListRef = ref<string[]>([]);
+      const fileList = ref<string[]>([]);
 
       const showPreview = computed(() => {
         const { emptyHidePreview } = props;
         if (!emptyHidePreview) return true;
-        return emptyHidePreview ? fileListRef.value.length > 0 : true;
+        return emptyHidePreview ? fileList.value.length > 0 : true;
       });
 
       const bindValue = computed(() => {
@@ -78,21 +76,25 @@
       watch(
         () => props.value,
         (value = []) => {
-          fileListRef.value = value;
+          fileList.value = value;
         },
         { immediate: true }
       );
 
       // 上传modal保存操作
       function handleChange(urls: string[]) {
-        fileListRef.value = [...unref(fileListRef), ...(urls || [])];
-        emit('change', fileListRef.value);
+        fileList.value = [...unref(fileList), ...(urls || [])];
+        emit('change', fileList.value);
       }
 
       // 预览modal保存操作
       function handlePreviewChange(urls: string[]) {
-        fileListRef.value = [...(urls || [])];
-        emit('change', fileListRef.value);
+        fileList.value = [...(urls || [])];
+        emit('change', fileList.value);
+      }
+
+      function handleDelete(record: Recordable) {
+        emit('delete', record);
       }
 
       return {
@@ -102,9 +104,10 @@
         handlePreviewChange,
         registerPreviewModal,
         openPreviewModal,
-        fileListRef,
+        fileList,
         showPreview,
         bindValue,
+        handleDelete,
         t,
       };
     },

+ 0 - 31
src/components/Upload/src/FileList.less

@@ -1,31 +0,0 @@
-.file-table {
-  width: 100%;
-  border-collapse: collapse;
-
-  .center {
-    text-align: center;
-  }
-
-  .left {
-    text-align: left;
-  }
-
-  .right {
-    text-align: right;
-  }
-
-  &-th,
-  &-td {
-    padding: 12px 8px;
-  }
-
-  thead {
-    background-color: @background-color-light;
-  }
-
-  table,
-  td,
-  th {
-    border: 1px solid @border-color-base;
-  }
-}

+ 0 - 72
src/components/Upload/src/FileList.tsx

@@ -1,72 +0,0 @@
-import { defineComponent, CSSProperties, watch, nextTick } from 'vue';
-import { fileListProps } from './props';
-import { isFunction } from '/@/utils/is';
-import './FileList.less';
-import { useModalContext } from '/@/components/Modal/src/hooks/useModalContext';
-
-export default defineComponent({
-  name: 'FileList',
-  props: fileListProps,
-  setup(props) {
-    const modalFn = useModalContext();
-    watch(
-      () => props.dataSource,
-      () => {
-        nextTick(() => {
-          modalFn?.redoModalHeight?.();
-        });
-      }
-    );
-    return () => {
-      const { columns, actionColumn, dataSource } = props;
-      const columnList = [...columns, actionColumn];
-      return (
-        <table class="file-table">
-          <colgroup>
-            {columnList.map((item) => {
-              const { width = 0, dataIndex } = item;
-
-              const style: CSSProperties = {
-                width: `${width}px`,
-                minWidth: `${width}px`,
-              };
-
-              return <col style={width ? style : {}} key={dataIndex} />;
-            })}
-          </colgroup>
-          <thead>
-            <tr class="file-table-tr">
-              {columnList.map((item) => {
-                const { title = '', align = 'center', dataIndex } = item;
-                return (
-                  <th class={['file-table-th', align]} key={dataIndex}>
-                    {title}
-                  </th>
-                );
-              })}
-            </tr>
-          </thead>
-          <tbody>
-            {dataSource.map((record = {}, index) => {
-              return (
-                <tr class="file-table-tr" key={`${index + record.name || ''}`}>
-                  {columnList.map((item) => {
-                    const { dataIndex = '', customRender, align = 'center' } = item;
-                    const render = customRender && isFunction(customRender);
-                    return (
-                      <td class={['file-table-td', align]} key={dataIndex}>
-                        {render
-                          ? customRender?.({ text: record[dataIndex], record })
-                          : record[dataIndex]}
-                      </td>
-                    );
-                  })}
-                </tr>
-              );
-            })}
-          </tbody>
-        </table>
-      );
-    };
-  },
-});

+ 104 - 0
src/components/Upload/src/FileList.vue

@@ -0,0 +1,104 @@
+<script lang="tsx">
+  import { defineComponent, CSSProperties, watch, nextTick } from 'vue';
+  import { fileListProps } from './props';
+  import { isFunction } from '/@/utils/is';
+  import { useModalContext } from '/@/components/Modal/src/hooks/useModalContext';
+
+  export default defineComponent({
+    name: 'FileList',
+    props: fileListProps,
+    setup(props) {
+      const modalFn = useModalContext();
+      watch(
+        () => props.dataSource,
+        () => {
+          nextTick(() => {
+            modalFn?.redoModalHeight?.();
+          });
+        }
+      );
+      return () => {
+        const { columns, actionColumn, dataSource } = props;
+        const columnList = [...columns, actionColumn];
+        return (
+          <table class="file-table">
+            <colgroup>
+              {columnList.map((item) => {
+                const { width = 0, dataIndex } = item;
+                const style: CSSProperties = {
+                  width: `${width}px`,
+                  minWidth: `${width}px`,
+                };
+                return <col style={width ? style : {}} key={dataIndex} />;
+              })}
+            </colgroup>
+            <thead>
+              <tr class="file-table-tr">
+                {columnList.map((item) => {
+                  const { title = '', align = 'center', dataIndex } = item;
+                  return (
+                    <th class={['file-table-th', align]} key={dataIndex}>
+                      {title}
+                    </th>
+                  );
+                })}
+              </tr>
+            </thead>
+            <tbody>
+              {dataSource.map((record = {}, index) => {
+                return (
+                  <tr class="file-table-tr" key={`${index + record.name || ''}`}>
+                    {columnList.map((item) => {
+                      const { dataIndex = '', customRender, align = 'center' } = item;
+                      const render = customRender && isFunction(customRender);
+                      return (
+                        <td class={['file-table-td', align]} key={dataIndex}>
+                          {render
+                            ? customRender?.({ text: record[dataIndex], record })
+                            : record[dataIndex]}
+                        </td>
+                      );
+                    })}
+                  </tr>
+                );
+              })}
+            </tbody>
+          </table>
+        );
+      };
+    },
+  });
+</script>
+<style lang="less">
+  .file-table {
+    width: 100%;
+    border-collapse: collapse;
+
+    .center {
+      text-align: center;
+    }
+
+    .left {
+      text-align: left;
+    }
+
+    .right {
+      text-align: right;
+    }
+
+    &-th,
+    &-td {
+      padding: 12px 8px;
+    }
+
+    thead {
+      background-color: @background-color-light;
+    }
+
+    table,
+    td,
+    th {
+      border: 1px solid @border-color-base;
+    }
+  }
+</style>

+ 11 - 9
src/components/Upload/src/UploadModal.vue

@@ -50,7 +50,7 @@
   import { useUploadType } from './useUpload';
   import { useMessage } from '/@/hooks/web/useMessage';
   //   types
-  import { FileItem, UploadResultStatus } from './types';
+  import { FileItem, UploadResultStatus } from './typing';
   import { basicProps } from './props';
   import { createTableColumns, createActionColumn } from './data';
   // utils
@@ -58,9 +58,9 @@
   import { buildUUID } from '/@/utils/uuid';
   import { isFunction } from '/@/utils/is';
   import { warn } from '/@/utils/log';
-  import FileList from './FileList';
-
+  import FileList from './FileList.vue';
   import { useI18n } from '/@/hooks/web/useI18n';
+
   export default defineComponent({
     components: { BasicModal, Upload, Alert, FileList },
     props: {
@@ -70,20 +70,20 @@
         default: () => [],
       },
     },
-    emits: ['change', 'register'],
+    emits: ['change', 'register', 'delete'],
     setup(props, { emit }) {
-      const { t } = useI18n();
+      const state = reactive<{ fileList: FileItem[] }>({
+        fileList: [],
+      });
 
       //   是否正在上传
       const isUploadingRef = ref(false);
       const fileListRef = ref<FileItem[]>([]);
-      const state = reactive<{ fileList: FileItem[] }>({
-        fileList: [],
-      });
+      const { accept, helpText, maxNumber, maxSize } = toRefs(props);
 
+      const { t } = useI18n();
       const [register, { closeModal }] = useModalInner();
 
-      const { accept, helpText, maxNumber, maxSize } = toRefs(props);
       const { getAccept, getStringAccept, getHelpText } = useUploadType({
         acceptRef: accept,
         helpTextRef: helpText,
@@ -162,10 +162,12 @@
         }
         return false;
       }
+
       // 删除
       function handleRemove(record: FileItem) {
         const index = fileListRef.value.findIndex((item) => item.uuid === record.uuid);
         index !== -1 && fileListRef.value.splice(index, 1);
+        emit('delete', record);
       }
 
       // 预览

+ 3 - 6
src/components/Upload/src/UploadPreviewModal.vue

@@ -12,18 +12,15 @@
 </template>
 <script lang="ts">
   import { defineComponent, watch, ref } from 'vue';
-
   //   import { BasicTable, useTable } from '/@/components/Table';
-  import FileList from './FileList';
-
+  import FileList from './FileList.vue';
   import { BasicModal, useModalInner } from '/@/components/Modal';
   import { previewProps } from './props';
-  import { PreviewFileItem } from './types';
+  import { PreviewFileItem } from './typing';
   import { downloadByUrl } from '/@/utils/file/download';
-
   import { createPreviewColumns, createPreviewActionColumn } from './data';
-
   import { useI18n } from '/@/hooks/web/useI18n';
+
   export default defineComponent({
     components: { BasicModal, FileList },
     props: previewProps,

+ 2 - 3
src/components/Upload/src/data.tsx

@@ -1,15 +1,14 @@
 import type { BasicColumn, ActionItem } from '/@/components/Table';
-
-import { FileItem, PreviewFileItem, UploadResultStatus } from './types';
+import { FileItem, PreviewFileItem, UploadResultStatus } from './typing';
 import {
   // checkImgType,
   isImgTypeByName,
 } from './helper';
 import { Progress, Tag } from 'ant-design-vue';
-
 import TableAction from '/@/components/Table/src/components/TableAction.vue';
 import ThumbUrl from './ThumbUrl.vue';
 import { useI18n } from '/@/hooks/web/useI18n';
+
 const { t } = useI18n();
 
 // 文件上传列表

+ 1 - 1
src/components/Upload/src/props.ts

@@ -1,5 +1,5 @@
 import type { PropType } from 'vue';
-import { FileBasicColumn } from './types';
+import { FileBasicColumn } from './typing';
 
 export const basicProps = {
   helpText: {

+ 0 - 0
src/components/Upload/src/types.ts → src/components/Upload/src/typing.ts


+ 1 - 3
src/components/Upload/src/useUpload.ts

@@ -3,20 +3,17 @@ import { useI18n } from '/@/hooks/web/useI18n';
 const { t } = useI18n();
 export function useUploadType({
   acceptRef,
-  //   uploadTypeRef,
   helpTextRef,
   maxNumberRef,
   maxSizeRef,
 }: {
   acceptRef: Ref<string[]>;
-  //   uploadTypeRef: Ref<UploadTypeEnum>;
   helpTextRef: Ref<string>;
   maxNumberRef: Ref<number>;
   maxSizeRef: Ref<number>;
 }) {
   // 文件类型限制
   const getAccept = computed(() => {
-    // const uploadType = unref(uploadTypeRef);
     const accept = unref(acceptRef);
     if (accept && accept.length > 0) {
       return accept;
@@ -28,6 +25,7 @@ export function useUploadType({
       .map((item) => `.${item}`)
       .join(',');
   });
+
   // 支持jpg、jpeg、png格式,不超过2M,最多可选择10张图片,。
   const getHelpText = computed(() => {
     const helpText = unref(helpTextRef);