gemercheung 3 anni fa
parent
commit
efad62789f
51 ha cambiato i file con 2879 aggiunte e 1948 eliminazioni
  1. 3 2
      .eslintrc.js
  2. 91 60
      package.json
  3. 2362 1569
      pnpm-lock.yaml
  4. 81 86
      src/components/CardList/src/CardList.vue
  5. 1 1
      src/components/CardList/src/data.ts
  6. 2 2
      src/components/CodeEditor/src/codemirror/codemirror.css
  7. 1 1
      src/components/Container/src/collapse/CollapseContainer.vue
  8. 9 9
      src/components/ContextMenu/src/ContextMenu.vue
  9. 10 1
      src/components/Form/src/BasicForm.vue
  10. 11 6
      src/components/Form/src/components/ApiSelect.vue
  11. 2 0
      src/components/Form/src/helper.ts
  12. 7 7
      src/components/Form/src/hooks/useFormEvents.ts
  13. 2 1
      src/components/Form/src/hooks/useFormValues.ts
  14. 6 3
      src/components/Form/src/hooks/useLabelWidth.ts
  15. 2 1
      src/components/Form/src/props.ts
  16. 4 2
      src/components/Form/src/types/form.ts
  17. 1 1
      src/components/Markdown/src/MarkdownViewer.vue
  18. 6 2
      src/components/Modal/src/components/Modal.tsx
  19. 6 1
      src/components/Page/src/PageWrapper.vue
  20. 1 0
      src/components/Table/index.ts
  21. 17 5
      src/components/Table/src/BasicTable.vue
  22. 0 23
      src/components/Table/src/components/ExpandIcon.tsx
  23. 14 15
      src/components/Table/src/components/TableAction.vue
  24. 1 1
      src/components/Table/src/components/editable/EditableCell.vue
  25. 27 18
      src/components/Table/src/components/settings/ColumnSetting.vue
  26. 6 14
      src/components/Table/src/hooks/useColumns.ts
  27. 14 15
      src/components/Table/src/hooks/useDataSource.ts
  28. 0 3
      src/components/Table/src/hooks/useRowSelection.ts
  29. 55 0
      src/components/Table/src/hooks/useScrollTo.ts
  30. 6 0
      src/components/Table/src/hooks/useTable.ts
  31. 8 1
      src/components/Table/src/hooks/useTableExpand.ts
  32. 1 1
      src/components/Table/src/hooks/useTableFooter.ts
  33. 41 14
      src/components/Table/src/hooks/useTableScroll.ts
  34. 15 13
      src/components/Table/src/props.ts
  35. 6 4
      src/components/Table/src/types/table.ts
  36. 13 0
      src/components/Table/src/types/tableAction.ts
  37. 2 2
      src/components/Tree/src/TreeHeader.vue
  38. 6 7
      src/components/Upload/src/BasicUpload.vue
  39. 4 9
      src/components/Upload/src/UploadModal.vue
  40. 1 1
      src/components/Upload/src/UploadPreviewModal.vue
  41. 1 12
      src/components/registerGlobComp.ts
  42. 1 3
      src/directives/loading.ts
  43. 1 1
      src/settings/projectSetting.ts
  44. 6 9
      src/utils/cache/storageCache.ts
  45. 10 7
      src/utils/dateUtil.ts
  46. 1 1
      src/utils/factory/createAsyncComponent.tsx
  47. 1 1
      src/utils/file/base64Conver.ts
  48. 2 5
      src/utils/http/axios/Axios.ts
  49. 2 1
      src/utils/http/axios/helper.ts
  50. 2 1
      src/utils/http/axios/index.ts
  51. 7 6
      vite.config.ts

+ 3 - 2
.eslintrc.js

@@ -55,8 +55,6 @@ module.exports = defineConfig({
     'space-before-function-paren': 'off',
 
     'vue/attributes-order': 'off',
-    'vue/v-on-event-hyphenation': 'off',
-    'vue/multi-word-component-names': 'off',
     'vue/one-component-per-file': 'off',
     'vue/html-closing-bracket-newline': 'off',
     'vue/max-attributes-per-line': 'off',
@@ -64,6 +62,8 @@ module.exports = defineConfig({
     'vue/singleline-html-element-content-newline': 'off',
     'vue/attribute-hyphenation': 'off',
     'vue/require-default-prop': 'off',
+    'vue/require-explicit-emits': 'off',
+    'vue/no-useless-template-attributes': 'off',
     'vue/html-self-closing': [
       'error',
       {
@@ -76,5 +76,6 @@ module.exports = defineConfig({
         math: 'always',
       },
     ],
+    'vue/multi-word-component-names': 'off',
   },
 });

+ 91 - 60
package.json

@@ -1,13 +1,13 @@
 {
-  "name": "zfb-4.0",
-  "version": "2.8.0",
+  "name": "zfb-mp",
+  "version": "4.0.0",
   "scripts": {
-    "bootstrap": "yarn install",
+    "bootstrap": "pnpm install",
     "serve": "npm run dev",
     "dev": "vite",
     "build": "cross-env NODE_ENV=production vite build && esno ./build/script/postBuild.ts",
     "build:test": "cross-env vite build --mode test && esno ./build/script/postBuild.ts",
-    "build:no-cache": "yarn clean:cache && npm run build",
+    "build:no-cache": "pnpm clean:cache && npm run build",
     "report": "cross-env REPORT=true npm run build",
     "type:check": "vue-tsc --noEmit --skipLibCheck",
     "preview": "npm run build && vite preview",
@@ -18,117 +18,129 @@
     "lint:eslint": "eslint --cache --max-warnings 0  \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
     "lint:prettier": "prettier --write  \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
     "lint:stylelint": "stylelint --cache --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
-    "lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
+    "lint:lint-staged": "lint-staged",
     "test:unit": "jest",
     "test:unit-coverage": "jest --coverage",
     "test:gzip": "npx http-server dist --cors --gzip -c-1",
     "test:br": "npx http-server dist --cors --brotli -c-1",
-    "reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
-    "prepare": "node -e \"if(require('fs').existsSync('.git')){process.exit(1)}\" || is-ci || husky install",
+    "reinstall": "rimraf pnpm-lock.yaml && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
+    "prepare": "node -e \"if(require('fs').existsSync('.git')){process.exit(1)}\" || husky install",
     "gen:icon": "esno ./build/generate/icon/index.ts"
   },
   "dependencies": {
     "@ant-design/colors": "^6.0.0",
     "@ant-design/icons-vue": "^6.0.1",
-    "@iconify/iconify": "^2.0.4",
-    "@vueuse/core": "^6.7.4",
-    "@vueuse/shared": "^6.7.4",
-    "@zxcvbn-ts/core": "^1.0.0-beta.0",
-    "ant-design-vue": "2.2.8",
+    "@iconify/iconify": "^2.1.0",
+    "@logicflow/core": "^0.7.16",
+    "@logicflow/extension": "^0.7.16",
+    "@vue/runtime-core": "^3.2.26",
+    "@vue/shared": "^3.2.26",
+    "@vueuse/core": "^7.4.1",
+    "@vueuse/shared": "^7.4.1",
+    "@zxcvbn-ts/core": "^1.2.0",
+    "ant-design-vue": "3.0.0-beta.3",
     "axios": "^0.24.0",
+    "codemirror": "^5.65.0",
     "cropperjs": "^1.5.12",
     "crypto-js": "^4.1.1",
+    "dayjs": "^1.10.7",
     "echarts": "^5.2.2",
+    "intro.js": "^4.3.0",
     "lodash-es": "^4.17.21",
     "mockjs": "^1.1.0",
     "moment": "^2.29.1",
     "nprogress": "^0.2.0",
     "path-to-regexp": "^6.2.0",
-    "pinia": "2.0.0",
-    "qrcode": "^1.4.4",
-    "qs": "^6.10.1",
+    "pinia": "2.0.9",
+    "print-js": "^1.6.0",
+    "qrcode": "^1.5.0",
+    "qs": "^6.10.2",
     "resize-observer-polyfill": "^1.5.1",
+    "showdown": "^1.9.1",
     "sortablejs": "^1.14.0",
     "tinymce": "^5.10.2",
-    "vue": "^3.2.21",
+    "vditor": "^3.8.10",
+    "vue": "^3.2.26",
     "vue-i18n": "^9.1.9",
+    "vue-json-pretty": "^1.8.2",
     "vue-router": "^4.0.12",
-    "vue-types": "^4.1.1"
+    "vue-types": "^4.1.1",
+    "xlsx": "^0.17.4"
   },
   "devDependencies": {
-    "@commitlint/cli": "^14.1.0",
-    "@commitlint/config-conventional": "^14.1.0",
-    "@iconify/json": "^1.1.422",
+    "@commitlint/cli": "^16.0.1",
+    "@commitlint/config-conventional": "^16.0.0",
+    "@iconify/json": "^2.0.16",
     "@purge-icons/generated": "^0.7.0",
     "@types/codemirror": "^5.60.5",
     "@types/crypto-js": "^4.0.2",
     "@types/fs-extra": "^9.0.13",
     "@types/inquirer": "^8.1.3",
     "@types/intro.js": "^3.0.2",
-    "@types/jest": "^27.0.2",
+    "@types/jest": "^27.0.3",
     "@types/lodash-es": "^4.17.5",
     "@types/mockjs": "^1.0.4",
-    "@types/node": "^16.11.6",
+    "@types/node": "^17.0.5",
     "@types/nprogress": "^0.2.0",
-    "@types/qrcode": "^1.4.1",
+    "@types/qrcode": "^1.4.2",
     "@types/qs": "^6.9.7",
     "@types/showdown": "^1.9.4",
     "@types/sortablejs": "^1.10.7",
-    "@typescript-eslint/eslint-plugin": "^5.3.0",
-    "@typescript-eslint/parser": "^5.3.0",
-    "@vitejs/plugin-legacy": "^1.6.2",
-    "@vitejs/plugin-vue": "^1.9.4",
-    "@vitejs/plugin-vue-jsx": "^1.2.0",
-    "@vue/compiler-sfc": "3.2.21",
-    "@vue/test-utils": "^2.0.0-rc.16",
+    "@typescript-eslint/eslint-plugin": "^5.8.1",
+    "@typescript-eslint/parser": "^5.8.1",
+    "@vitejs/plugin-legacy": "^1.6.4",
+    "@vitejs/plugin-vue": "^2.0.1",
+    "@vitejs/plugin-vue-jsx": "^1.3.3",
+    "@vue/compiler-sfc": "3.2.26",
+    "@vue/test-utils": "^2.0.0-rc.18",
     "autoprefixer": "^10.4.0",
     "commitizen": "^4.2.4",
-    "conventional-changelog-cli": "^2.1.1",
+    "conventional-changelog-cli": "^2.2.2",
     "cross-env": "^7.0.3",
     "dotenv": "^10.0.0",
-    "eslint": "^8.1.0",
+    "eslint": "^8.5.0",
     "eslint-config-prettier": "^8.3.0",
-    "eslint-define-config": "^1.1.2",
-    "eslint-plugin-jest": "^25.2.2",
+    "eslint-define-config": "^1.2.1",
+    "eslint-plugin-jest": "^25.3.2",
     "eslint-plugin-prettier": "^4.0.0",
-    "eslint-plugin-vue": "^8.0.3",
-    "esno": "^0.10.1",
+    "eslint-plugin-vue": "^8.2.0",
+    "esno": "^0.13.0",
     "fs-extra": "^10.0.0",
     "husky": "^7.0.4",
     "inquirer": "^8.2.0",
-    "is-ci": "^3.0.1",
-    "jest": "^27.3.1",
+    "jest": "^27.4.5",
     "less": "^4.1.2",
-    "lint-staged": "11.2.6",
+    "lint-staged": "12.1.4",
     "npm-run-all": "^4.1.5",
-    "postcss": "^8.3.11",
-    "postcss-html": "^1.2.0",
+    "postcss": "^8.4.5",
+    "postcss-html": "^1.3.0",
     "postcss-less": "^5.0.0",
-    "prettier": "^2.4.1",
+    "prettier": "^2.5.1",
     "rimraf": "^3.0.2",
     "rollup-plugin-visualizer": "^5.5.2",
-    "stylelint": "^14.0.1",
+    "stylelint": "^14.2.0",
     "stylelint-config-html": "^1.0.0",
     "stylelint-config-prettier": "^9.0.3",
-    "stylelint-config-standard": "^23.0.0",
+    "stylelint-config-recommended": "^6.0.0",
+    "stylelint-config-standard": "^24.0.0",
     "stylelint-order": "^5.0.0",
-    "ts-jest": "^27.0.7",
+    "ts-jest": "^27.1.2",
     "ts-node": "^10.4.0",
-    "typescript": "^4.4.4",
-    "vite": "^2.6.13",
-    "vite-plugin-compression": "^0.3.5",
-    "vite-plugin-html": "^2.1.1",
-    "vite-plugin-imagemin": "^0.4.6",
+    "typescript": "^4.5.4",
+    "vite": "^2.7.8",
+    "vite-plugin-compression": "^0.4.0",
+    "vite-plugin-html": "^2.1.2",
+    "vite-plugin-imagemin": "^0.5.1",
     "vite-plugin-mock": "^2.9.6",
     "vite-plugin-purge-icons": "^0.7.0",
-    "vite-plugin-pwa": "^0.11.3",
-    "vite-plugin-style-import": "^1.3.0",
+    "vite-plugin-pwa": "^0.11.12",
+    "vite-plugin-style-import": "^1.4.1",
     "vite-plugin-svg-icons": "^1.0.5",
     "vite-plugin-theme": "^0.8.1",
-    "vite-plugin-vue-setup-extend": "^0.1.0",
-    "vite-plugin-windicss": "^1.4.12",
+    "vite-plugin-vue-setup-extend": "^0.3.0",
+    "vite-plugin-windicss": "^1.6.1",
     "vue-eslint-parser": "^8.0.1",
-    "vue-tsc": "^0.28.10"
+    "vue-tsc": "^0.30.1"
   },
   "resolutions": {
     "bin-wrapper": "npm:bin-wrapper-china",
@@ -137,14 +149,33 @@
   },
   "repository": {
     "type": "git",
-    "url": "git+https://github.com/anncwb/vue-vben-admin.git"
+    "url": "git+http://face3d.4dage.com:7005/zhangyupeng/zfb_mp.git "
   },
   "license": "MIT",
-  "bugs": {
-    "url": "https://github.com/anncwb/vue-vben-admin/issues"
-  },
-  "homepage": "https://github.com/anncwb/vue-vben-admin",
   "engines": {
     "node": "^12 || >=14"
+  },
+  "lint-staged": {
+    "*.{js,jsx,ts,tsx}": [
+      "eslint --fix",
+      "prettier --write"
+    ],
+    "{!(package)*.json,*.code-snippets,.!(browserslist)*rc}": [
+      "prettier --write--parser json"
+    ],
+    "package.json": [
+      "prettier --write"
+    ],
+    "*.vue": [
+      "eslint --fix",
+      "prettier --write"
+    ],
+    "*.{scss,less,styl,html}": [
+      "stylelint --fix",
+      "prettier --write"
+    ],
+    "*.md": [
+      "prettier --write"
+    ]
   }
 }

File diff suppressed because it is too large
+ 2362 - 1569
pnpm-lock.yaml


+ 81 - 86
src/components/CardList/src/CardList.vue

@@ -1,3 +1,81 @@
+<template>
+  <div class="p-2">
+    <div class="p-4 mb-2 bg-white">
+      <BasicForm @register="registerForm" />
+    </div>
+    {{ sliderProp.width }}
+    <div class="p-2 bg-white">
+      <List
+        :grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }"
+        :data-source="data"
+        :pagination="paginationProp"
+      >
+        <template #header>
+          <div class="flex justify-end space-x-2"
+            ><slot name="header"></slot>
+            <Tooltip>
+              <template #title>
+                <div class="w-50">每行显示数量</div
+                ><Slider
+                  id="slider"
+                  v-bind="sliderProp"
+                  v-model:value="grid"
+                  @change="sliderChange"
+              /></template>
+              <Button><TableOutlined /></Button>
+            </Tooltip>
+            <Tooltip @click="fetch">
+              <template #title>刷新</template>
+              <Button><RedoOutlined /></Button>
+            </Tooltip>
+          </div>
+        </template>
+        <template #renderItem="{ item }">
+          <ListItem>
+            <Card>
+              <template #title></template>
+              <template #cover>
+                <div :class="height">
+                  <Image :src="item.imgs[0]" />
+                </div>
+              </template>
+              <template class="ant-card-actions" #actions>
+                <!--              <SettingOutlined key="setting" />-->
+                <EditOutlined key="edit" />
+                <Dropdown
+                  :trigger="['hover']"
+                  :dropMenuList="[
+                    {
+                      text: '删除',
+                      event: '1',
+                      popConfirm: {
+                        title: '是否确认删除',
+                        confirm: handleDelete.bind(null, item.id),
+                      },
+                    },
+                  ]"
+                  popconfirm
+                >
+                  <EllipsisOutlined key="ellipsis" />
+                </Dropdown>
+              </template>
+
+              <CardMeta>
+                <template #title>
+                  <TypographyText :content="item.name" :ellipsis="{ tooltip: item.address }" />
+                </template>
+                <template #avatar>
+                  <Avatar :src="item.avatar" />
+                </template>
+                <template #description>{{ item.time }}</template>
+              </CardMeta>
+            </Card>
+          </ListItem>
+        </template>
+      </List>
+    </div>
+  </div>
+</template>
 <script lang="ts" setup>
   import { computed, onMounted, ref } from 'vue';
   import {
@@ -9,6 +87,7 @@
   import { List, Card, Image, Typography, Tooltip, Slider, Avatar } from 'ant-design-vue';
   import { Dropdown } from '/@/components/Dropdown';
   import { BasicForm, useForm } from '/@/components/Form';
+  import { propTypes } from '/@/utils/propTypes';
   import { Button } from '/@/components/Button';
   import { isFunction } from '/@/utils/is';
   import { useSlider, grid } from './data';
@@ -20,15 +99,9 @@
   // 组件接收参数
   const props = defineProps({
     // 请求API的参数
-    params: {
-      type: Object,
-      default: () => ({}),
-    },
+    params: propTypes.object.def({}),
     //api
-    api: {
-      type: Function,
-      default: null,
-    },
+    api: propTypes.func,
   });
   //暴露内部方法
   const emit = defineEmits(['getMethod', 'delete']);
@@ -103,81 +176,3 @@
     emit('delete', id);
   }
 </script>
-
-<template>
-  <div class="p-2">
-    <div class="p-4 mb-2 bg-white">
-      <BasicForm @register="registerForm" />
-    </div>
-    {{ sliderProp.width }}
-    <div class="p-2 bg-white">
-      <List
-        :grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }"
-        :data-source="data"
-        :pagination="paginationProp"
-      >
-        <template #header>
-          <div class="flex justify-end space-x-2"
-            ><slot name="header"></slot>
-            <Tooltip>
-              <template #title>
-                <div class="w-50">每行显示数量</div
-                ><Slider
-                  id="slider"
-                  v-bind="sliderProp"
-                  v-model:value="grid"
-                  @change="sliderChange"
-              /></template>
-              <Button><TableOutlined /></Button>
-            </Tooltip>
-            <Tooltip @click="fetch">
-              <template #title>刷新</template>
-              <Button><RedoOutlined /></Button>
-            </Tooltip>
-          </div>
-        </template>
-        <template #renderItem="{ item }">
-          <ListItem>
-            <Card>
-              <template #title></template>
-              <template #cover>
-                <div :class="height">
-                  <Image :src="item.imgs[0]" />
-                </div>
-              </template>
-              <template #actions>
-                <EditOutlined key="edit" />
-                <Dropdown
-                  :trigger="['hover']"
-                  :dropMenuList="[
-                    {
-                      text: '删除',
-                      event: '1',
-                      popConfirm: {
-                        title: '是否确认删除',
-                        confirm: handleDelete.bind(null, item.id),
-                      },
-                    },
-                  ]"
-                  popconfirm
-                >
-                  <EllipsisOutlined key="ellipsis" />
-                </Dropdown>
-              </template>
-
-              <CardMeta>
-                <template #title>
-                  <TypographyText :content="item.name" :ellipsis="{ tooltip: item.address }" />
-                </template>
-                <template #avatar>
-                  <Avatar :src="item.avatar" />
-                </template>
-                <template #description>{{ item.time }}</template>
-              </CardMeta>
-            </Card>
-          </ListItem>
-        </template>
-      </List>
-    </div>
-  </div>
-</template>

+ 1 - 1
src/components/CardList/src/data.ts

@@ -1,5 +1,5 @@
 import { ref } from 'vue';
-//每行个数
+// 每行个数
 export const grid = ref(12);
 // slider属性
 export const useSlider = (min = 6, max = 12) => {

+ 2 - 2
src/components/CodeEditor/src/codemirror/codemirror.css

@@ -53,7 +53,7 @@
   color: var(--comment);
   text-align: right;
   white-space: nowrap;
-  opacity: 60%;
+  opacity: 0.6;
 }
 
 .CodeMirror-guttermarker {
@@ -90,7 +90,7 @@
   display: inline-block;
   font-size: 0.8em;
   content: '>';
-  opacity: 80%;
+  opacity: 0.8;
   transform: rotate(90deg);
   transition: transform 0.2s;
 }

+ 1 - 1
src/components/Container/src/collapse/CollapseContainer.vue

@@ -1,6 +1,6 @@
 <template>
   <div :class="prefixCls">
-    <CollapseHeader v-bind="$props" :prefixCls="prefixCls" :show="show" @expand="handleExpand">
+    <CollapseHeader v-bind="props" :prefixCls="prefixCls" :show="show" @expand="handleExpand">
       <template #title>
         <slot name="title"></slot>
       </template>

+ 9 - 9
src/components/ContextMenu/src/ContextMenu.vue

@@ -60,6 +60,7 @@
         const top = body.clientHeight < y + menuHeight ? y - menuHeight : y;
         return {
           ...styles,
+          position: 'absolute',
           width: `${width}px`,
           left: `${left + 1}px`,
           top: `${top + 1}px`,
@@ -124,15 +125,11 @@
         }
         const { items } = props;
         return (
-          <Menu
-            inlineIndent={12}
-            mode="vertical"
-            class={prefixCls}
-            ref={wrapRef}
-            style={unref(getStyle)}
-          >
-            {renderMenuItem(items)}
-          </Menu>
+          <div class={prefixCls}>
+            <Menu inlineIndent={12} mode="vertical" ref={wrapRef} style={unref(getStyle)}>
+              {renderMenuItem(items)}
+            </Menu>
+          </div>
         );
       };
     },
@@ -185,6 +182,9 @@
     background-clip: padding-box;
     user-select: none;
 
+    &__item {
+      margin: 0 !important;
+    }
     .item-style();
 
     .ant-divider {

+ 10 - 1
src/components/Form/src/BasicForm.vue

@@ -58,6 +58,7 @@
   import { createFormContext } from './hooks/useFormContext';
   import { useAutoFocus } from './hooks/useAutoFocus';
   import { useModalContext } from '/@/components/Modal';
+  import { useDebounceFn } from '@vueuse/core';
 
   import { basicProps } from './props';
   import { useDesign } from '/@/hooks/web/useDesign';
@@ -122,7 +123,7 @@
             if (!Array.isArray(defaultValue)) {
               schema.defaultValue = dateUtil(defaultValue);
             } else {
-              const def: moment.Moment[] = [];
+              const def: any[] = [];
               defaultValue.forEach((item) => {
                 def.push(dateUtil(item));
               });
@@ -225,6 +226,14 @@
         },
       );
 
+      watch(
+        () => formModel,
+        useDebounceFn(() => {
+          unref(getProps).submitOnChange && handleSubmit();
+        }, 300),
+        { deep: true },
+      );
+
       async function setProps(formProps: Partial<FormProps>): Promise<void> {
         propsRef.value = deepMerge(unref(propsRef) || {}, formProps);
       }

+ 11 - 6
src/components/Form/src/components/ApiSelect.vue

@@ -1,6 +1,6 @@
 <template>
   <Select
-    @dropdownVisibleChange="handleFetch"
+    @dropdown-visible-change="handleFetch"
     v-bind="$attrs"
     @change="handleChange"
     :options="getOptions"
@@ -57,6 +57,7 @@
       labelField: propTypes.string.def('label'),
       valueField: propTypes.string.def('value'),
       immediate: propTypes.bool.def(true),
+      alwaysLoad: propTypes.bool.def(false),
     },
     emits: ['options-change', 'change'],
     setup(props, { emit }) {
@@ -87,7 +88,7 @@
       });
 
       watchEffect(() => {
-        props.immediate && fetch();
+        props.immediate && !props.alwaysLoad && fetch();
       });
 
       watch(
@@ -121,10 +122,14 @@
         }
       }
 
-      async function handleFetch() {
-        if (!props.immediate && unref(isFirstLoad)) {
-          await fetch();
-          isFirstLoad.value = false;
+      async function handleFetch(visible) {
+        if (visible) {
+          if (props.alwaysLoad) {
+            await fetch();
+          } else if (!props.immediate && unref(isFirstLoad)) {
+            await fetch();
+            isFirstLoad.value = false;
+          }
         }
       }
 

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

@@ -70,3 +70,5 @@ export function handleInputNumberValue(component?: ComponentType, val?: any) {
  * 时间字段
  */
 export const dateItemType = genType();
+
+export const defaultValueComponents = ['Input', 'InputPassword', 'InputSearch', 'InputTextArea'];

+ 7 - 7
src/components/Form/src/hooks/useFormEvents.ts

@@ -1,10 +1,10 @@
 import type { ComputedRef, Ref } from 'vue';
 import type { FormProps, FormSchema, FormActionType } from '../types/form';
 import type { NamePath } from 'ant-design-vue/lib/form/interface';
-import { unref, toRaw } from 'vue';
+import { unref, toRaw, nextTick } from 'vue';
 import { isArray, isFunction, isObject, isString } from '/@/utils/is';
 import { deepMerge } from '/@/utils';
-import { dateItemType, handleInputNumberValue } from '../helper';
+import { dateItemType, handleInputNumberValue, defaultValueComponents } from '../helper';
 import { dateUtil } from '/@/utils/dateUtil';
 import { cloneDeep, uniqBy } from 'lodash-es';
 import { error } from '/@/utils/log';
@@ -37,9 +37,12 @@ export function useFormEvents({
     if (!formEl) return;
 
     Object.keys(formModel).forEach((key) => {
-      formModel[key] = defaultValueRef.value[key];
+      const schema = unref(getSchema).find((item) => item.field === key);
+      const isInput = schema?.component && defaultValueComponents.includes(schema.component);
+      formModel[key] = isInput ? defaultValueRef.value[key] || '' : defaultValueRef.value[key];
     });
-    clearValidate();
+    nextTick(() => clearValidate());
+
     emit('reset', toRaw(formModel));
     submitOnReset && handleSubmit();
   }
@@ -125,9 +128,6 @@ export function useFormEvents({
     const schemaList: FormSchema[] = cloneDeep(unref(getSchema));
 
     const index = schemaList.findIndex((schema) => schema.field === prefixField);
-    const hasInList = schemaList.some((item) => item.field === prefixField || schema.field);
-
-    if (!hasInList) return;
 
     if (!prefixField || index === -1 || first) {
       first ? schemaList.unshift(schema) : schemaList.push(schema);

+ 2 - 1
src/components/Form/src/hooks/useFormValues.ts

@@ -33,7 +33,8 @@ export function useFormValues({
       if (isObject(value)) {
         value = transformDateFunc?.(value);
       }
-      if (isArray(value) && value[0]?._isAMomentObject && value[1]?._isAMomentObject) {
+
+      if (isArray(value) && value[0]?.format && value[1]?.format) {
         value = value.map((item) => transformDateFunc?.(item));
       }
       // Remove spaces

+ 6 - 3
src/components/Form/src/hooks/useLabelWidth.ts

@@ -1,7 +1,6 @@
 import type { Ref } from 'vue';
-import type { FormProps, FormSchema } from '../types/form';
-
 import { computed, unref } from 'vue';
+import type { FormProps, FormSchema } from '../types/form';
 import { isNumber } from '/@/utils/is';
 
 export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<FormProps>) {
@@ -14,6 +13,7 @@ export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<
       labelWidth: globalLabelWidth,
       labelCol: globalLabelCol,
       wrapperCol: globWrapperCol,
+      layout,
     } = unref(propsRef);
 
     // If labelWidth is set globally, all items setting
@@ -33,7 +33,10 @@ export function useItemLabelWidth(schemaItemRef: Ref<FormSchema>, propsRef: Ref<
 
     return {
       labelCol: { style: { width }, ...col },
-      wrapperCol: { style: { width: `calc(100% - ${width})` }, ...wrapCol },
+      wrapperCol: {
+        style: { width: layout === 'vertical' ? '100%' : `calc(100% - ${width})` },
+        ...wrapCol,
+      },
     };
   });
 }

+ 2 - 1
src/components/Form/src/props.ts

@@ -40,6 +40,7 @@ export const basicProps = {
   // 在INPUT组件上单击回车时,是否自动提交
   autoSubmitOnEnter: propTypes.bool.def(false),
   submitOnReset: propTypes.bool,
+  submitOnChange: propTypes.bool,
   size: propTypes.oneOf(['default', 'small', 'large']).def('default'),
   // 禁用表单
   disabled: propTypes.bool,
@@ -53,7 +54,7 @@ export const basicProps = {
   transformDateFunc: {
     type: Function as PropType<Fn>,
     default: (date: any) => {
-      return date._isAMomentObject ? date?.format('YYYY-MM-DD HH:mm:ss') : date;
+      return date?.format?.('YYYY-MM-DD HH:mm:ss') ?? date;
     },
   },
   rulesMessageJoinLabel: propTypes.bool.def(true),

+ 4 - 2
src/components/Form/src/types/form.ts

@@ -54,12 +54,14 @@ export interface FormProps {
   model?: Recordable;
   // The width of all items in the entire form
   labelWidth?: number | string;
-  //alignment
+  // alignment
   labelAlign?: 'left' | 'right';
-  //Row configuration for the entire form
+  // Row configuration for the entire form
   rowProps?: RowProps;
   // Submit form on reset
   submitOnReset?: boolean;
+  // Submit form on form changing
+  submitOnChange?: boolean;
   // Col configuration for the entire form
   labelCol?: Partial<ColEx>;
   // Col configuration for the entire form

+ 1 - 1
src/components/Markdown/src/MarkdownViewer.vue

@@ -4,7 +4,7 @@
 </template>
 
 <script lang="ts" setup>
-  import { computed } from 'vue';
+  import { computed, defineProps } from 'vue';
   import showdown from 'showdown';
 
   const converter = new showdown.Converter();

+ 6 - 2
src/components/Modal/src/components/Modal.tsx

@@ -10,7 +10,7 @@ export default defineComponent({
   inheritAttrs: false,
   props: basicProps,
   emits: ['cancel'],
-  setup(props, { slots }) {
+  setup(props, { slots, emit }) {
     const { visible, draggable, destroyOnClose } = toRefs(props);
     const attrs = useAttrs();
     useModalDragMove({
@@ -19,8 +19,12 @@ export default defineComponent({
       draggable,
     });
 
+    const onCancel = (e: Event) => {
+      emit('cancel', e);
+    };
+
     return () => {
-      const propsData = { ...unref(attrs), ...props } as Recordable;
+      const propsData = { ...unref(attrs), ...props, onCancel } as Recordable;
       return <Modal {...propsData}>{extendSlots(slots)}</Modal>;
     };
   },

+ 6 - 1
src/components/Page/src/PageWrapper.vue

@@ -5,7 +5,7 @@
       :title="title"
       v-bind="omit($attrs, 'class')"
       ref="headerRef"
-      v-if="content || $slots.headerContent || title || getHeaderSlots.length"
+      v-if="getShowHeader"
     >
       <template #default>
         <template v-if="content">
@@ -99,6 +99,10 @@
         ];
       });
 
+      const getShowHeader = computed(
+        () => props.content || slots?.headerContent || props.title || getHeaderSlots.value.length,
+      );
+
       const getShowFooter = computed(() => slots?.leftFooter || slots?.rightFooter);
 
       const getHeaderSlots = computed(() => {
@@ -150,6 +154,7 @@
         getClass,
         getHeaderSlots,
         prefixCls,
+        getShowHeader,
         getShowFooter,
         omit,
         getContentClass,

+ 1 - 0
src/components/Table/index.ts

@@ -2,6 +2,7 @@ export { default as BasicTable } from './src/BasicTable.vue';
 export { default as TableAction } from './src/components/TableAction.vue';
 export { default as EditTableHeaderIcon } from './src/components/EditTableHeaderIcon.vue';
 export { default as TableImg } from './src/components/TableImg.vue';
+
 export * from './src/types/table';
 export * from './src/types/pagination';
 export * from './src/types/tableAction';

+ 17 - 5
src/components/Table/src/BasicTable.vue

@@ -1,6 +1,7 @@
 <template>
   <div ref="wrapRef" :class="getWrapperClass">
     <BasicForm
+      ref="formRef"
       submitOnReset
       v-bind="getFormProps"
       v-if="getBindValues.useSearchForm"
@@ -25,7 +26,7 @@
         <slot :name="item" v-bind="data || {}"></slot>
       </template>
 
-      <template #[`header-${column.dataIndex}`] v-for="column in columns" :key="column.dataIndex">
+      <template #[`header-${column.dataIndex}`] v-for="(column, index) in columns" :key="index">
         <HeaderCell :column="column" />
       </template>
     </Table>
@@ -43,7 +44,6 @@
   import { Table } from 'ant-design-vue';
   import { BasicForm, useForm } from '/@/components/Form/index';
   import { PageWrapperFixedHeightKey } from '/@/components/Page';
-  import expandIcon from './components/ExpandIcon';
   import HeaderCell from './components/HeaderCell.vue';
   import { InnerHandlers } from './types/table';
 
@@ -53,6 +53,7 @@
   import { useLoading } from './hooks/useLoading';
   import { useRowSelection } from './hooks/useRowSelection';
   import { useTableScroll } from './hooks/useTableScroll';
+  import { useTableScrollTo } from './hooks/useScrollTo';
   import { useCustomRow } from './hooks/useCustomRow';
   import { useTableStyle } from './hooks/useTableStyle';
   import { useTableHeader } from './hooks/useTableHeader';
@@ -97,6 +98,7 @@
       const tableData = ref<Recordable[]>([]);
 
       const wrapRef = ref(null);
+      const formRef = ref(null);
       const innerPropsRef = ref<Partial<BasicTableProps>>();
 
       const { prefixCls } = useDesign('basic-table');
@@ -185,8 +187,12 @@
         getColumnsRef,
         getRowSelectionRef,
         getDataSourceRef,
+        wrapRef,
+        formRef,
       );
 
+      const { scrollTo } = useTableScrollTo(tableElRef, getDataSourceRef);
+
       const { customRow } = useCustomRow(getProps, {
         setSelectedRowKeys,
         getSelectRowKeys,
@@ -197,7 +203,11 @@
 
       const { getRowClassName } = useTableStyle(getProps, prefixCls);
 
-      const { getExpandOption, expandAll, collapseAll } = useTableExpand(getProps, tableData, emit);
+      const { getExpandOption, expandAll, expandRows, collapseAll } = useTableExpand(
+        getProps,
+        tableData,
+        emit,
+      );
 
       const handlers: InnerHandlers = {
         onColumnsChange: (data: ColumnChangeParam[]) => {
@@ -222,10 +232,8 @@
       const getBindValues = computed(() => {
         const dataSource = unref(getDataSourceRef);
         let propsData: Recordable = {
-          // ...(dataSource.length === 0 ? { getPopupContainer: () => document.body } : {}),
           ...attrs,
           customRow,
-          expandIcon: slots.expandIcon ? null : expandIcon(),
           ...unref(getProps),
           ...unref(getHeaderProps),
           scroll: unref(getScrollRef),
@@ -300,7 +308,9 @@
         getShowPagination,
         setCacheColumnsByField,
         expandAll,
+        expandRows,
         collapseAll,
+        scrollTo,
         getSize: () => {
           return unref(getBindValues).size as SizeType;
         },
@@ -312,6 +322,7 @@
       emit('register', tableAction, formActions);
 
       return {
+        formRef,
         tableElRef,
         getBindValues,
         getLoading,
@@ -346,6 +357,7 @@
 
   .@{prefix-cls} {
     max-width: 100%;
+    height: 100%;
 
     &-row__striped {
       td {

+ 0 - 23
src/components/Table/src/components/ExpandIcon.tsx

@@ -1,23 +0,0 @@
-import { BasicArrow } from '/@/components/Basic';
-
-export default () => {
-  return (props: Recordable) => {
-    if (!props.expandable) {
-      if (props.needIndentSpaced) {
-        return <span class="ant-table-row-expand-icon ant-table-row-spaced" />;
-      } else {
-        return <span />;
-      }
-    }
-    return (
-      <BasicArrow
-        style="margin-right: 8px"
-        iconStyle="margin-top: -2px;"
-        onClick={(e: Event) => {
-          props.onExpand(props.record, e);
-        }}
-        expand={props.expanded}
-      />
-    );
-  };
-};

+ 14 - 15
src/components/Table/src/components/TableAction.vue

@@ -104,21 +104,20 @@
       });
 
       const getDropdownList = computed((): any[] => {
-        return (toRaw(props.dropDownActions) || [])
-          .filter((action) => {
-            return hasPermission(action.auth) && isIfShow(action);
-          })
-          .map((action, index) => {
-            const { label, popConfirm } = action;
-            return {
-              ...action,
-              ...popConfirm,
-              onConfirm: popConfirm?.confirm,
-              onCancel: popConfirm?.cancel,
-              text: label,
-              divider: index < props.dropDownActions.length - 1 ? props.divider : false,
-            };
-          });
+        const list = (toRaw(props.dropDownActions) || []).filter((action) => {
+          return hasPermission(action.auth) && isIfShow(action);
+        });
+        return list.map((action, index) => {
+          const { label, popConfirm } = action;
+          return {
+            ...action,
+            ...popConfirm,
+            onConfirm: popConfirm?.confirm,
+            onCancel: popConfirm?.cancel,
+            text: label,
+            divider: index < list.length - 1 ? props.divider : false,
+          };
+        });
       });
 
       const getAlign = computed(() => {

+ 1 - 1
src/components/Table/src/components/editable/EditableCell.vue

@@ -6,7 +6,7 @@
       @click="handleEdit"
     >
       <div class="cell-content" :title="column.ellipsis ? getValues ?? '' : ''">
-        {{ getValues ? getValues : '&nbsp;' }}
+        {{ getValues || getValues === 0 ? getValues : '&nbsp;' }}
       </div>
       <FormOutlined :class="`${prefixCls}__normal-icon`" v-if="!column.editRow" />
     </div>

+ 27 - 18
src/components/Table/src/components/settings/ColumnSetting.vue

@@ -43,7 +43,7 @@
           <CheckboxGroup v-model:value="checkedList" @change="onChange" ref="columnListRef">
             <template v-for="item in plainOptions" :key="item.value">
               <div :class="`${prefixCls}__check-item`" v-if="!('ifShow' in item && !item.ifShow)">
-                <DragOutlined class="table-coulmn-drag-icon" />
+                <DragOutlined class="table-column-drag-icon" />
                 <Checkbox :value="item.value">
                   {{ item.label }}
                 </Checkbox>
@@ -117,13 +117,16 @@
   import { useI18n } from '/@/hooks/web/useI18n';
   import { useTableContext } from '../../hooks/useTableContext';
   import { useDesign } from '/@/hooks/web/useDesign';
-  import { useSortable } from '/@/hooks/web/useSortable';
+  // import { useSortable } from '/@/hooks/web/useSortable';
   import { isFunction, isNullAndUnDef } from '/@/utils/is';
   import { getPopupContainer as getParentContainer } from '/@/utils';
-  import { omit } from 'lodash-es';
+  import { cloneDeep, omit } from 'lodash-es';
+  import Sortablejs from 'sortablejs';
+  import type Sortable from 'sortablejs';
 
   interface State {
     checkAll: boolean;
+    isInit?: boolean;
     checkedList: string[];
     defaultCheckList: string[];
   }
@@ -157,7 +160,7 @@
       let inited = false;
 
       const cachePlainOptions = ref<Options[]>([]);
-      const plainOptions = ref<Options[]>([]);
+      const plainOptions = ref<Options[] | any>([]);
 
       const plainSortOptions = ref<Options[]>([]);
 
@@ -180,7 +183,7 @@
 
       watchEffect(() => {
         const columns = table.getColumns();
-        if (columns.length) {
+        if (columns.length && !state.isInit) {
           init();
         }
       });
@@ -233,6 +236,7 @@
             }
           });
         }
+        state.isInit = true;
         state.checkedList = checkList;
       }
 
@@ -250,16 +254,15 @@
 
       const indeterminate = computed(() => {
         const len = plainOptions.value.length;
-        let checkdedLen = state.checkedList.length;
-        unref(checkIndex) && checkdedLen--;
-        return checkdedLen > 0 && checkdedLen < len;
+        let checkedLen = state.checkedList.length;
+        unref(checkIndex) && checkedLen--;
+        return checkedLen > 0 && checkedLen < len;
       });
 
       // Trigger when check/uncheck a column
       function onChange(checkedList: string[]) {
-        const len = plainOptions.value.length;
+        const len = plainSortOptions.value.length;
         state.checkAll = checkedList.length === len;
-
         const sortList = unref(plainSortOptions).map((item) => item.value);
         checkedList.sort((prev, next) => {
           return sortList.indexOf(prev) - sortList.indexOf(next);
@@ -267,6 +270,8 @@
         setColumns(checkedList);
       }
 
+      let sortable: Sortable;
+      let sortableOrder: string[] = [];
       // reset columns
       function reset() {
         state.checkedList = [...state.defaultCheckList];
@@ -274,6 +279,7 @@
         plainOptions.value = unref(cachePlainOptions);
         plainSortOptions.value = unref(cachePlainOptions);
         setColumns(table.getCacheColumns());
+        sortable.sort(sortableOrder);
       }
 
       // Open the pop-up window for drag and drop initialization
@@ -285,15 +291,18 @@
           const el = columnListEl.$el as any;
           if (!el) return;
           // Drag and drop sort
-          const { initSortable } = useSortable(el, {
-            handle: '.table-coulmn-drag-icon ',
+          sortable = Sortablejs.create(unref(el), {
+            animation: 500,
+            delay: 400,
+            delayOnTouchOnly: true,
+            handle: '.table-column-drag-icon ',
             onEnd: (evt) => {
               const { oldIndex, newIndex } = evt;
               if (isNullAndUnDef(oldIndex) || isNullAndUnDef(newIndex) || oldIndex === newIndex) {
                 return;
               }
               // Sort column
-              const columns = getColumns();
+              const columns = cloneDeep(plainSortOptions.value);
 
               if (oldIndex > newIndex) {
                 columns.splice(newIndex, 0, columns[oldIndex]);
@@ -304,11 +313,11 @@
               }
 
               plainSortOptions.value = columns;
-              plainOptions.value = columns;
               setColumns(columns);
             },
           });
-          initSortable();
+          // 记录原始order 序列
+          sortableOrder = sortable.toArray();
           inited = true;
         });
       }
@@ -341,13 +350,13 @@
         if (isFixed && !item.width) {
           item.width = 100;
         }
-        table.setCacheColumnsByField?.(item.dataIndex, { fixed: isFixed });
+        table.setCacheColumnsByField?.(item.dataIndex as string, { fixed: isFixed });
         setColumns(columns);
       }
 
       function setColumns(columns: BasicColumn[] | string[]) {
         table.setColumns(columns);
-        const data: ColumnChangeParam[] = unref(plainOptions).map((col) => {
+        const data: ColumnChangeParam[] = unref(plainSortOptions).map((col) => {
           const visible =
             columns.findIndex(
               (c: BasicColumn | string) =>
@@ -390,7 +399,7 @@
 <style lang="less">
   @prefix-cls: ~'@{namespace}-basic-column-setting';
 
-  .table-coulmn-drag-icon {
+  .table-column-drag-icon {
     margin: 0 5px;
     cursor: move;
   }

+ 6 - 14
src/components/Table/src/hooks/useColumns.ts

@@ -216,25 +216,17 @@ export function useColumns(
       const columnKeys = columns as string[];
       const newColumns: BasicColumn[] = [];
       cacheColumns.forEach((item) => {
-        if (columnKeys.includes(item.dataIndex! || (item.key as string))) {
-          newColumns.push({
-            ...item,
-            defaultHidden: false,
-          });
-        } else {
-          newColumns.push({
-            ...item,
-            defaultHidden: true,
-          });
-        }
+        newColumns.push({
+          ...item,
+          defaultHidden: !columnKeys.includes(item.dataIndex! || (item.key as string)),
+        });
       });
-
       // Sort according to another array
       if (!isEqual(cacheKeys, columns)) {
         newColumns.sort((prev, next) => {
           return (
-            cacheKeys.indexOf(prev.dataIndex as string) -
-            cacheKeys.indexOf(next.dataIndex as string)
+            columnKeys.indexOf(prev.dataIndex as string) -
+            columnKeys.indexOf(next.dataIndex as string)
           );
         });
       }

+ 14 - 15
src/components/Table/src/hooks/useDataSource.ts

@@ -14,7 +14,7 @@ import {
 import { useTimeoutFn } from '/@/hooks/core/useTimeout';
 import { buildUUID } from '/@/utils/uuid';
 import { isFunction, isBoolean } from '/@/utils/is';
-import { get, cloneDeep } from 'lodash-es';
+import { get, cloneDeep, merge } from 'lodash-es';
 import { FETCH_SETTING, ROW_KEY, PAGE_SIZE } from '../const';
 
 interface ActionType {
@@ -196,11 +196,10 @@ export function useDataSource(
   }
 
   function insertTableDataRecord(record: Recordable, index: number): Recordable | undefined {
-    if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;
+    // if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;
     index = index ?? dataSourceRef.value?.length;
     unref(dataSourceRef).splice(index, 0, record);
-    unref(propsRef).dataSource?.splice(index, 0, record);
-    return unref(propsRef).dataSource;
+    return unref(dataSourceRef);
   }
 
   function findTableDataRecord(rowKey: string | number) {
@@ -272,17 +271,17 @@ export function useDataSource(
 
       const { sortInfo = {}, filterInfo } = searchState;
 
-      let params: Recordable = {
-        ...pageParams,
-        ...(useSearchForm ? getFieldsValue() : {}),
-        ...searchInfo,
-        ...(opt?.searchInfo ?? {}),
-        ...defSort,
-        ...sortInfo,
-        ...filterInfo,
-        ...(opt?.sortInfo ?? {}),
-        ...(opt?.filterInfo ?? {}),
-      };
+      let params: Recordable = merge(
+        pageParams,
+        useSearchForm ? getFieldsValue() : {},
+        searchInfo,
+        opt?.searchInfo ?? {},
+        defSort,
+        sortInfo,
+        filterInfo,
+        opt?.sortInfo ?? {},
+        opt?.filterInfo ?? {},
+      );
       if (beforeFetch && isFunction(beforeFetch)) {
         params = (await beforeFetch(params)) || params;
       }

+ 0 - 3
src/components/Table/src/hooks/useRowSelection.ts

@@ -21,11 +21,8 @@ export function useRowSelection(
 
     return {
       selectedRowKeys: unref(selectedRowKeysRef),
-      hideDefaultSelections: false,
       onChange: (selectedRowKeys: string[]) => {
         setSelectedRowKeys(selectedRowKeys);
-        // selectedRowKeysRef.value = selectedRowKeys;
-        // selectedRowRef.value = selectedRows;
       },
       ...omit(rowSelection, ['onChange']),
     };

+ 55 - 0
src/components/Table/src/hooks/useScrollTo.ts

@@ -0,0 +1,55 @@
+import type { ComputedRef, Ref } from 'vue';
+import { nextTick, unref } from 'vue';
+import { warn } from '/@/utils/log';
+
+export function useTableScrollTo(
+  tableElRef: Ref<ComponentRef>,
+  getDataSourceRef: ComputedRef<Recordable[]>,
+) {
+  let bodyEl: HTMLElement | null;
+
+  async function findTargetRowToScroll(targetRowData: Recordable) {
+    const { id } = targetRowData;
+    const targetRowEl: HTMLElement | null | undefined = bodyEl?.querySelector(
+      `[data-row-key="${id}"]`,
+    );
+    //Add a delay to get new dataSource
+    await nextTick();
+    bodyEl?.scrollTo({
+      top: targetRowEl?.offsetTop ?? 0,
+      behavior: 'smooth',
+    });
+  }
+
+  function scrollTo(pos: string): void {
+    const table = unref(tableElRef);
+    if (!table) return;
+
+    const tableEl: Element = table.$el;
+    if (!tableEl) return;
+
+    if (!bodyEl) {
+      bodyEl = tableEl.querySelector('.ant-table-body');
+      if (!bodyEl) return;
+    }
+
+    const dataSource = unref(getDataSourceRef);
+    if (!dataSource) return;
+
+    // judge pos type
+    if (pos === 'top') {
+      findTargetRowToScroll(dataSource[0]);
+    } else if (pos === 'bottom') {
+      findTargetRowToScroll(dataSource[dataSource.length - 1]);
+    } else {
+      const targetRowData = dataSource.find((data) => data.id === pos);
+      if (targetRowData) {
+        findTargetRowToScroll(targetRowData);
+      } else {
+        warn(`id: ${pos} doesn't exist`);
+      }
+    }
+  }
+
+  return { scrollTo };
+}

+ 6 - 0
src/components/Table/src/hooks/useTable.ts

@@ -152,9 +152,15 @@ export function useTable(tableProps?: Props): [
     expandAll: () => {
       getTableInstance().expandAll();
     },
+    expandRows: (keys: string[]) => {
+      getTableInstance().expandRows(keys);
+    },
     collapseAll: () => {
       getTableInstance().collapseAll();
     },
+    scrollTo: (pos: string) => {
+      getTableInstance().scrollTo(pos);
+    },
   };
 
   return [register, methods];

+ 8 - 1
src/components/Table/src/hooks/useTableExpand.ts

@@ -37,6 +37,13 @@ export function useTableExpand(
     expandedRowKeys.value = keys;
   }
 
+  function expandRows(keys: string[]) {
+    // use row ID expands the specified table row
+    const { isTreeTable } = unref(propsRef);
+    if (!isTreeTable) return;
+    expandedRowKeys.value = [...expandedRowKeys.value, ...keys];
+  }
+
   function getAllKeys(data?: Recordable[]) {
     const keys: string[] = [];
     const { childrenColumnName } = unref(propsRef);
@@ -54,5 +61,5 @@ export function useTableExpand(
     expandedRowKeys.value = [];
   }
 
-  return { getExpandOption, expandAll, collapseAll };
+  return { getExpandOption, expandAll, expandRows, collapseAll };
 }

+ 1 - 1
src/components/Table/src/hooks/useTableFooter.ts

@@ -8,7 +8,7 @@ export function useTableFooter(
   propsRef: ComputedRef<BasicTableProps>,
   scrollRef: ComputedRef<{
     x: string | number | true;
-    y: Nullable<number>;
+    y: string | number | null;
     scrollToFirstRowOnChange: boolean;
   }>,
   tableElRef: Ref<ComponentRef>,

+ 41 - 14
src/components/Table/src/hooks/useTableScroll.ts

@@ -1,6 +1,6 @@
 import type { BasicTableProps, TableRowSelection, BasicColumn } from '../types/table';
-import type { Ref, ComputedRef } from 'vue';
-import { computed, unref, ref, nextTick, watch } from 'vue';
+import { Ref, ComputedRef, ref } from 'vue';
+import { computed, unref, nextTick, watch } from 'vue';
 import { getViewportOffset } from '/@/utils/domUtils';
 import { isBoolean } from '/@/utils/is';
 import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
@@ -12,11 +12,12 @@ export function useTableScroll(
   propsRef: ComputedRef<BasicTableProps>,
   tableElRef: Ref<ComponentRef>,
   columnsRef: ComputedRef<BasicColumn[]>,
-  rowSelectionRef: ComputedRef<TableRowSelection<any> | null>,
+  rowSelectionRef: ComputedRef<TableRowSelection | null>,
   getDataSourceRef: ComputedRef<Recordable[]>,
+  wrapRef: Ref<HTMLElement | null>,
+  formRef: Ref<ComponentRef>,
 ) {
-  const tableHeightRef: Ref<Nullable<number>> = ref(null);
-
+  const tableHeightRef: Ref<Nullable<number | string>> = ref(167);
   const modalFn = useModalContext();
 
   // Greater than animation time 280
@@ -43,8 +44,8 @@ export function useTableScroll(
     });
   }
 
-  function setHeight(heigh: number) {
-    tableHeightRef.value = heigh;
+  function setHeight(height: number) {
+    tableHeightRef.value = height;
     //  Solve the problem of modal adaptive height calculation when the form is placed in the modal
     modalFn?.redoModalHeight?.();
   }
@@ -55,7 +56,8 @@ export function useTableScroll(
   let bodyEl: HTMLElement | null;
 
   async function calcTableHeight() {
-    const { resizeHeightOffset, pagination, maxHeight } = unref(propsRef);
+    const { resizeHeightOffset, pagination, maxHeight, isCanResizeParent, useSearchForm } =
+      unref(propsRef);
     const tableData = unref(getDataSourceRef);
 
     const table = unref(tableElRef);
@@ -91,17 +93,14 @@ export function useTableScroll(
     if (!unref(getCanResize) || tableData.length === 0) return;
 
     await nextTick();
-    //Add a delay to get the correct bottomIncludeBody paginationHeight footerHeight headerHeight
+    // Add a delay to get the correct bottomIncludeBody paginationHeight footerHeight headerHeight
 
     const headEl = tableEl.querySelector('.ant-table-thead ');
 
     if (!headEl) return;
 
-    // Table height from bottom
-    const { bottomIncludeBody } = getViewportOffset(headEl);
     // Table height from bottom height-custom offset
-
-    const paddingHeight = 32;
+    let paddingHeight = 32;
     // Pager height
     let paginationHeight = 2;
     if (!isBoolean(pagination)) {
@@ -132,6 +131,35 @@ export function useTableScroll(
       headerHeight = (headEl as HTMLElement).offsetHeight;
     }
 
+    let bottomIncludeBody = 0;
+    if (unref(wrapRef) && isCanResizeParent) {
+      const tablePadding = 12;
+      const formMargin = 16;
+      let paginationMargin = 10;
+      const wrapHeight = unref(wrapRef)?.offsetHeight ?? 0;
+
+      let formHeight = unref(formRef)?.$el.offsetHeight ?? 0;
+      if (formHeight) {
+        formHeight += formMargin;
+      }
+      if (isBoolean(pagination) && !pagination) {
+        paginationMargin = 0;
+      }
+      if (isBoolean(useSearchForm) && !useSearchForm) {
+        paddingHeight = 0;
+      }
+
+      const headerCellHeight =
+        (tableEl.querySelector('.ant-table-title') as HTMLElement)?.offsetHeight ?? 0;
+
+      console.log(wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin);
+      bottomIncludeBody =
+        wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin;
+    } else {
+      // Table height from bottom
+      bottomIncludeBody = getViewportOffset(headEl).bottomIncludeBody;
+    }
+
     let height =
       bottomIncludeBody -
       (resizeHeightOffset || 0) -
@@ -139,7 +167,6 @@ export function useTableScroll(
       paginationHeight -
       footerHeight -
       headerHeight;
-
     height = (height > maxHeight! ? (maxHeight as number) : height) ?? height;
     setHeight(height);
 

+ 15 - 13
src/components/Table/src/props.ts

@@ -10,14 +10,15 @@ import type {
   SizeType,
 } from './types/table';
 import type { FormProps } from '/@/components/Form';
+
 import { DEFAULT_FILTER_FN, DEFAULT_SORT_FN, FETCH_SETTING, DEFAULT_SIZE } from './const';
 import { propTypes } from '/@/utils/propTypes';
 
 export const basicProps = {
-  clickToRowSelect: propTypes.bool.def(true),
-  isTreeTable: propTypes.bool.def(false),
+  clickToRowSelect: { type: Boolean, default: true },
+  isTreeTable: Boolean,
   tableSetting: propTypes.shape<TableSetting>({}),
-  inset: propTypes.bool,
+  inset: Boolean,
   sortFn: {
     type: Function as PropType<(sortInfo: SorterResult) => any>,
     default: DEFAULT_SORT_FN,
@@ -26,10 +27,10 @@ export const basicProps = {
     type: Function as PropType<(data: Partial<Recordable<string[]>>) => any>,
     default: DEFAULT_FILTER_FN,
   },
-  showTableSetting: propTypes.bool,
-  autoCreateKey: propTypes.bool.def(true),
-  striped: propTypes.bool.def(true),
-  showSummary: propTypes.bool,
+  showTableSetting: Boolean,
+  autoCreateKey: { type: Boolean, default: true },
+  striped: { type: Boolean, default: true },
+  showSummary: Boolean,
   summaryFunc: {
     type: [Function, Array] as PropType<(...arg: any[]) => any[]>,
     default: null,
@@ -39,7 +40,7 @@ export const basicProps = {
     default: null,
   },
   indentSize: propTypes.number.def(24),
-  canColDrag: propTypes.bool.def(true),
+  canColDrag: { type: Boolean, default: true },
   api: {
     type: Function as PropType<(...arg: any[]) => Promise<any>>,
     default: null,
@@ -63,8 +64,8 @@ export const basicProps = {
     },
   },
   // 立即请求接口
-  immediate: propTypes.bool.def(true),
-  emptyDataIsShowTable: propTypes.bool.def(true),
+  immediate: { type: Boolean, default: true },
+  emptyDataIsShowTable: { type: Boolean, default: true },
   // 额外的请求参数
   searchInfo: {
     type: Object as PropType<Recordable>,
@@ -86,7 +87,7 @@ export const basicProps = {
     type: [Array] as PropType<BasicColumn[]>,
     default: () => [],
   },
-  showIndexColumn: propTypes.bool.def(true),
+  showIndexColumn: { type: Boolean, default: true },
   indexColumnProps: {
     type: Object as PropType<BasicColumn>,
     default: null,
@@ -95,8 +96,9 @@ export const basicProps = {
     type: Object as PropType<BasicColumn>,
     default: null,
   },
-  ellipsis: propTypes.bool.def(true),
-  canResize: propTypes.bool.def(true),
+  ellipsis: { type: Boolean, default: true },
+  isCanResizeParent: { type: Boolean, default: false },
+  canResize: { type: Boolean, default: true },
   clearSelectOnPageChange: propTypes.bool,
   resizeHeightOffset: propTypes.number.def(0),
   rowSelection: {

+ 6 - 4
src/components/Table/src/types/table.ts

@@ -1,10 +1,8 @@
 import type { VNodeChild } from 'vue';
 import type { PaginationProps } from './pagination';
 import type { FormProps } from '/@/components/Form';
-import type {
-  ColumnProps,
-  TableRowSelection as ITableRowSelection,
-} from 'ant-design-vue/lib/table/interface';
+import type { TableRowSelection as ITableRowSelection } from 'ant-design-vue/lib/table/interface';
+import type { ColumnProps } from 'ant-design-vue/lib/table';
 
 import { ComponentType } from './componentType';
 import { VueNode } from '/@/utils/propTypes';
@@ -89,7 +87,9 @@ export interface TableActionType {
   getSelectRows: <T = Recordable>() => T[];
   clearSelectedRowKeys: () => void;
   expandAll: () => void;
+  expandRows: (keys: string[]) => void;
   collapseAll: () => void;
+  scrollTo: (pos: string) => void; // pos: id | "top" | "bottom"
   getSelectRowKeys: () => string[];
   deleteSelectRowByKey: (key: string) => void;
   setPagination: (info: Partial<PaginationProps>) => void;
@@ -191,6 +191,8 @@ export interface BasicTableProps<T = any> {
   actionColumn?: BasicColumn;
   // 文本超过宽度是否显示。。。
   ellipsis?: boolean;
+  // 是否继承父级高度(父级高度-表单高度-padding高度)
+  isCanResizeParent?: boolean;
   // 是否可以自适应高度
   canResize?: boolean;
   // 自适应高度偏移, 计算结果-偏移量

+ 13 - 0
src/components/Table/src/types/tableAction.ts

@@ -23,4 +23,17 @@ export interface PopConfirm {
   confirm: Fn;
   cancel?: Fn;
   icon?: string;
+  placement?:
+    | 'top'
+    | 'left'
+    | 'right'
+    | 'bottom'
+    | 'topLeft'
+    | 'topRight'
+    | 'leftTop'
+    | 'leftBottom'
+    | 'rightTop'
+    | 'rightBottom'
+    | 'bottomLeft'
+    | 'bottomRight';
 }

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

@@ -24,7 +24,7 @@
               <MenuItem v-bind="{ key: item.value }">
                 {{ item.label }}
               </MenuItem>
-              <Menu.Divider v-if="item.divider" />
+              <MenuDivider v-if="item.divider" />
             </template>
           </Menu>
         </template>
@@ -34,7 +34,7 @@
 </template>
 <script lang="ts" setup>
   import { computed, ref, watch, useSlots } from 'vue';
-  import { Dropdown, Menu, MenuItem, InputSearch } from 'ant-design-vue';
+  import { Dropdown, Menu, MenuItem, MenuDivider, InputSearch } from 'ant-design-vue';
   import { Icon } from '/@/components/Icon';
   import { BasicTitle } from '/@/components/Basic';
   import { useI18n } from '/@/hooks/web/useI18n';

+ 6 - 7
src/components/Upload/src/BasicUpload.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <a-button-group>
+    <Space>
       <a-button type="primary" @click="openUploadModal" preIcon="carbon:cloud-upload">
         {{ t('component.upload.upload') }}
       </a-button>
@@ -18,8 +18,7 @@
           </template>
         </a-button>
       </Tooltip>
-    </a-button-group>
-
+    </Space>
     <UploadModal
       v-bind="bindValue"
       :previewFileList="fileList"
@@ -38,19 +37,19 @@
 </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 { Tooltip } from 'ant-design-vue';
+  import { Tooltip, Space } from 'ant-design-vue';
   import { useModal } from '/@/components/Modal';
   import { uploadContainerProps } from './props';
   import { omit } from 'lodash-es';
   import { useI18n } from '/@/hooks/web/useI18n';
   import { isArray } from '/@/utils/is';
+  import UploadModal from './UploadModal.vue';
+  import UploadPreviewModal from './UploadPreviewModal.vue';
 
   export default defineComponent({
     name: 'BasicUpload',
-    components: { UploadModal, UploadPreviewModal, Icon, Tooltip },
+    components: { UploadModal, Space, UploadPreviewModal, Icon, Tooltip },
     props: uploadContainerProps,
     emits: ['change', 'delete', 'preview-delete', 'update:value'],
 

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

@@ -9,7 +9,7 @@
     :closeFunc="handleCloseFunc"
     :maskClosable="false"
     :keyboard="false"
-    wrapClassName="upload-modal"
+    class="upload-modal"
     :okButtonProps="getOkButtonProps"
     :cancelButtonProps="{ disabled: isUploadingRef }"
   >
@@ -31,6 +31,7 @@
         :accept="getStringAccept"
         :multiple="multiple"
         :before-upload="beforeUpload"
+        :show-upload-list="false"
         class="upload-modal-toolbar__btn"
       >
         <a-button type="primary">
@@ -54,7 +55,7 @@
   import { basicProps } from './props';
   import { createTableColumns, createActionColumn } from './data';
   // utils
-  import { checkFileType, checkImgType, getBase64WithFile } from './helper';
+  import { checkImgType, getBase64WithFile } from './helper';
   import { buildUUID } from '/@/utils/uuid';
   import { isFunction } from '/@/utils/is';
   import { warn } from '/@/utils/log';
@@ -84,7 +85,7 @@
       const { t } = useI18n();
       const [register, { closeModal }] = useModalInner();
 
-      const { getAccept, getStringAccept, getHelpText } = useUploadType({
+      const { getStringAccept, getHelpText } = useUploadType({
         acceptRef: accept,
         helpTextRef: helpText,
         maxNumberRef: maxNumber,
@@ -124,18 +125,12 @@
       function beforeUpload(file: File) {
         const { size, name } = file;
         const { maxSize } = props;
-        const accept = unref(getAccept);
         // 设置最大值,则判断
         if (maxSize && file.size / 1024 / 1024 >= maxSize) {
           createMessage.error(t('component.upload.maxSizeMultiple', [maxSize]));
           return false;
         }
 
-        // 设置类型,则判断
-        if (accept.length > 0 && !checkFileType(file, accept)) {
-          createMessage.error!(t('component.upload.acceptUpload', [accept.join(',')]));
-          return false;
-        }
         const commonItem = {
           uuid: buildUUID(),
           file,

+ 1 - 1
src/components/Upload/src/UploadPreviewModal.vue

@@ -2,7 +2,7 @@
   <BasicModal
     width="800px"
     :title="t('component.upload.preview')"
-    wrapClassName="upload-preview-modal"
+    class="upload-preview-modal"
     v-bind="$attrs"
     @register="register"
     :showOkBtn="false"

+ 1 - 12
src/components/registerGlobComp.ts

@@ -1,18 +1,7 @@
 import type { App } from 'vue';
 import { Button } from './Button';
-import {
-  // Need
-  Button as AntButton,
-  Input,
-  Layout,
-} from 'ant-design-vue';
-
-const compList = [AntButton.Group];
+import { Input, Layout } from 'ant-design-vue';
 
 export function registerGlobComp(app: App) {
-  compList.forEach((comp) => {
-    app.component(comp.name || comp.displayName, comp);
-  });
-
   app.use(Input).use(Button).use(Layout);
 }

+ 1 - 3
src/directives/loading.ts

@@ -24,9 +24,7 @@ const loadingDirective: Directive = {
     if (!instance) return;
     instance.setTip(el.getAttribute('loading-tip'));
     if (binding.oldValue !== binding.value) {
-      if (binding.oldValue !== binding.value) {
-        instance.setLoading?.(binding.value && !instance.loading);
-      }
+      instance.setLoading?.(binding.value && !instance.loading);
     }
   },
   unmounted(el) {

+ 1 - 1
src/settings/projectSetting.ts

@@ -134,7 +134,7 @@ const setting: ProjectConfig = {
   // Transition Setting
   transitionSetting: {
     //  Whether to open the page switching animation
-    // The disabled state will also disable pageLoadinng
+    // The disabled state will also disable pageLoading
     enable: true,
 
     // Route basic switching animation

+ 6 - 9
src/utils/cache/storageCache.ts

@@ -1,9 +1,6 @@
 import { cacheCipher } from '/@/settings/encryptionSetting';
-
 import type { EncryptionParams } from '/@/utils/cipher';
-
 import { AesEncryption } from '/@/utils/cipher';
-
 import { isNullOrUnDef } from '/@/utils/is';
 
 export interface CreateStorageParams extends EncryptionParams {
@@ -27,8 +24,8 @@ export const createStorage = ({
   const encryption = new AesEncryption({ key, iv });
 
   /**
-   *Cache class
-   *Construction parameters can be passed into sessionStorage, localStorage,
+   * Cache class
+   * Construction parameters can be passed into sessionStorage, localStorage,
    * @class Cache
    * @example
    */
@@ -53,11 +50,10 @@ export const createStorage = ({
     }
 
     /**
-     *
-     *  Set cache
+     * Set cache
      * @param {string} key
      * @param {*} value
-     * @expire Expiration time in seconds
+     * @param {*} expire Expiration time in seconds
      * @memberof Cache
      */
     set(key: string, value: any, expire: number | null = timeout) {
@@ -73,8 +69,9 @@ export const createStorage = ({
     }
 
     /**
-     *Read cache
+     * Read cache
      * @param {string} key
+     * @param {*} def
      * @memberof Cache
      */
     get(key: string, def: any = null): any {

+ 10 - 7
src/utils/dateUtil.ts

@@ -1,20 +1,23 @@
 /**
  * Independent time operation tool to facilitate subsequent switch to dayjs
  */
-import moment from 'moment';
+import dayjs from 'dayjs';
 
 const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
-const DATE_FORMAT = 'YYYY-MM-DD ';
+const DATE_FORMAT = 'YYYY-MM-DD';
 
 export function formatToDateTime(
-  date: moment.MomentInput = undefined,
+  date: dayjs.Dayjs | undefined = undefined,
   format = DATE_TIME_FORMAT,
 ): string {
-  return moment(date).format(format);
+  return dayjs(date).format(format);
 }
 
-export function formatToDate(date: moment.MomentInput = undefined, format = DATE_FORMAT): string {
-  return moment(date).format(format);
+export function formatToDate(
+  date: dayjs.Dayjs | undefined = undefined,
+  format = DATE_FORMAT,
+): string {
+  return dayjs(date).format(format);
 }
 
-export const dateUtil = moment;
+export const dateUtil = dayjs;

+ 1 - 1
src/utils/factory/createAsyncComponent.tsx

@@ -3,7 +3,7 @@ import {
   // FunctionalComponent, CSSProperties
 } from 'vue';
 import { Spin } from 'ant-design-vue';
-import { noop } from '/@/utils/index';
+import { noop } from '/@/utils';
 
 // const Loading: FunctionalComponent<{ size: 'small' | 'default' | 'large' }> = (props) => {
 //   const style: CSSProperties = {

+ 1 - 1
src/utils/file/base64Conver.ts

@@ -5,7 +5,7 @@ export function dataURLtoBlob(base64Buf: string): Blob {
   const arr = base64Buf.split(',');
   const typeItem = arr[0];
   const mime = typeItem.match(/:(.*?);/)![1];
-  const bstr = atob(arr[1]);
+  const bstr = window.atob(arr[1]);
   let n = bstr.length;
   const u8arr = new Uint8Array(n);
   while (n--) {

+ 2 - 5
src/utils/http/axios/Axios.ts

@@ -80,11 +80,8 @@ export class VAxios {
     // Request interceptor configuration processing
     this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {
       // If cancel repeat request is turned on, then cancel repeat request is prohibited
-      const {
-        // @ts-ignore
-        headers: { ignoreCancelToken },
-      } = config;
-
+      // @ts-ignore
+      const { ignoreCancelToken } = config.requestOptions;
       const ignoreCancel =
         ignoreCancelToken !== undefined
           ? ignoreCancelToken

+ 2 - 1
src/utils/http/axios/helper.ts

@@ -27,7 +27,8 @@ export function formatRequestDate(params: Recordable) {
   }
 
   for (const key in params) {
-    if (params[key] && params[key]._isAMomentObject) {
+    const format = params[key]?.format ?? null;
+    if (format && typeof format === 'function') {
       params[key] = params[key].format(DATE_TIME_FORMAT);
     }
     if (isString(key)) {

+ 2 - 1
src/utils/http/axios/index.ts

@@ -2,6 +2,7 @@
 // The axios configuration can be changed according to the project, just change the file, other files can be left unchanged
 
 import type { AxiosResponse } from 'axios';
+import { clone } from 'lodash-es';
 import type { RequestOptions, Result } from '/#/axios';
 import type { AxiosTransform, CreateAxiosOptions } from './axiosTransform';
 import { VAxios } from './Axios';
@@ -208,7 +209,7 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
         // 如果是form-data格式
         // headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED },
         // 数据处理方式
-        transform,
+        transform: clone(transform),
         // 配置项,下面的选项都可以在独立的接口请求中覆盖
         requestOptions: {
           // 默认将prefix 添加到url

+ 7 - 6
vite.config.ts

@@ -1,6 +1,6 @@
 import type { UserConfig, ConfigEnv } from 'vite';
 import pkg from './package.json';
-import moment from 'moment';
+import dayjs from 'dayjs';
 import { loadEnv } from 'vite';
 import { resolve } from 'path';
 import { generateModifyVars } from './build/generate/generateModifyVars';
@@ -16,7 +16,7 @@ function pathResolve(dir: string) {
 const { dependencies, devDependencies, name, version } = pkg;
 const __APP_INFO__ = {
   pkg: { dependencies, devDependencies, name, version },
-  lastBuildTime: moment().format('YYYY-MM-DD HH:mm:ss'),
+  lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
 };
 
 export default ({ command, mode }: ConfigEnv): UserConfig => {
@@ -60,7 +60,9 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
       proxy: createProxy(VITE_PROXY),
     },
     build: {
-      target: 'es2015',
+      minify: false,
+      // target: 'es2015',
+      // cssTarget: 'chrome86',
       outDir: OUTPUT_DIR,
       terserOptions: {
         compress: {
@@ -95,13 +97,12 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
     optimizeDeps: {
       // @iconify/iconify: The dependency is dynamically and virtually loaded by @purge-icons/generated, so it needs to be specified explicitly
       include: [
+        '@vue/runtime-core',
+        '@vue/shared',
         '@iconify/iconify',
         'ant-design-vue/es/locale/zh_CN',
-        'moment/dist/locale/zh-cn',
         'ant-design-vue/es/locale/en_US',
-        'moment/dist/locale/eu',
       ],
-      exclude: ['vue-demi', 'consolidate'],
     },
   };
 };