Yansen vor 2 Jahren
Ursprung
Commit
2f54f1b7ff
42 geänderte Dateien mit 1356 neuen und 242 gelöschten Zeilen
  1. 4
    0
      package.json
  2. 626
    1
      pnpm-lock.yaml
  3. 15
    0
      src/components/EditableTag/Tag.jsx
  4. 21
    0
      src/components/EditableTag/index.jsx
  5. 27
    0
      src/components/EditableTag/style.less
  6. 4
    0
      src/components/Money/float.js
  7. 30
    0
      src/components/Money/index.jsx
  8. 87
    0
      src/components/Wangeditor/index.jsx
  9. 0
    10
      src/components/page/Container.jsx
  10. 0
    14
      src/components/page/index.jsx
  11. 0
    5
      src/components/page/style.less
  12. 6
    1
      src/index.less
  13. 17
    18
      src/layouts/AuthLayout/components/Container.jsx
  14. 7
    6
      src/layouts/AuthLayout/components/Footer.jsx
  15. 21
    2
      src/layouts/AuthLayout/components/Header/Exit.jsx
  16. 3
    5
      src/layouts/AuthLayout/components/Header/Title.jsx
  17. 2
    2
      src/layouts/AuthLayout/components/Header/User.jsx
  18. 3
    6
      src/layouts/AuthLayout/components/Header/index.jsx
  19. 1
    3
      src/layouts/AuthLayout/components/Logo.jsx
  20. 15
    22
      src/layouts/AuthLayout/components/Menus.jsx
  21. 1
    1
      src/layouts/AuthLayout/components/PageTransition/index.jsx
  22. 16
    8
      src/layouts/AuthLayout/components/RequireLogin.jsx
  23. 3
    4
      src/layouts/AuthLayout/components/SiderBar.jsx
  24. 19
    21
      src/layouts/AuthLayout/index.jsx
  25. 30
    24
      src/layouts/AuthLayout/style.less
  26. 0
    14
      src/layouts/AuthLayout/useReady.jsx
  27. 23
    0
      src/layouts/PageContainer.jsx
  28. 1
    2
      src/pages/sample/form/index.jsx
  29. 2
    3
      src/pages/sample/home/index.jsx
  30. 4
    3
      src/pages/sample/table/index.jsx
  31. 13
    2
      src/routes/Router.jsx
  32. 21
    31
      src/routes/menus.jsx
  33. 14
    0
      src/routes/permissions.js
  34. 58
    18
      src/routes/routes.jsx
  35. 1
    5
      src/store/models/system.js
  36. 27
    7
      src/store/models/user.js
  37. 61
    0
      src/utils/array.js
  38. 5
    0
      src/utils/float.js
  39. 13
    0
      src/utils/hooks/useBool.js
  40. 1
    4
      src/utils/hooks/useRoute.jsx
  41. 151
    0
      src/utils/request.js
  42. 3
    0
      vite.config.js

+ 4
- 0
package.json Datei anzeigen

@@ -11,10 +11,14 @@
11 11
   "dependencies": {
12 12
     "@ant-design/icons": "^4.7.0",
13 13
     "@ant-design/pro-components": "^2.3.13",
14
+    "@wangeditor/editor": "^5.1.23",
15
+    "@wangeditor/editor-for-react": "^1.0.6",
14 16
     "@zjxpcyc/react-tiny-store": "^2.0.1",
15 17
     "antd": "^4.23.4",
18
+    "axios": "^1.2.0",
16 19
     "classnames": "^2.3.2",
17 20
     "echarts": "^5.4.0",
21
+    "md5": "^2.3.0",
18 22
     "react": "18.1.0",
19 23
     "react-dom": "18.1.0",
20 24
     "react-helmet": "^6.1.0",

+ 626
- 1
pnpm-lock.yaml Datei anzeigen

@@ -6,11 +6,15 @@ specifiers:
6 6
   '@types/react': ^18.0.15
7 7
   '@types/react-dom': ^18.0.6
8 8
   '@vitejs/plugin-react': ^2.0.0
9
+  '@wangeditor/editor': ^5.1.23
10
+  '@wangeditor/editor-for-react': ^1.0.6
9 11
   '@zjxpcyc/react-tiny-store': ^2.0.1
10 12
   antd: ^4.23.4
13
+  axios: ^1.2.0
11 14
   classnames: ^2.3.2
12 15
   echarts: ^5.4.0
13 16
   less: ^4.1.3
17
+  md5: ^2.3.0
14 18
   react: 18.1.0
15 19
   react-dom: 18.1.0
16 20
   react-helmet: ^6.1.0
@@ -22,10 +26,14 @@ specifiers:
22 26
 dependencies:
23 27
   '@ant-design/icons': registry.npmmirror.com/@ant-design/icons/4.7.0_ef5jwxihqo6n7gxfmzogljlgcm
24 28
   '@ant-design/pro-components': registry.npmmirror.com/@ant-design/pro-components/2.3.13_4ahbtacxshq5zvmbq25uec6w6a
29
+  '@wangeditor/editor': registry.npmmirror.com/@wangeditor/editor/5.1.23
30
+  '@wangeditor/editor-for-react': registry.npmmirror.com/@wangeditor/editor-for-react/1.0.6_ziin7aqlteivrij4ag3ltbri4m
25 31
   '@zjxpcyc/react-tiny-store': registry.npmmirror.com/@zjxpcyc/react-tiny-store/2.0.1
26 32
   antd: registry.npmmirror.com/antd/4.23.4_ef5jwxihqo6n7gxfmzogljlgcm
33
+  axios: registry.npmmirror.com/axios/1.2.0
27 34
   classnames: registry.npmmirror.com/classnames/2.3.2
28 35
   echarts: registry.npmmirror.com/echarts/5.4.0
36
+  md5: registry.npmmirror.com/md5/2.3.0
29 37
   react: registry.npmmirror.com/react/18.1.0
30 38
   react-dom: registry.npmmirror.com/react-dom/18.1.0_react@18.1.0
31 39
   react-helmet: registry.npmmirror.com/react-helmet/6.1.0_react@18.1.0
@@ -841,6 +849,18 @@ packages:
841 849
     engines: {node: '>=14'}
842 850
     dev: false
843 851
 
852
+  registry.npmmirror.com/@transloadit/prettier-bytes/0.0.7:
853
+    resolution: {integrity: sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz}
854
+    name: '@transloadit/prettier-bytes'
855
+    version: 0.0.7
856
+    dev: false
857
+
858
+  registry.npmmirror.com/@types/event-emitter/0.3.3:
859
+    resolution: {integrity: sha512-UfnOK1pIxO7P+EgPRZXD9jMpimd8QEFcEZ5R67R1UhGbv4zghU5+NE7U8M8G9H5Jc8FI51rqDWQs6FtUfq2e/Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/event-emitter/-/event-emitter-0.3.3.tgz}
860
+    name: '@types/event-emitter'
861
+    version: 0.3.3
862
+    dev: false
863
+
844 864
   registry.npmmirror.com/@types/prop-types/15.7.5:
845 865
     resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/prop-types/-/prop-types-15.7.5.tgz}
846 866
     name: '@types/prop-types'
@@ -899,6 +919,58 @@ packages:
899 919
       react: registry.npmmirror.com/react/18.1.0
900 920
     dev: false
901 921
 
922
+  registry.npmmirror.com/@uppy/companion-client/2.2.2:
923
+    resolution: {integrity: sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@uppy/companion-client/-/companion-client-2.2.2.tgz}
924
+    name: '@uppy/companion-client'
925
+    version: 2.2.2
926
+    dependencies:
927
+      '@uppy/utils': registry.npmmirror.com/@uppy/utils/4.1.3
928
+      namespace-emitter: registry.npmmirror.com/namespace-emitter/2.0.1
929
+    dev: false
930
+
931
+  registry.npmmirror.com/@uppy/core/2.3.4:
932
+    resolution: {integrity: sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@uppy/core/-/core-2.3.4.tgz}
933
+    name: '@uppy/core'
934
+    version: 2.3.4
935
+    dependencies:
936
+      '@transloadit/prettier-bytes': registry.npmmirror.com/@transloadit/prettier-bytes/0.0.7
937
+      '@uppy/store-default': registry.npmmirror.com/@uppy/store-default/2.1.1
938
+      '@uppy/utils': registry.npmmirror.com/@uppy/utils/4.1.3
939
+      lodash.throttle: registry.npmmirror.com/lodash.throttle/4.1.1
940
+      mime-match: registry.npmmirror.com/mime-match/1.0.2
941
+      namespace-emitter: registry.npmmirror.com/namespace-emitter/2.0.1
942
+      nanoid: registry.npmmirror.com/nanoid/3.3.4
943
+      preact: registry.npmmirror.com/preact/10.11.3
944
+    dev: false
945
+
946
+  registry.npmmirror.com/@uppy/store-default/2.1.1:
947
+    resolution: {integrity: sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@uppy/store-default/-/store-default-2.1.1.tgz}
948
+    name: '@uppy/store-default'
949
+    version: 2.1.1
950
+    dev: false
951
+
952
+  registry.npmmirror.com/@uppy/utils/4.1.3:
953
+    resolution: {integrity: sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@uppy/utils/-/utils-4.1.3.tgz}
954
+    name: '@uppy/utils'
955
+    version: 4.1.3
956
+    dependencies:
957
+      lodash.throttle: registry.npmmirror.com/lodash.throttle/4.1.1
958
+    dev: false
959
+
960
+  registry.npmmirror.com/@uppy/xhr-upload/2.1.3_@uppy+core@2.3.4:
961
+    resolution: {integrity: sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz}
962
+    id: registry.npmmirror.com/@uppy/xhr-upload/2.1.3
963
+    name: '@uppy/xhr-upload'
964
+    version: 2.1.3
965
+    peerDependencies:
966
+      '@uppy/core': ^2.3.3
967
+    dependencies:
968
+      '@uppy/companion-client': registry.npmmirror.com/@uppy/companion-client/2.2.2
969
+      '@uppy/core': registry.npmmirror.com/@uppy/core/2.3.4
970
+      '@uppy/utils': registry.npmmirror.com/@uppy/utils/4.1.3
971
+      nanoid: registry.npmmirror.com/nanoid/3.3.4
972
+    dev: false
973
+
902 974
   registry.npmmirror.com/@vitejs/plugin-react/2.0.0_vite@3.0.4:
903 975
     resolution: {integrity: sha512-zHkRR+X4zqEPNBbKV2FvWSxK7Q6crjMBVIAYroSU8Nbb4M3E5x4qOiLoqJBHtXgr27kfednXjkwr3lr8jS6Wrw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-2.0.0.tgz}
904 976
     id: registry.npmmirror.com/@vitejs/plugin-react/2.0.0
@@ -920,6 +992,221 @@ packages:
920 992
       - supports-color
921 993
     dev: true
922 994
 
995
+  registry.npmmirror.com/@wangeditor/basic-modules/1.1.7_j7icpicfeimtkldwmemjnpdjs4:
996
+    resolution: {integrity: sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz}
997
+    id: registry.npmmirror.com/@wangeditor/basic-modules/1.1.7
998
+    name: '@wangeditor/basic-modules'
999
+    version: 1.1.7
1000
+    peerDependencies:
1001
+      '@wangeditor/core': 1.x
1002
+      dom7: ^3.0.0
1003
+      lodash.throttle: ^4.1.1
1004
+      nanoid: ^3.2.0
1005
+      slate: ^0.72.0
1006
+      snabbdom: ^3.1.0
1007
+    dependencies:
1008
+      '@wangeditor/core': registry.npmmirror.com/@wangeditor/core/1.1.19_qokc4m5r26t2nkvzejrgzroa7e
1009
+      dom7: registry.npmmirror.com/dom7/3.0.0
1010
+      is-url: registry.npmmirror.com/is-url/1.2.4
1011
+      lodash.throttle: registry.npmmirror.com/lodash.throttle/4.1.1
1012
+      nanoid: registry.npmmirror.com/nanoid/3.3.4
1013
+      slate: registry.npmmirror.com/slate/0.72.8
1014
+      snabbdom: registry.npmmirror.com/snabbdom/3.5.1
1015
+    dev: false
1016
+
1017
+  registry.npmmirror.com/@wangeditor/code-highlight/1.0.3_tztyh2vh7kwzpeloifaekkk3my:
1018
+    resolution: {integrity: sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@wangeditor/code-highlight/-/code-highlight-1.0.3.tgz}
1019
+    id: registry.npmmirror.com/@wangeditor/code-highlight/1.0.3
1020
+    name: '@wangeditor/code-highlight'
1021
+    version: 1.0.3
1022
+    peerDependencies:
1023
+      '@wangeditor/core': 1.x
1024
+      dom7: ^3.0.0
1025
+      slate: ^0.72.0
1026
+      snabbdom: ^3.1.0
1027
+    dependencies:
1028
+      '@wangeditor/core': registry.npmmirror.com/@wangeditor/core/1.1.19_qokc4m5r26t2nkvzejrgzroa7e
1029
+      dom7: registry.npmmirror.com/dom7/3.0.0
1030
+      prismjs: registry.npmmirror.com/prismjs/1.29.0
1031
+      slate: registry.npmmirror.com/slate/0.72.8
1032
+      snabbdom: registry.npmmirror.com/snabbdom/3.5.1
1033
+    dev: false
1034
+
1035
+  registry.npmmirror.com/@wangeditor/core/1.1.19_qokc4m5r26t2nkvzejrgzroa7e:
1036
+    resolution: {integrity: sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@wangeditor/core/-/core-1.1.19.tgz}
1037
+    id: registry.npmmirror.com/@wangeditor/core/1.1.19
1038
+    name: '@wangeditor/core'
1039
+    version: 1.1.19
1040
+    peerDependencies:
1041
+      '@uppy/core': ^2.1.1
1042
+      '@uppy/xhr-upload': ^2.0.3
1043
+      dom7: ^3.0.0
1044
+      is-hotkey: ^0.2.0
1045
+      lodash.camelcase: ^4.3.0
1046
+      lodash.clonedeep: ^4.5.0
1047
+      lodash.debounce: ^4.0.8
1048
+      lodash.foreach: ^4.5.0
1049
+      lodash.isequal: ^4.5.0
1050
+      lodash.throttle: ^4.1.1
1051
+      lodash.toarray: ^4.4.0
1052
+      nanoid: ^3.2.0
1053
+      slate: ^0.72.0
1054
+      snabbdom: ^3.1.0
1055
+    dependencies:
1056
+      '@types/event-emitter': registry.npmmirror.com/@types/event-emitter/0.3.3
1057
+      '@uppy/core': registry.npmmirror.com/@uppy/core/2.3.4
1058
+      '@uppy/xhr-upload': registry.npmmirror.com/@uppy/xhr-upload/2.1.3_@uppy+core@2.3.4
1059
+      dom7: registry.npmmirror.com/dom7/3.0.0
1060
+      event-emitter: registry.npmmirror.com/event-emitter/0.3.5
1061
+      html-void-elements: registry.npmmirror.com/html-void-elements/2.0.1
1062
+      i18next: registry.npmmirror.com/i18next/20.6.1
1063
+      is-hotkey: registry.npmmirror.com/is-hotkey/0.2.0
1064
+      lodash.camelcase: registry.npmmirror.com/lodash.camelcase/4.3.0
1065
+      lodash.clonedeep: registry.npmmirror.com/lodash.clonedeep/4.5.0
1066
+      lodash.debounce: registry.npmmirror.com/lodash.debounce/4.0.8
1067
+      lodash.foreach: registry.npmmirror.com/lodash.foreach/4.5.0
1068
+      lodash.isequal: registry.npmmirror.com/lodash.isequal/4.5.0
1069
+      lodash.throttle: registry.npmmirror.com/lodash.throttle/4.1.1
1070
+      lodash.toarray: registry.npmmirror.com/lodash.toarray/4.4.0
1071
+      nanoid: registry.npmmirror.com/nanoid/3.3.4
1072
+      scroll-into-view-if-needed: registry.npmmirror.com/scroll-into-view-if-needed/2.2.29
1073
+      slate: registry.npmmirror.com/slate/0.72.8
1074
+      slate-history: registry.npmmirror.com/slate-history/0.66.0_slate@0.72.8
1075
+      snabbdom: registry.npmmirror.com/snabbdom/3.5.1
1076
+    dev: false
1077
+
1078
+  registry.npmmirror.com/@wangeditor/editor-for-react/1.0.6_ziin7aqlteivrij4ag3ltbri4m:
1079
+    resolution: {integrity: sha512-KJNSfgMr5Blzae3oyaiz20flMKHZHnvsz4bCYQKDCUs/qkvC+xNTnwedlCmhGP187oPWPEypCIYI8Zg6sz0psQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@wangeditor/editor-for-react/-/editor-for-react-1.0.6.tgz}
1080
+    id: registry.npmmirror.com/@wangeditor/editor-for-react/1.0.6
1081
+    name: '@wangeditor/editor-for-react'
1082
+    version: 1.0.6
1083
+    peerDependencies:
1084
+      '@wangeditor/core': '>=1.1.0'
1085
+      '@wangeditor/editor': '>=5.1.0'
1086
+      react: '>=17.0.2'
1087
+      react-dom: '>=17.0.2'
1088
+    dependencies:
1089
+      '@wangeditor/editor': registry.npmmirror.com/@wangeditor/editor/5.1.23
1090
+      react: registry.npmmirror.com/react/18.1.0
1091
+      react-dom: registry.npmmirror.com/react-dom/18.1.0_react@18.1.0
1092
+    dev: false
1093
+
1094
+  registry.npmmirror.com/@wangeditor/editor/5.1.23:
1095
+    resolution: {integrity: sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@wangeditor/editor/-/editor-5.1.23.tgz}
1096
+    name: '@wangeditor/editor'
1097
+    version: 5.1.23
1098
+    dependencies:
1099
+      '@uppy/core': registry.npmmirror.com/@uppy/core/2.3.4
1100
+      '@uppy/xhr-upload': registry.npmmirror.com/@uppy/xhr-upload/2.1.3_@uppy+core@2.3.4
1101
+      '@wangeditor/basic-modules': registry.npmmirror.com/@wangeditor/basic-modules/1.1.7_j7icpicfeimtkldwmemjnpdjs4
1102
+      '@wangeditor/code-highlight': registry.npmmirror.com/@wangeditor/code-highlight/1.0.3_tztyh2vh7kwzpeloifaekkk3my
1103
+      '@wangeditor/core': registry.npmmirror.com/@wangeditor/core/1.1.19_qokc4m5r26t2nkvzejrgzroa7e
1104
+      '@wangeditor/list-module': registry.npmmirror.com/@wangeditor/list-module/1.0.5_tztyh2vh7kwzpeloifaekkk3my
1105
+      '@wangeditor/table-module': registry.npmmirror.com/@wangeditor/table-module/1.1.4_2dde2uzwslfxq2cqrl35sl4erm
1106
+      '@wangeditor/upload-image-module': registry.npmmirror.com/@wangeditor/upload-image-module/1.0.2_dwqga4onuah5imhngzkgmw6t5a
1107
+      '@wangeditor/video-module': registry.npmmirror.com/@wangeditor/video-module/1.1.4_i6gxywmu7tvxmjxypclnjlcil4
1108
+      dom7: registry.npmmirror.com/dom7/3.0.0
1109
+      is-hotkey: registry.npmmirror.com/is-hotkey/0.2.0
1110
+      lodash.camelcase: registry.npmmirror.com/lodash.camelcase/4.3.0
1111
+      lodash.clonedeep: registry.npmmirror.com/lodash.clonedeep/4.5.0
1112
+      lodash.debounce: registry.npmmirror.com/lodash.debounce/4.0.8
1113
+      lodash.foreach: registry.npmmirror.com/lodash.foreach/4.5.0
1114
+      lodash.isequal: registry.npmmirror.com/lodash.isequal/4.5.0
1115
+      lodash.throttle: registry.npmmirror.com/lodash.throttle/4.1.1
1116
+      lodash.toarray: registry.npmmirror.com/lodash.toarray/4.4.0
1117
+      nanoid: registry.npmmirror.com/nanoid/3.3.4
1118
+      slate: registry.npmmirror.com/slate/0.72.8
1119
+      snabbdom: registry.npmmirror.com/snabbdom/3.5.1
1120
+    dev: false
1121
+
1122
+  registry.npmmirror.com/@wangeditor/list-module/1.0.5_tztyh2vh7kwzpeloifaekkk3my:
1123
+    resolution: {integrity: sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@wangeditor/list-module/-/list-module-1.0.5.tgz}
1124
+    id: registry.npmmirror.com/@wangeditor/list-module/1.0.5
1125
+    name: '@wangeditor/list-module'
1126
+    version: 1.0.5
1127
+    peerDependencies:
1128
+      '@wangeditor/core': 1.x
1129
+      dom7: ^3.0.0
1130
+      slate: ^0.72.0
1131
+      snabbdom: ^3.1.0
1132
+    dependencies:
1133
+      '@wangeditor/core': registry.npmmirror.com/@wangeditor/core/1.1.19_qokc4m5r26t2nkvzejrgzroa7e
1134
+      dom7: registry.npmmirror.com/dom7/3.0.0
1135
+      slate: registry.npmmirror.com/slate/0.72.8
1136
+      snabbdom: registry.npmmirror.com/snabbdom/3.5.1
1137
+    dev: false
1138
+
1139
+  registry.npmmirror.com/@wangeditor/table-module/1.1.4_2dde2uzwslfxq2cqrl35sl4erm:
1140
+    resolution: {integrity: sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@wangeditor/table-module/-/table-module-1.1.4.tgz}
1141
+    id: registry.npmmirror.com/@wangeditor/table-module/1.1.4
1142
+    name: '@wangeditor/table-module'
1143
+    version: 1.1.4
1144
+    peerDependencies:
1145
+      '@wangeditor/core': 1.x
1146
+      dom7: ^3.0.0
1147
+      lodash.isequal: ^4.5.0
1148
+      lodash.throttle: ^4.1.1
1149
+      nanoid: ^3.2.0
1150
+      slate: ^0.72.0
1151
+      snabbdom: ^3.1.0
1152
+    dependencies:
1153
+      '@wangeditor/core': registry.npmmirror.com/@wangeditor/core/1.1.19_qokc4m5r26t2nkvzejrgzroa7e
1154
+      dom7: registry.npmmirror.com/dom7/3.0.0
1155
+      lodash.isequal: registry.npmmirror.com/lodash.isequal/4.5.0
1156
+      lodash.throttle: registry.npmmirror.com/lodash.throttle/4.1.1
1157
+      nanoid: registry.npmmirror.com/nanoid/3.3.4
1158
+      slate: registry.npmmirror.com/slate/0.72.8
1159
+      snabbdom: registry.npmmirror.com/snabbdom/3.5.1
1160
+    dev: false
1161
+
1162
+  registry.npmmirror.com/@wangeditor/upload-image-module/1.0.2_dwqga4onuah5imhngzkgmw6t5a:
1163
+    resolution: {integrity: sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@wangeditor/upload-image-module/-/upload-image-module-1.0.2.tgz}
1164
+    id: registry.npmmirror.com/@wangeditor/upload-image-module/1.0.2
1165
+    name: '@wangeditor/upload-image-module'
1166
+    version: 1.0.2
1167
+    peerDependencies:
1168
+      '@uppy/core': ^2.0.3
1169
+      '@uppy/xhr-upload': ^2.0.3
1170
+      '@wangeditor/basic-modules': 1.x
1171
+      '@wangeditor/core': 1.x
1172
+      dom7: ^3.0.0
1173
+      lodash.foreach: ^4.5.0
1174
+      slate: ^0.72.0
1175
+      snabbdom: ^3.1.0
1176
+    dependencies:
1177
+      '@uppy/core': registry.npmmirror.com/@uppy/core/2.3.4
1178
+      '@uppy/xhr-upload': registry.npmmirror.com/@uppy/xhr-upload/2.1.3_@uppy+core@2.3.4
1179
+      '@wangeditor/basic-modules': registry.npmmirror.com/@wangeditor/basic-modules/1.1.7_j7icpicfeimtkldwmemjnpdjs4
1180
+      '@wangeditor/core': registry.npmmirror.com/@wangeditor/core/1.1.19_qokc4m5r26t2nkvzejrgzroa7e
1181
+      dom7: registry.npmmirror.com/dom7/3.0.0
1182
+      lodash.foreach: registry.npmmirror.com/lodash.foreach/4.5.0
1183
+      slate: registry.npmmirror.com/slate/0.72.8
1184
+      snabbdom: registry.npmmirror.com/snabbdom/3.5.1
1185
+    dev: false
1186
+
1187
+  registry.npmmirror.com/@wangeditor/video-module/1.1.4_i6gxywmu7tvxmjxypclnjlcil4:
1188
+    resolution: {integrity: sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@wangeditor/video-module/-/video-module-1.1.4.tgz}
1189
+    id: registry.npmmirror.com/@wangeditor/video-module/1.1.4
1190
+    name: '@wangeditor/video-module'
1191
+    version: 1.1.4
1192
+    peerDependencies:
1193
+      '@uppy/core': ^2.1.4
1194
+      '@uppy/xhr-upload': ^2.0.7
1195
+      '@wangeditor/core': 1.x
1196
+      dom7: ^3.0.0
1197
+      nanoid: ^3.2.0
1198
+      slate: ^0.72.0
1199
+      snabbdom: ^3.1.0
1200
+    dependencies:
1201
+      '@uppy/core': registry.npmmirror.com/@uppy/core/2.3.4
1202
+      '@uppy/xhr-upload': registry.npmmirror.com/@uppy/xhr-upload/2.1.3_@uppy+core@2.3.4
1203
+      '@wangeditor/core': registry.npmmirror.com/@wangeditor/core/1.1.19_qokc4m5r26t2nkvzejrgzroa7e
1204
+      dom7: registry.npmmirror.com/dom7/3.0.0
1205
+      nanoid: registry.npmmirror.com/nanoid/3.3.4
1206
+      slate: registry.npmmirror.com/slate/0.72.8
1207
+      snabbdom: registry.npmmirror.com/snabbdom/3.5.1
1208
+    dev: false
1209
+
923 1210
   registry.npmmirror.com/@zjxpcyc/react-tiny-store/2.0.1:
924 1211
     resolution: {integrity: sha512-+MTTcQ9aU8OMl7YrmX8UVnM5qUDktdHl0wpxmI5dVIwZxvHsKRKZuQn+ExOeCvJAVC2l+ubS7afT9rzTHPuPrA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@zjxpcyc/react-tiny-store/-/react-tiny-store-2.0.1.tgz}
925 1212
     name: '@zjxpcyc/react-tiny-store'
@@ -1021,6 +1308,24 @@ packages:
1021 1308
     version: 4.2.5
1022 1309
     dev: false
1023 1310
 
1311
+  registry.npmmirror.com/asynckit/0.4.0:
1312
+    resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz}
1313
+    name: asynckit
1314
+    version: 0.4.0
1315
+    dev: false
1316
+
1317
+  registry.npmmirror.com/axios/1.2.0:
1318
+    resolution: {integrity: sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/axios/-/axios-1.2.0.tgz}
1319
+    name: axios
1320
+    version: 1.2.0
1321
+    dependencies:
1322
+      follow-redirects: registry.npmmirror.com/follow-redirects/1.15.2
1323
+      form-data: registry.npmmirror.com/form-data/4.0.0
1324
+      proxy-from-env: registry.npmmirror.com/proxy-from-env/1.1.0
1325
+    transitivePeerDependencies:
1326
+      - debug
1327
+    dev: false
1328
+
1024 1329
   registry.npmmirror.com/browserslist/4.21.3:
1025 1330
     resolution: {integrity: sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/browserslist/-/browserslist-4.21.3.tgz}
1026 1331
     name: browserslist
@@ -1061,6 +1366,12 @@ packages:
1061 1366
       supports-color: registry.npmmirror.com/supports-color/7.2.0
1062 1367
     dev: true
1063 1368
 
1369
+  registry.npmmirror.com/charenc/0.0.2:
1370
+    resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/charenc/-/charenc-0.0.2.tgz}
1371
+    name: charenc
1372
+    version: 0.0.2
1373
+    dev: false
1374
+
1064 1375
   registry.npmmirror.com/classnames/2.3.2:
1065 1376
     resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/classnames/-/classnames-2.3.2.tgz}
1066 1377
     name: classnames
@@ -1096,6 +1407,15 @@ packages:
1096 1407
     version: 1.1.4
1097 1408
     dev: true
1098 1409
 
1410
+  registry.npmmirror.com/combined-stream/1.0.8:
1411
+    resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz}
1412
+    name: combined-stream
1413
+    version: 1.0.8
1414
+    engines: {node: '>= 0.8'}
1415
+    dependencies:
1416
+      delayed-stream: registry.npmmirror.com/delayed-stream/1.0.0
1417
+    dev: false
1418
+
1099 1419
   registry.npmmirror.com/compute-scroll-into-view/1.0.17:
1100 1420
     resolution: {integrity: sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz}
1101 1421
     name: compute-scroll-into-view
@@ -1126,11 +1446,26 @@ packages:
1126 1446
       toggle-selection: registry.npmmirror.com/toggle-selection/1.0.6
1127 1447
     dev: false
1128 1448
 
1449
+  registry.npmmirror.com/crypt/0.0.2:
1450
+    resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/crypt/-/crypt-0.0.2.tgz}
1451
+    name: crypt
1452
+    version: 0.0.2
1453
+    dev: false
1454
+
1129 1455
   registry.npmmirror.com/csstype/3.1.0:
1130 1456
     resolution: {integrity: sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/csstype/-/csstype-3.1.0.tgz}
1131 1457
     name: csstype
1132 1458
     version: 3.1.0
1133 1459
 
1460
+  registry.npmmirror.com/d/1.0.1:
1461
+    resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/d/-/d-1.0.1.tgz}
1462
+    name: d
1463
+    version: 1.0.1
1464
+    dependencies:
1465
+      es5-ext: registry.npmmirror.com/es5-ext/0.10.62
1466
+      type: registry.npmmirror.com/type/1.2.0
1467
+    dev: false
1468
+
1134 1469
   registry.npmmirror.com/date-fns/2.29.1:
1135 1470
     resolution: {integrity: sha512-dlLD5rKaKxpFdnjrs+5azHDFOPEu4ANy/LTh04A1DTzMM7qoajmKCBc8pkKRFT41CNzw+4gQh79X5C+Jq27HAw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/date-fns/-/date-fns-2.29.1.tgz}
1136 1471
     name: date-fns
@@ -1172,6 +1507,13 @@ packages:
1172 1507
       ms: registry.npmmirror.com/ms/2.1.2
1173 1508
     dev: true
1174 1509
 
1510
+  registry.npmmirror.com/delayed-stream/1.0.0:
1511
+    resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz}
1512
+    name: delayed-stream
1513
+    version: 1.0.0
1514
+    engines: {node: '>=0.4.0'}
1515
+    dev: false
1516
+
1175 1517
   registry.npmmirror.com/dom-align/1.12.3:
1176 1518
     resolution: {integrity: sha512-Gj9hZN3a07cbR6zviMUBOMPdWxYhbMI+x+WS0NAIu2zFZmbK8ys9R79g+iG9qLnlCwpFoaB+fKy8Pdv470GsPA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/dom-align/-/dom-align-1.12.3.tgz}
1177 1519
     name: dom-align
@@ -1187,6 +1529,14 @@ packages:
1187 1529
       csstype: registry.npmmirror.com/csstype/3.1.0
1188 1530
     dev: false
1189 1531
 
1532
+  registry.npmmirror.com/dom7/3.0.0:
1533
+    resolution: {integrity: sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/dom7/-/dom7-3.0.0.tgz}
1534
+    name: dom7
1535
+    version: 3.0.0
1536
+    dependencies:
1537
+      ssr-window: registry.npmmirror.com/ssr-window/3.0.0
1538
+    dev: false
1539
+
1190 1540
   registry.npmmirror.com/dot-case/3.0.4:
1191 1541
     resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/dot-case/-/dot-case-3.0.4.tgz}
1192 1542
     name: dot-case
@@ -1222,6 +1572,37 @@ packages:
1222 1572
     dev: true
1223 1573
     optional: true
1224 1574
 
1575
+  registry.npmmirror.com/es5-ext/0.10.62:
1576
+    resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/es5-ext/-/es5-ext-0.10.62.tgz}
1577
+    name: es5-ext
1578
+    version: 0.10.62
1579
+    engines: {node: '>=0.10'}
1580
+    requiresBuild: true
1581
+    dependencies:
1582
+      es6-iterator: registry.npmmirror.com/es6-iterator/2.0.3
1583
+      es6-symbol: registry.npmmirror.com/es6-symbol/3.1.3
1584
+      next-tick: registry.npmmirror.com/next-tick/1.1.0
1585
+    dev: false
1586
+
1587
+  registry.npmmirror.com/es6-iterator/2.0.3:
1588
+    resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/es6-iterator/-/es6-iterator-2.0.3.tgz}
1589
+    name: es6-iterator
1590
+    version: 2.0.3
1591
+    dependencies:
1592
+      d: registry.npmmirror.com/d/1.0.1
1593
+      es5-ext: registry.npmmirror.com/es5-ext/0.10.62
1594
+      es6-symbol: registry.npmmirror.com/es6-symbol/3.1.3
1595
+    dev: false
1596
+
1597
+  registry.npmmirror.com/es6-symbol/3.1.3:
1598
+    resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/es6-symbol/-/es6-symbol-3.1.3.tgz}
1599
+    name: es6-symbol
1600
+    version: 3.1.3
1601
+    dependencies:
1602
+      d: registry.npmmirror.com/d/1.0.1
1603
+      ext: registry.npmmirror.com/ext/1.7.0
1604
+    dev: false
1605
+
1225 1606
   registry.npmmirror.com/esbuild-android-64/0.14.53:
1226 1607
     resolution: {integrity: sha512-fIL93sOTnEU+NrTAVMIKiAw0YH22HWCAgg4N4Z6zov2t0kY9RAJ50zY9ZMCQ+RT6bnOfDt8gCTnt/RaSNA2yRA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.14.53.tgz}
1227 1608
     name: esbuild-android-64
@@ -1487,12 +1868,52 @@ packages:
1487 1868
     engines: {node: '>=0.8.0'}
1488 1869
     dev: true
1489 1870
 
1871
+  registry.npmmirror.com/event-emitter/0.3.5:
1872
+    resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/event-emitter/-/event-emitter-0.3.5.tgz}
1873
+    name: event-emitter
1874
+    version: 0.3.5
1875
+    dependencies:
1876
+      d: registry.npmmirror.com/d/1.0.1
1877
+      es5-ext: registry.npmmirror.com/es5-ext/0.10.62
1878
+    dev: false
1879
+
1880
+  registry.npmmirror.com/ext/1.7.0:
1881
+    resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ext/-/ext-1.7.0.tgz}
1882
+    name: ext
1883
+    version: 1.7.0
1884
+    dependencies:
1885
+      type: registry.npmmirror.com/type/2.7.2
1886
+    dev: false
1887
+
1490 1888
   registry.npmmirror.com/fast-deep-equal/3.1.3:
1491 1889
     resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz}
1492 1890
     name: fast-deep-equal
1493 1891
     version: 3.1.3
1494 1892
     dev: false
1495 1893
 
1894
+  registry.npmmirror.com/follow-redirects/1.15.2:
1895
+    resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz}
1896
+    name: follow-redirects
1897
+    version: 1.15.2
1898
+    engines: {node: '>=4.0'}
1899
+    peerDependencies:
1900
+      debug: '*'
1901
+    peerDependenciesMeta:
1902
+      debug:
1903
+        optional: true
1904
+    dev: false
1905
+
1906
+  registry.npmmirror.com/form-data/4.0.0:
1907
+    resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz}
1908
+    name: form-data
1909
+    version: 4.0.0
1910
+    engines: {node: '>= 6'}
1911
+    dependencies:
1912
+      asynckit: registry.npmmirror.com/asynckit/0.4.0
1913
+      combined-stream: registry.npmmirror.com/combined-stream/1.0.8
1914
+      mime-types: registry.npmmirror.com/mime-types/2.1.35
1915
+    dev: false
1916
+
1496 1917
   registry.npmmirror.com/fsevents/2.3.2:
1497 1918
     resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz}
1498 1919
     name: fsevents
@@ -1554,6 +1975,20 @@ packages:
1554 1975
       function-bind: registry.npmmirror.com/function-bind/1.1.1
1555 1976
     dev: true
1556 1977
 
1978
+  registry.npmmirror.com/html-void-elements/2.0.1:
1979
+    resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/html-void-elements/-/html-void-elements-2.0.1.tgz}
1980
+    name: html-void-elements
1981
+    version: 2.0.1
1982
+    dev: false
1983
+
1984
+  registry.npmmirror.com/i18next/20.6.1:
1985
+    resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/i18next/-/i18next-20.6.1.tgz}
1986
+    name: i18next
1987
+    version: 20.6.1
1988
+    dependencies:
1989
+      '@babel/runtime': registry.npmmirror.com/@babel/runtime/7.18.9
1990
+    dev: false
1991
+
1557 1992
   registry.npmmirror.com/iconv-lite/0.6.3:
1558 1993
     resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz}
1559 1994
     name: iconv-lite
@@ -1574,6 +2009,12 @@ packages:
1574 2009
     dev: true
1575 2010
     optional: true
1576 2011
 
2012
+  registry.npmmirror.com/immer/9.0.16:
2013
+    resolution: {integrity: sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/immer/-/immer-9.0.16.tgz}
2014
+    name: immer
2015
+    version: 9.0.16
2016
+    dev: false
2017
+
1577 2018
   registry.npmmirror.com/invariant/2.2.4:
1578 2019
     resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/invariant/-/invariant-2.2.4.tgz}
1579 2020
     name: invariant
@@ -1582,6 +2023,12 @@ packages:
1582 2023
       loose-envify: registry.npmmirror.com/loose-envify/1.4.0
1583 2024
     dev: false
1584 2025
 
2026
+  registry.npmmirror.com/is-buffer/1.1.6:
2027
+    resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-buffer/-/is-buffer-1.1.6.tgz}
2028
+    name: is-buffer
2029
+    version: 1.1.6
2030
+    dev: false
2031
+
1585 2032
   registry.npmmirror.com/is-core-module/2.10.0:
1586 2033
     resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-core-module/-/is-core-module-2.10.0.tgz}
1587 2034
     name: is-core-module
@@ -1590,6 +2037,25 @@ packages:
1590 2037
       has: registry.npmmirror.com/has/1.0.3
1591 2038
     dev: true
1592 2039
 
2040
+  registry.npmmirror.com/is-hotkey/0.2.0:
2041
+    resolution: {integrity: sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-hotkey/-/is-hotkey-0.2.0.tgz}
2042
+    name: is-hotkey
2043
+    version: 0.2.0
2044
+    dev: false
2045
+
2046
+  registry.npmmirror.com/is-plain-object/5.0.0:
2047
+    resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-plain-object/-/is-plain-object-5.0.0.tgz}
2048
+    name: is-plain-object
2049
+    version: 5.0.0
2050
+    engines: {node: '>=0.10.0'}
2051
+    dev: false
2052
+
2053
+  registry.npmmirror.com/is-url/1.2.4:
2054
+    resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-url/-/is-url-1.2.4.tgz}
2055
+    name: is-url
2056
+    version: 1.2.4
2057
+    dev: false
2058
+
1593 2059
   registry.npmmirror.com/is-what/3.14.1:
1594 2060
     resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz}
1595 2061
     name: is-what
@@ -1647,6 +2113,30 @@ packages:
1647 2113
       - supports-color
1648 2114
     dev: true
1649 2115
 
2116
+  registry.npmmirror.com/lodash.camelcase/4.3.0:
2117
+    resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz}
2118
+    name: lodash.camelcase
2119
+    version: 4.3.0
2120
+    dev: false
2121
+
2122
+  registry.npmmirror.com/lodash.clonedeep/4.5.0:
2123
+    resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz}
2124
+    name: lodash.clonedeep
2125
+    version: 4.5.0
2126
+    dev: false
2127
+
2128
+  registry.npmmirror.com/lodash.debounce/4.0.8:
2129
+    resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz}
2130
+    name: lodash.debounce
2131
+    version: 4.0.8
2132
+    dev: false
2133
+
2134
+  registry.npmmirror.com/lodash.foreach/4.5.0:
2135
+    resolution: {integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz}
2136
+    name: lodash.foreach
2137
+    version: 4.5.0
2138
+    dev: false
2139
+
1650 2140
   registry.npmmirror.com/lodash.isequal/4.5.0:
1651 2141
     resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz}
1652 2142
     name: lodash.isequal
@@ -1665,6 +2155,18 @@ packages:
1665 2155
     version: 4.5.0
1666 2156
     dev: false
1667 2157
 
2158
+  registry.npmmirror.com/lodash.throttle/4.1.1:
2159
+    resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz}
2160
+    name: lodash.throttle
2161
+    version: 4.1.1
2162
+    dev: false
2163
+
2164
+  registry.npmmirror.com/lodash.toarray/4.4.0:
2165
+    resolution: {integrity: sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz}
2166
+    name: lodash.toarray
2167
+    version: 4.4.0
2168
+    dev: false
2169
+
1668 2170
   registry.npmmirror.com/lodash.tonumber/4.0.3:
1669 2171
     resolution: {integrity: sha512-SY0SwuPOHRwKcCNTdsntPYb+Zddz5mDUIVFABzRMqmAiL41pMeyoQFGxYAw5zdc9NnH4pbJqiqqp5ckfxa+zSA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lodash.tonumber/-/lodash.tonumber-4.0.3.tgz}
1670 2172
     name: lodash.tonumber
@@ -1715,6 +2217,16 @@ packages:
1715 2217
     dev: true
1716 2218
     optional: true
1717 2219
 
2220
+  registry.npmmirror.com/md5/2.3.0:
2221
+    resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/md5/-/md5-2.3.0.tgz}
2222
+    name: md5
2223
+    version: 2.3.0
2224
+    dependencies:
2225
+      charenc: registry.npmmirror.com/charenc/0.0.2
2226
+      crypt: registry.npmmirror.com/crypt/0.0.2
2227
+      is-buffer: registry.npmmirror.com/is-buffer/1.1.6
2228
+    dev: false
2229
+
1718 2230
   registry.npmmirror.com/memoize-one/5.2.1:
1719 2231
     resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/memoize-one/-/memoize-one-5.2.1.tgz}
1720 2232
     name: memoize-one
@@ -1727,6 +2239,30 @@ packages:
1727 2239
     version: 6.0.0
1728 2240
     dev: false
1729 2241
 
2242
+  registry.npmmirror.com/mime-db/1.52.0:
2243
+    resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz}
2244
+    name: mime-db
2245
+    version: 1.52.0
2246
+    engines: {node: '>= 0.6'}
2247
+    dev: false
2248
+
2249
+  registry.npmmirror.com/mime-match/1.0.2:
2250
+    resolution: {integrity: sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/mime-match/-/mime-match-1.0.2.tgz}
2251
+    name: mime-match
2252
+    version: 1.0.2
2253
+    dependencies:
2254
+      wildcard: registry.npmmirror.com/wildcard/1.1.2
2255
+    dev: false
2256
+
2257
+  registry.npmmirror.com/mime-types/2.1.35:
2258
+    resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz}
2259
+    name: mime-types
2260
+    version: 2.1.35
2261
+    engines: {node: '>= 0.6'}
2262
+    dependencies:
2263
+      mime-db: registry.npmmirror.com/mime-db/1.52.0
2264
+    dev: false
2265
+
1730 2266
   registry.npmmirror.com/mime/1.6.0:
1731 2267
     resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz}
1732 2268
     name: mime
@@ -1756,13 +2292,18 @@ packages:
1756 2292
     dev: true
1757 2293
     optional: true
1758 2294
 
2295
+  registry.npmmirror.com/namespace-emitter/2.0.1:
2296
+    resolution: {integrity: sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/namespace-emitter/-/namespace-emitter-2.0.1.tgz}
2297
+    name: namespace-emitter
2298
+    version: 2.0.1
2299
+    dev: false
2300
+
1759 2301
   registry.npmmirror.com/nanoid/3.3.4:
1760 2302
     resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz}
1761 2303
     name: nanoid
1762 2304
     version: 3.3.4
1763 2305
     engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
1764 2306
     hasBin: true
1765
-    dev: true
1766 2307
 
1767 2308
   registry.npmmirror.com/needle/3.1.0:
1768 2309
     resolution: {integrity: sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/needle/-/needle-3.1.0.tgz}
@@ -1780,6 +2321,12 @@ packages:
1780 2321
     dev: true
1781 2322
     optional: true
1782 2323
 
2324
+  registry.npmmirror.com/next-tick/1.1.0:
2325
+    resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/next-tick/-/next-tick-1.1.0.tgz}
2326
+    name: next-tick
2327
+    version: 1.1.0
2328
+    dev: false
2329
+
1783 2330
   registry.npmmirror.com/no-case/3.0.4:
1784 2331
     resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/no-case/-/no-case-3.0.4.tgz}
1785 2332
     name: no-case
@@ -1870,6 +2417,19 @@ packages:
1870 2417
       source-map-js: registry.npmmirror.com/source-map-js/1.0.2
1871 2418
     dev: true
1872 2419
 
2420
+  registry.npmmirror.com/preact/10.11.3:
2421
+    resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/preact/-/preact-10.11.3.tgz}
2422
+    name: preact
2423
+    version: 10.11.3
2424
+    dev: false
2425
+
2426
+  registry.npmmirror.com/prismjs/1.29.0:
2427
+    resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/prismjs/-/prismjs-1.29.0.tgz}
2428
+    name: prismjs
2429
+    version: 1.29.0
2430
+    engines: {node: '>=6'}
2431
+    dev: false
2432
+
1873 2433
   registry.npmmirror.com/prop-types/15.8.1:
1874 2434
     resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/prop-types/-/prop-types-15.8.1.tgz}
1875 2435
     name: prop-types
@@ -1880,6 +2440,12 @@ packages:
1880 2440
       react-is: registry.npmmirror.com/react-is/16.13.1
1881 2441
     dev: false
1882 2442
 
2443
+  registry.npmmirror.com/proxy-from-env/1.1.0:
2444
+    resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz}
2445
+    name: proxy-from-env
2446
+    version: 1.1.0
2447
+    dev: false
2448
+
1883 2449
   registry.npmmirror.com/prr/1.0.1:
1884 2450
     resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz}
1885 2451
     name: prr
@@ -2785,6 +3351,35 @@ packages:
2785 3351
     version: 1.1.0
2786 3352
     dev: false
2787 3353
 
3354
+  registry.npmmirror.com/slate-history/0.66.0_slate@0.72.8:
3355
+    resolution: {integrity: sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/slate-history/-/slate-history-0.66.0.tgz}
3356
+    id: registry.npmmirror.com/slate-history/0.66.0
3357
+    name: slate-history
3358
+    version: 0.66.0
3359
+    peerDependencies:
3360
+      slate: '>=0.65.3'
3361
+    dependencies:
3362
+      is-plain-object: registry.npmmirror.com/is-plain-object/5.0.0
3363
+      slate: registry.npmmirror.com/slate/0.72.8
3364
+    dev: false
3365
+
3366
+  registry.npmmirror.com/slate/0.72.8:
3367
+    resolution: {integrity: sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/slate/-/slate-0.72.8.tgz}
3368
+    name: slate
3369
+    version: 0.72.8
3370
+    dependencies:
3371
+      immer: registry.npmmirror.com/immer/9.0.16
3372
+      is-plain-object: registry.npmmirror.com/is-plain-object/5.0.0
3373
+      tiny-warning: registry.npmmirror.com/tiny-warning/1.0.3
3374
+    dev: false
3375
+
3376
+  registry.npmmirror.com/snabbdom/3.5.1:
3377
+    resolution: {integrity: sha512-wHMNIOjkm/YNE5EM3RCbr/+DVgPg6AqQAX1eOxO46zYNvCXjKP5Y865tqQj3EXnaMBjkxmQA5jFuDpDK/dbfiA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/snabbdom/-/snabbdom-3.5.1.tgz}
3378
+    name: snabbdom
3379
+    version: 3.5.1
3380
+    engines: {node: '>=8.3.0'}
3381
+    dev: false
3382
+
2788 3383
   registry.npmmirror.com/source-map-js/1.0.2:
2789 3384
     resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz}
2790 3385
     name: source-map-js
@@ -2807,6 +3402,12 @@ packages:
2807 3402
     version: 1.4.8
2808 3403
     dev: true
2809 3404
 
3405
+  registry.npmmirror.com/ssr-window/3.0.0:
3406
+    resolution: {integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ssr-window/-/ssr-window-3.0.0.tgz}
3407
+    name: ssr-window
3408
+    version: 3.0.0
3409
+    dev: false
3410
+
2810 3411
   registry.npmmirror.com/string-convert/0.2.1:
2811 3412
     resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/string-convert/-/string-convert-0.2.1.tgz}
2812 3413
     name: string-convert
@@ -2855,6 +3456,12 @@ packages:
2855 3456
       react: registry.npmmirror.com/react/18.1.0
2856 3457
     dev: false
2857 3458
 
3459
+  registry.npmmirror.com/tiny-warning/1.0.3:
3460
+    resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/tiny-warning/-/tiny-warning-1.0.3.tgz}
3461
+    name: tiny-warning
3462
+    version: 1.0.3
3463
+    dev: false
3464
+
2858 3465
   registry.npmmirror.com/tinycolor2/1.4.2:
2859 3466
     resolution: {integrity: sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.4.2.tgz}
2860 3467
     name: tinycolor2
@@ -2886,6 +3493,18 @@ packages:
2886 3493
     version: 2.4.0
2887 3494
     dev: true
2888 3495
 
3496
+  registry.npmmirror.com/type/1.2.0:
3497
+    resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/type/-/type-1.2.0.tgz}
3498
+    name: type
3499
+    version: 1.2.0
3500
+    dev: false
3501
+
3502
+  registry.npmmirror.com/type/2.7.2:
3503
+    resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/type/-/type-2.7.2.tgz}
3504
+    name: type
3505
+    version: 2.7.2
3506
+    dev: false
3507
+
2889 3508
   registry.npmmirror.com/unstated-next/1.1.0:
2890 3509
     resolution: {integrity: sha512-AAn47ZncPvgBGOvMcn8tSRxsrqwf2VdAPxLASTuLJvZt4rhKfDvUkmYZLGfclImSfTVMv7tF4ynaVxin0JjDCA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/unstated-next/-/unstated-next-1.1.0.tgz}
2891 3510
     name: unstated-next
@@ -2987,6 +3606,12 @@ packages:
2987 3606
       loose-envify: registry.npmmirror.com/loose-envify/1.4.0
2988 3607
     dev: false
2989 3608
 
3609
+  registry.npmmirror.com/wildcard/1.1.2:
3610
+    resolution: {integrity: sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/wildcard/-/wildcard-1.1.2.tgz}
3611
+    name: wildcard
3612
+    version: 1.1.2
3613
+    dev: false
3614
+
2990 3615
   registry.npmmirror.com/zrender/5.4.0:
2991 3616
     resolution: {integrity: sha512-rOS09Z2HSVGFs2dn/TuYk5BlCaZcVe8UDLLjj1ySYF828LATKKdxuakSZMvrDz54yiKPDYVfjdKqcX8Jky3BIA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/zrender/-/zrender-5.4.0.tgz}
2992 3617
     name: zrender

+ 15
- 0
src/components/EditableTag/Tag.jsx Datei anzeigen

@@ -0,0 +1,15 @@
1
+import React from 'react';
2
+import { Button } from 'antd';
3
+import { CloseOutlined } from '@ant-design/icons';
4
+import './style.less'
5
+
6
+export default (props) => {
7
+  const { size, type, onDelete, children } = props;
8
+
9
+  return (
10
+    <div className='tag-btn-group'>
11
+      <Button size={size} type={type}>{children}</Button>
12
+      <Button size={size} type="primary" icon={<CloseOutlined />} onClick={onDelete} />
13
+    </div>
14
+  )
15
+}

+ 21
- 0
src/components/EditableTag/index.jsx Datei anzeigen

@@ -0,0 +1,21 @@
1
+import React from 'react';
2
+import { Button } from 'antd';
3
+import Tag from './Tag';
4
+import './style.less'
5
+
6
+export default (props) => {
7
+  const { size, type, list = [], onDelete, keyFuc, labelFunc } = props;
8
+
9
+  return (
10
+    <div className='editable-tag-box'>
11
+      {
12
+        list.map((item, index) => {
13
+          const key = keyFuc(item, index);
14
+          const label = labelFunc(item, index);
15
+
16
+          return <Tag key={key} size={size} type={type} onDelete={() => onDelete(item)}>{label}</Tag>
17
+        })
18
+      }
19
+    </div>
20
+  )
21
+}

+ 27
- 0
src/components/EditableTag/style.less Datei anzeigen

@@ -0,0 +1,27 @@
1
+.tag-btn-group {
2
+  .ant-btn {
3
+    vertical-align: middle;
4
+  }
5
+
6
+  .ant-btn:first-child {
7
+    border-right: none;
8
+  }
9
+
10
+  .ant-btn:last-child {
11
+    // border-left: none;
12
+    border-top-left-radius: 0;
13
+    border-bottom-left-radius: 0;
14
+    margin-left: -1px;
15
+  }
16
+}
17
+
18
+.editable-tag-box {
19
+  display: flex;
20
+  flex-wrap: wrap;
21
+
22
+  .tag-btn-group {
23
+    flex: none;
24
+    box-sizing: border-box;
25
+    padding: 1em;
26
+  }
27
+}

+ 4
- 0
src/components/Money/float.js Datei anzeigen

@@ -0,0 +1,4 @@
1
+const epsilonN = N => num => Math.round( num * N + Number.EPSILON ) / N;
2
+const epsilon2 = epsilonN(1e2);
3
+
4
+export default epsilon2;

+ 30
- 0
src/components/Money/index.jsx Datei anzeigen

@@ -0,0 +1,30 @@
1
+import { InputNumber } from "antd"
2
+import { useEffect, useState } from "react"
3
+import epsilon2 from './float'
4
+
5
+export default (props) => {
6
+
7
+  const { value, onChange, ...leftProps } = props
8
+
9
+  const [money, setMoney] = useState(0)
10
+
11
+  useEffect(() => {
12
+    setMoney(epsilon2(value / 100))
13
+  }, [value])
14
+
15
+  const handleChange = (val) => {
16
+    onChange(epsilon2(val * 100))
17
+  }
18
+
19
+  return (
20
+    <InputNumber
21
+      min='0'
22
+      {...leftProps}
23
+      value={money}
24
+      onChange={handleChange}
25
+      precision={2}
26
+      formatter={value => `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')}
27
+      parser={value => value.replace(/\¥\s?|(,*)/g, '')}
28
+    />
29
+  )
30
+}

+ 87
- 0
src/components/Wangeditor/index.jsx Datei anzeigen

@@ -0,0 +1,87 @@
1
+import React, { useState, useEffect } from "react";
2
+import "@wangeditor/editor/dist/css/style.css";
3
+import { Editor, Toolbar } from "@wangeditor/editor-for-react";
4
+
5
+// 工具栏配置参考
6
+// https://www.cnblogs.com/-roc/p/16400965.html
7
+
8
+const defaultStyle = {
9
+  border: "1px solid #ccc",
10
+  zIndex: 100,
11
+  marginTop: "15px"
12
+}
13
+
14
+function MyEditor(props) {
15
+
16
+  const style = React.useMemo(() => ({ ...defaultStyle, ...(props.style || {}) }), [props.style])
17
+
18
+  const {
19
+    value = "",
20
+    onChange = (e) => {
21
+      setHtml(e);
22
+    },
23
+    toolbarConfig = {
24
+      excludeKeys: ["group-image", "group-video"],
25
+    },
26
+    editorConfig = {
27
+      placeholder: "请输入内容...",
28
+    },
29
+    readonly = false,
30
+  } = props;
31
+  const [editor, setEditor] = useState(null); // 存储 editor 实例
32
+  const [html, setHtml] = useState("");
33
+ 
34
+  // 模拟 ajax 请求,异步设置 html
35
+  useEffect(() => {
36
+    setHtml(value || "");
37
+  }, [value]);
38
+
39
+  // 及时销毁 editor
40
+  useEffect(() => {
41
+    return () => {
42
+      if (editor == null) return;
43
+      editor.destroy();
44
+      setEditor(null);
45
+    };
46
+  }, [editor]);
47
+
48
+  function insertText() {
49
+    if (editor == null) return;
50
+    editor.insertText(" hello ");
51
+  }
52
+
53
+  function printHtml() {
54
+    if (editor == null) return;
55
+    console.log(editor.getHtml());
56
+  }
57
+
58
+  const handleChange = (editor) => {
59
+    const raw = editor.getHtml();
60
+    if (raw !== '<p><br></p>') {
61
+      onChange(raw)
62
+    }
63
+  }
64
+
65
+  return !readonly ? (
66
+    <div className={props.className} style={style}>
67
+      <Toolbar
68
+        editor={editor}
69
+        defaultConfig={toolbarConfig}
70
+        mode="default"
71
+        style={{ borderBottom: "1px solid #ccc" }}
72
+      />
73
+      <Editor
74
+        defaultConfig={editorConfig}
75
+        value={html}
76
+        onCreated={setEditor}
77
+        onChange={handleChange}
78
+        mode="default"
79
+        style={{ height: "500px" }}
80
+      />
81
+    </div>
82
+  ) : (
83
+    <div dangerouslySetInnerHTML={{ __html: value }}></div>
84
+  );
85
+}
86
+
87
+export default MyEditor;

+ 0
- 10
src/components/page/Container.jsx Datei anzeigen

@@ -1,10 +0,0 @@
1
-import React from 'react';
2
-import './style.less'
3
-
4
-export default (props) => {
5
-  return (
6
-    <div className="page-container">
7
-      {props.children}
8
-    </div>
9
-  )
10
-}

+ 0
- 14
src/components/page/index.jsx Datei anzeigen

@@ -1,14 +0,0 @@
1
-import React, { useEffect } from 'react';
2
-// import { PageHeader } from 'antd';
3
-import { useModel } from '@/store';
4
-import Container from './Container';
5
-
6
-export default (props) => {
7
-  // const { children, ...headerProps } = props;
8
-  
9
-  return (
10
-    <Container>
11
-      {props.children}
12
-    </Container>
13
-  )
14
-}

+ 0
- 5
src/components/page/style.less Datei anzeigen

@@ -1,5 +0,0 @@
1
-
2
-.page-container {
3
-  margin: 24px;
4
-  margin-bottom: 0;
5
-}

+ 6
- 1
src/index.less Datei anzeigen

@@ -33,6 +33,7 @@ html, body, #root {
33 33
 .ant-layout-header {
34 34
   line-height: var(--header-height);
35 35
   box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
36
+  // border-bottom: 1px solid gainsboro;
36 37
   z-index: 10;
37 38
 }
38 39
 
@@ -40,7 +41,11 @@ html, body, #root {
40 41
   width: var(--siderbar-width);
41 42
   background-color: var(--theme-color);
42 43
   color: var(--theme-front);
43
-  box-shadow: 1px 0 4px 0 rgba(0, 21, 41, 0.04);
44
+  box-shadow: 1px 0 4px 0 rgba(0, 21, 41, 0.08);
45
+
46
+  .ant-menu {
47
+    background: transparent;
48
+  }
44 49
 }
45 50
 
46 51
 

+ 17
- 18
src/layouts/AuthLayout/components/Container.jsx Datei anzeigen

@@ -1,32 +1,31 @@
1
-import React, { useEffect, useRef, useMemo, useState } from 'react';
2
-import { Layout, Spin } from 'antd';
3
-import { Outlet, useLocation } from "react-router-dom";
1
+import React from 'react';
2
+import { Layout } from 'antd';
3
+import { Outlet } from "react-router-dom";
4 4
 import PageTransition from './PageTransition';
5 5
 import Footer from './Footer';
6 6
 
7 7
 const { Content } = Layout;
8
+const marginSpace = 24;
8 9
 
9 10
 export default (props) => {
10
-  const location = useLocation();
11
-  
12
-  const containerRef = useRef();
13
-  const [minHeight, setMinHeight] = useState(0);
14
-  const contentStyle = useMemo(() => ({ minHeight: `${minHeight}px` }), [minHeight]);
15
-  
16
-  useEffect(() => {
17
-    const containerHeight = containerRef.current.offsetHeight;
18
-    const footerHeight = document.querySelector('.ant-layout-footer').offsetHeight;
19
-    setMinHeight(containerHeight - footerHeight);
20
-  }, [minHeight]);
11
+  const { noFooter } = props;
12
+  const footerRef = React.useRef();
13
+  const [height, setHeight] = React.useState(`calc(100% - ${marginSpace * 2}px`);
14
+
15
+  React.useEffect(() => {
16
+    if (footerRef.current) {
17
+      setHeight(`calc(100% - ${footerRef.current.offsetHeight + marginSpace * 2}px)`);
18
+    }
19
+  }, [noFooter])
21 20
 
22 21
   return (
23
-    <div className='layout-container' ref={containerRef}>
24
-      <Content style={contentStyle}>
25
-        <PageTransition location={location}>
22
+    <div className='layout-container'>
23
+      <Content style={{ minHeight: height, margin: `${marginSpace}px` }}>
24
+        <PageTransition location={props.location}>
26 25
           <Outlet />
27 26
         </PageTransition>
28 27
       </Content>
29
-      <Footer />
28
+      {!noFooter && <Footer ref={footerRef} />}
30 29
     </div>
31 30
   )
32 31
 }

+ 7
- 6
src/layouts/AuthLayout/components/Footer.jsx Datei anzeigen

@@ -1,14 +1,15 @@
1 1
 import React from 'react';
2
-import { Layout, Spin } from 'antd';
2
+import { Layout } from 'antd';
3
+import { useModel } from '@/store';
3 4
 
4 5
 const { Footer } = Layout;
5 6
 
6 7
 const year = new Date().getFullYear();
7
-export default (props) => {
8
-
9
-  const copyRight = `南京云致 @${year}`
8
+export default React.forwardRef((props, ref) => {
9
+  const { app } = useModel('system');
10
+  const copyRight = `${app.company || '南京云致'} @ ${year}`;
10 11
 
11 12
   return (
12
-    <Footer style={{ textAlign: 'center' }}>{copyRight}</Footer>
13
+    <Footer ref={ref} style={{ textAlign: 'center', color: 'rgba(0,0,0, 0.3)' }}>{copyRight}</Footer>
13 14
   )
14
-}
15
+})

+ 21
- 2
src/layouts/AuthLayout/components/Header/Exit.jsx Datei anzeigen

@@ -1,9 +1,28 @@
1 1
 import React from 'react';
2
+import { useNavigate } from 'react-router-dom';
2 3
 import { LogoutOutlined } from '@ant-design/icons';
3
-import { Button } from 'antd';
4
+import { Button, Modal } from 'antd';
5
+import { useModel } from '@/store';
6
+
7
+const { confirm } = Modal;
4 8
 
5 9
 export default (props) => {
10
+  const navigate = useNavigate();
11
+  const { setUser } = useModel('user');
12
+  
13
+  const onExit = () => {
14
+    confirm({
15
+      title: '确认退出系统?',
16
+      onOk: () => {
17
+        // logout(); // 调用接口
18
+        localStorage.removeItem('token');
19
+        setUser();
20
+        navigate('/login?back=true');
21
+      }
22
+    });
23
+  }
24
+
6 25
   return (
7
-    <Button className='font' type="text" icon={<LogoutOutlined />}>退出</Button>
26
+    <Button className='font' type="text" icon={<LogoutOutlined />} onClick={onExit}>退出</Button>
8 27
   )
9 28
 }

+ 3
- 5
src/layouts/AuthLayout/components/Header/Title.jsx Datei anzeigen

@@ -1,7 +1,5 @@
1
-import { Typography } from 'antd';
2
-import useRoute from '@/utils/hooks/useRoute';
3 1
 
4
-const { Title } = Typography;
2
+import useRoute from '@/utils/hooks/useRoute';
5 3
 
6 4
 const titleStyle = {
7 5
   margin: 0,
@@ -18,9 +16,9 @@ export default (props) => {
18 16
   const { title } = route && route.meta || {}
19 17
 
20 18
   return (
21
-    <Title level={5} style={titleStyle}>
19
+    <h5 style={titleStyle}>
22 20
       { title && <span style={spanStyle}>&raquo;</span> }
23 21
       { title && <span>{title}</span> }
24
-    </Title>
22
+    </h5>
25 23
   );
26 24
 }

+ 2
- 2
src/layouts/AuthLayout/components/Header/User.jsx Datei anzeigen

@@ -1,6 +1,6 @@
1 1
 import React, { useState, forwardRef, useRef, useImperativeHandle } from 'react';
2 2
 import { Avatar, Button, Dropdown, Menu, Form, Input, Modal } from 'antd';
3
-import { useModel } from '@/store'
3
+import md5 from 'md5';
4 4
 
5 5
 const ChangePassword = forwardRef((props, ref) => {
6 6
   const [visible, setVisible] = useState(false);
@@ -66,7 +66,7 @@ export default (props) => {
66 66
   ];
67 67
 
68 68
   const passRef = useRef();
69
-  const { user = {} } = useModel('user');
69
+  const { user = {} } = props;
70 70
 
71 71
   const onClick = ({ key }) => {
72 72
     if (key === 'changePassword') {

+ 3
- 6
src/layouts/AuthLayout/components/Header/index.jsx Datei anzeigen

@@ -1,29 +1,26 @@
1 1
 import React, { useMemo } from 'react';
2 2
 import { Layout, Space } from 'antd';
3 3
 import classNames from 'classnames';
4
-import Logo from './Logo';
5 4
 import Title from './Title';
6 5
 import User from './User';
7 6
 import Exit from './Exit';
7
+import Logo from '../Logo';
8 8
 
9 9
 const { Header } = Layout;
10 10
 
11 11
 export default (props) => {
12
+  const { user } = props;
12 13
 
13 14
   const className = useMemo(() => classNames({
14 15
     'layout-header': true,
15 16
     'light': props.theme === 'light',
16 17
   }), [props.theme]);
17 18
 
18
-
19 19
   return (
20 20
     <Header className={className}>
21 21
       <Logo />
22
-      <div className="header-content">
23
-        <Title />
24
-      </div>
25 22
       <Space>
26
-        <User />
23
+        <User user={user} />
27 24
         <Exit />
28 25
       </Space>
29 26
     </Header>

src/layouts/AuthLayout/components/Header/Logo.jsx → src/layouts/AuthLayout/components/Logo.jsx Datei anzeigen

@@ -3,15 +3,13 @@ import { Typography } from 'antd';
3 3
 import { NavLink } from "react-router-dom";
4 4
 import { useModel } from '@/store';
5 5
 
6
-const { Title } = Typography;
7
-
8 6
 export default (props) => {
9 7
   const { app } = useModel('system');
10 8
 
11 9
   return (
12 10
     <NavLink className='logo'  to="/">
13 11
       <img src="./logo.png" alt="" />
14
-      <Title level={5}>{app.shorName}</Title>
12
+      <h3>{app.shorName}</h3>
15 13
     </NavLink>
16 14
   )
17 15
 }

+ 15
- 22
src/layouts/AuthLayout/components/Menus.jsx Datei anzeigen

@@ -1,33 +1,26 @@
1
-import React, { useState } from 'react';
2
-import { useNavigate } from "react-router-dom";
1
+import React from 'react';
3 2
 import { Menu } from 'antd';
4
-import { getItems } from '@/routes/menus';
5
-
6
-const linkTo = url => {
7
-  const a = document.createElement('a');
8
-  a.href = item.key;
9
-  a.target = '_blank';
10
-  a.click();
11
-}
12 3
 
13 4
 const menuStyle = { height: '100%' };
14 5
 
15 6
 export default (props) => {
16
-  const { theme } = props;
7
+  const { theme, items, location } = props;
8
+
9
+  // const selectedKeys = React.useMemo(() => {
10
+  //   const parts = location.pathname.split('/').filter(Boolean);
11
+  //   const keys = parts.reduce((acc, it) => {
12
+  //     const parent = acc.pop();
13
+  //     const path = !parent ? `/${it}` : `${parent}/${it}`
14
+
15
+  //     return acc.concat([parent, path].filter(Boolean));
16
+  //   }, []);
17 17
 
18
-  const navigate = useNavigate();
19
-  const items = getItems();
18
+  //   return keys;
19
+  // }, [location.pathname]);
20 20
 
21
-  const onClick = (item) => {
22
-    // http 开头说明是外部链接
23
-    if (item.key.indexOf('http') === 0) {
24
-      linkTo(item.key);
25
-    } else {
26
-      navigate(item.key);
27
-    }
28
-  }
21
+  const selectedKeys = [location.pathname];
29 22
 
30 23
   return (
31
-    <Menu style={menuStyle} theme={theme} items={items} onClick={onClick} />
24
+    <Menu style={menuStyle} theme={theme} items={items} selectedKeys={selectedKeys} />
32 25
   )
33 26
 }

+ 1
- 1
src/layouts/AuthLayout/components/PageTransition/index.jsx Datei anzeigen

@@ -12,7 +12,7 @@ export default (props) => {
12 12
         addEndListener={(node, done) => node.addEventListener("transitionend", done, false)}
13 13
         classNames="page-fade"
14 14
       >
15
-        <div>
15
+        <div style={{ height: '100%' }}>
16 16
           {props.children}
17 17
         </div>
18 18
       </CSSTransition>

+ 16
- 8
src/layouts/AuthLayout/components/RequireLogin.jsx Datei anzeigen

@@ -1,13 +1,21 @@
1
-import React, { useState } from 'react'
2
-import { useLocation, Navigate } from "react-router-dom"
1
+import React, { useState, useEffect } from 'react';
2
+import { useLocation, Navigate } from "react-router-dom";
3
+import { useModel } from '@/store';
3 4
 
4 5
 export default (props) => {
5
-  const { user } = props
6
-  const location = useLocation()
6
+  const { user, getCurrentUser } = useModel('user');
7
+  const [userStatus, setUserStatus] = useState(user && user.id ? 1 : 0);
7 8
 
8
-  return props.children
9
+  useEffect(() => {
10
+    if (!user || !user.id) {
11
+      getCurrentUser().then(() => {
12
+        setUserStatus(1);
13
+      }).catch(() => {
14
+        setUserStatus(-1);
15
+      });
16
+    }
17
+  }, []);
9 18
 
10
-  // return !user || !user.isLoged ?
11
-  //   <Navigate to="/login" state={{ from: location }} replace /> :
12
-  //   props.children
19
+  return userStatus === 0 ? null :
20
+    userStatus === -1 ? <Navigate to="/login?back=true" /> : props.children;
13 21
 }

+ 3
- 4
src/layouts/AuthLayout/components/SiderBar.jsx Datei anzeigen

@@ -1,6 +1,5 @@
1 1
 import React, { useMemo } from 'react';
2 2
 import { Layout, Spin } from 'antd';
3
-import { useModel } from '@/store'
4 3
 import { getPropertyValue } from '@/utils/css';
5 4
 import Menus from './Menus';
6 5
 
@@ -8,16 +7,16 @@ const { Sider } = Layout;
8 7
 
9 8
 
10 9
 export default (props) => {
10
+  const { theme, location, menus } = props;
11 11
 
12 12
   const width = useMemo(() => {
13 13
     return /\d+/.exec(getPropertyValue('--siderbar-width'))[0] - 0;
14 14
   }, []);
15 15
 
16
-  const { theme } = useModel('system');
17 16
 
18 17
   return (
19 18
     <Sider className='layout-sidebar' theme={theme} collapsible width={width}>
20
-      <Menus theme={theme}/>
19
+      <Menus theme={theme} items={menus} location={location} />
21 20
     </Sider>
22
-  )
21
+  );
23 22
 }

+ 19
- 21
src/layouts/AuthLayout/index.jsx Datei anzeigen

@@ -1,42 +1,40 @@
1
-import React, { useEffect, useRef, useMemo, useState } from 'react';
1
+import React, { useEffect } from 'react';
2 2
 import { Layout, Spin } from 'antd';
3
-import { useLocation } from "react-router-dom";
3
+import { useLocation, Outlet } from "react-router-dom";
4 4
 import { useModel } from '@/store';
5
+import useRoute from '@/utils/hooks/useRoute';
5 6
 import RequireLogin from './components/RequireLogin';
6 7
 import SiderBar from './components/SiderBar';
7 8
 import Header from './components/Header';
8 9
 import Container from './components/Container';
9 10
 import HtmlTitle from './components/HtmlTitle';
10
-import useReady from './useReady';
11 11
 
12 12
 import './style.less';
13 13
 
14 14
 export default (props) => {
15 15
   const { theme } = useModel('system');
16
-  const { user, getCurrent } = useModel('user');
17
-
18
-  // const isReady = useReady(user)
19
-  // const isReady = true
20
-
16
+  const { user, menus } = useModel('user');
21 17
   const location = useLocation();
22
-
23
-  useEffect(() => {
24
-    if (!user) {
25
-      getCurrent()
26
-    }
27
-  }, []);
18
+  const { meta } = useRoute() || {};
19
+  const { noLayout = false, noSiderBar = false, noFooter = false } = meta || {};
28 20
 
29 21
   return (
30 22
     <Spin spinning={!user} size="large">
31 23
       <HtmlTitle />
32 24
       <RequireLogin>
33
-        <div className='main-layout'>
34
-          <Header theme={theme} />
35
-          <Layout>
36
-            <SiderBar theme={theme} />
37
-            <Container />
38
-          </Layout>
39
-        </div>
25
+        {
26
+          noLayout
27
+            ? <Outlet />
28
+            : (
29
+              <Layout style={{ height: '100vh' }}>
30
+                <Header theme={theme} user={user} />
31
+                <Layout style={{ height: 'calc(100vh - var(--header-height))' }}>
32
+                  { !noSiderBar && <SiderBar theme={theme} menus={menus} location={location} /> }
33
+                  <Container location={location} noFooter={noFooter} />
34
+                </Layout>
35
+              </Layout>
36
+            )
37
+        }
40 38
       </RequireLogin>
41 39
     </Spin>
42 40
   );

+ 30
- 24
src/layouts/AuthLayout/style.less Datei anzeigen

@@ -7,35 +7,15 @@
7 7
   justify-content: space-between;
8 8
   color: #fff;
9 9
 
10
-  &.light {
11
-    background-color: #fff;
12
-    color: #000;
13
-  }
10
+  // &.light {
11
+  //   background-color: #fff;
12
+  //   color: #000;
13
+  // }
14 14
 
15 15
   .header-content {
16 16
     flex: 1;
17 17
   }
18 18
 
19
-  .logo {
20
-    width: var(--siderbar-width);
21
-    display: flex;
22
-    align-items: center;
23
-    box-sizing: border-box;
24
-    padding-left: 1em;
25
-    color: inherit;
26
-
27
-    & > * {
28
-      color: inherit;
29
-      margin: 0;
30
-    }
31
-
32
-    img {
33
-      width: 28px;
34
-      vertical-align: middle;
35
-      margin-right: 1em;
36
-    }
37
-  }
38
-
39 19
   .font {
40 20
     color: inherit;
41 21
     display: inline-block;
@@ -58,6 +38,30 @@
58 38
   }
59 39
 }
60 40
 
41
+.logo {
42
+  height: var(--header-height);
43
+  display: flex;
44
+  align-items: center;
45
+  box-sizing: border-box;
46
+  padding-left: 1em;
47
+  color: inherit;
48
+
49
+  & > * {
50
+    color: inherit;
51
+    margin: 0;
52
+  }
53
+
54
+  h5 {
55
+    margin: 0;
56
+  }
57
+
58
+  img {
59
+    width: 28px;
60
+    vertical-align: middle;
61
+    margin-right: 1em;
62
+  }
63
+}
64
+
61 65
 .layout-container {
62 66
   flex: 1;
63 67
 
@@ -68,4 +72,6 @@
68 72
   &::--webkit-scrollbar {
69 73
     display: none;
70 74
   }
75
+
76
+  padding-top: 0; // 避免子元素的 margin 影响
71 77
 }

+ 0
- 14
src/layouts/AuthLayout/useReady.jsx Datei anzeigen

@@ -1,14 +0,0 @@
1
-import React, { useState, useEffect } from 'react'
2
-
3
-export default function useReady(user) {
4
-  const [isReady, setReady] = useState(false)
5
-  const isLogined = user && user.isLogined
6
-
7
-  useEffect(() => {
8
-    if (!isReady && !isLogined) {
9
-      // fetchCurrent
10
-    }
11
-  }, [isReady, isLogined])
12
-
13
-  return isLogined || isReady || true
14
-}

+ 23
- 0
src/layouts/PageContainer.jsx Datei anzeigen

@@ -0,0 +1,23 @@
1
+import React from 'react';
2
+import { Typography } from 'antd';
3
+import { Outlet } from 'react-router-dom';
4
+import useRoute from '@/utils/hooks/useRoute';
5
+
6
+const containerStyle = {
7
+  // margin: '24px 24px 0 24px',
8
+  margin: '24px',
9
+  minHeight: 'calc(100% - 48px)',
10
+}
11
+const { Title } = Typography;
12
+
13
+export default (props) => {
14
+  const { meta = {} } = useRoute() || {};
15
+  const style = meta.noLayout ? { height: '100%' } : containerStyle;
16
+
17
+  return (
18
+    <div style={style}>
19
+      { meta.title && !meta.noLayout && <Title level={4} style={{ paddingBottom: '12px' }}>{ meta.title }</Title> }
20
+      <Outlet />
21
+    </div>
22
+  )
23
+}

+ 1
- 2
src/pages/sample/form/index.jsx Datei anzeigen

@@ -12,7 +12,6 @@ import {
12 12
   Card,
13 13
 } from 'antd';
14 14
 import React, { useState } from 'react';
15
-import Page from '@/components/page';
16 15
 
17 16
 const { Option } = Select;
18 17
 const residences = [
@@ -350,4 +349,4 @@ const BasicForm = () => {
350 349
   );
351 350
 };
352 351
 
353
-export default () => <Page><Card><BasicForm /></Card></Page>;
352
+export default () => <Card><BasicForm /></Card>;

+ 2
- 3
src/pages/sample/home/index.jsx Datei anzeigen

@@ -1,6 +1,5 @@
1 1
 import React from 'react';
2 2
 import { Row, Col, Card, Space, Statistic } from 'antd';
3
-import Container from '@/components/page/Container';
4 3
 import Banner from './components/Banner';
5 4
 import AreaChart from './components/AreaChart';
6 5
 import BarChart from './components/BarChart';
@@ -16,7 +15,7 @@ export default (props) => {
16 15
   }
17 16
 
18 17
   return (
19
-    <Container>
18
+    <div>
20 19
       <Banner />
21 20
 
22 21
       <Row gutter={24} style={{ marginTop: '24px' }}>
@@ -36,6 +35,6 @@ export default (props) => {
36 35
           <BarChart style={chartStyle}/>
37 36
         </Col>
38 37
       </Row>
39
-    </Container>
38
+    </div>
40 39
   )
41 40
 }

+ 4
- 3
src/pages/sample/table/index.jsx Datei anzeigen

@@ -2,7 +2,6 @@ import { EllipsisOutlined, PlusOutlined } from '@ant-design/icons';
2 2
 import { ProTable, TableDropdown } from '@ant-design/pro-components';
3 3
 import { Button, Dropdown, Menu, Space, Tag } from 'antd';
4 4
 import { useRef, useEffect } from 'react';
5
-import Page from '@/components/page';
6 5
 import { useModel } from '@/store';
7 6
 
8 7
 // import request from 'umi-request';
@@ -126,7 +125,8 @@ const menu = (<Menu items={[
126 125
 export default () => {
127 126
 
128 127
     const actionRef = useRef();
129
-    return (<Page><ProTable columns={columns} actionRef={actionRef} cardBordered request={async (params = {}, sort, filter) => {
128
+    return (
129
+        <ProTable columns={columns} actionRef={actionRef} cardBordered request={async (params = {}, sort, filter) => {
130 130
             console.log(sort, filter);
131 131
             // return request('https://proapi.azurewebsites.net/github/issues', {
132 132
             //     params,
@@ -165,5 +165,6 @@ export default () => {
165 165
             <EllipsisOutlined />
166 166
           </Button>
167 167
         </Dropdown>,
168
-        ]}/></Page>);
168
+        ]}/>
169
+    );
169 170
 };

+ 13
- 2
src/routes/Router.jsx Datei anzeigen

@@ -1,7 +1,18 @@
1
+import React from "react";
1 2
 import { createHashRouter, RouterProvider } from "react-router-dom";
2
-import routes from './routes'
3
+import { useModel } from "@/store";
4
+import { defaultRoutes } from './routes';
3 5
 
4
-const router = createHashRouter(routes);
5 6
 export default (props) => {
7
+  const { routes } = useModel('user');
8
+
9
+  const router = React.useMemo(() => {
10
+    if (!routes || routes.length < 1) {
11
+      return createHashRouter(defaultRoutes);
12
+    } else {
13
+      return createHashRouter(routes);
14
+    }
15
+  }, [routes]);
16
+  
6 17
   return <RouterProvider router={router} />
7 18
 }

+ 21
- 31
src/routes/menus.jsx Datei anzeigen

@@ -1,10 +1,8 @@
1
-import routes from './routes';
2
-
3
-let routeArr = [];
1
+import { Link } from 'react-router-dom';
4 2
 
5 3
 // 菜单是否显示
6
-// 没有 meta 或者 meta.title 为空, 或者 meta.hiddenInMenu = true 的 都不显示
7
-const isShow = item => item.meta && item.meta.title && !item.meta.hiddenInMenu;
4
+// 没有 meta 或者 meta.title 为空, 或者 meta.hideInMenu = true 的 都不显示
5
+const isShow = item => item.meta && item.meta.title && !item.meta.hideInMenu;
8 6
 
9 7
 const hasChildren = (list) => {
10 8
   if (!list || list.length < 1) return false;
@@ -18,41 +16,33 @@ const getPath = (parent, current = '') => {
18 16
   return `${parent}/${current}`.replace(/\/\//g, '/');
19 17
 }
20 18
 
21
-const getMenuItems = (dts = [], fullPath = '/') => {
22
-  return dts.map(item => {
23
-    const path = getPath(fullPath, item.path);
24
-
25
-    routeArr.push({
26
-      ...item,
27
-      path,
28
-    });
19
+export const getMenuItems = (routes = [], fullPath = '/') => {
20
+  return routes.map(route => {
21
+    const path = getPath(fullPath, route.path);
29 22
 
30 23
     //
31
-    if (!isShow(item)) return false;
24
+    if (!isShow(route)) return false;
32 25
     
33
-    const children = hasChildren(item.children) ? getMenuItems(item.children, path) : false;
26
+    const children = hasChildren(route.children) ? getMenuItems(route.children, path) : false;
27
+
28
+    const { target, title, icon } = route.meta || {}
29
+
30
+    // 坑爹 react-router v6 不支持 hash 路由的 target 跳转
31
+    const label = target === '_blank' ?
32
+      <a href={`${window.location.pathname}#${path}`} target={target}>{title}</a>
33
+      : (
34
+        path.indexOf('http') === 0  ? <a href={path} target="_blank">{title}</a>
35
+        : <Link to={path} target={target}>{title}</Link>
36
+      );
34 37
 
35 38
     return Object.assign(
36 39
       {
37 40
         key: path,
38
-        label: item.meta.title,
39
-        title: item.meta.title,
40
-        icon: item.meta.icon,
41
+        label,
42
+        title,
43
+        icon,
41 44
       },
42 45
       children && { children },
43 46
     )
44 47
   }).filter(Boolean);
45 48
 }
46
-
47
-const getItems = () => getMenuItems(routes[0]?.children);
48
-const getRouteArr = () => {
49
-  if (routeArr.length < 1) {
50
-    getItems();
51
-  }
52
-  return routeArr;
53
-}
54
-// 
55
-export {
56
-  getItems,
57
-  getRouteArr,
58
-};

+ 14
- 0
src/routes/permissions.js Datei anzeigen

@@ -0,0 +1,14 @@
1
+
2
+export const getAuthedRoutes = (routes, permissions) => {
3
+  if (!routes || routes.length < 1) return [];
4
+
5
+  return routes.map(route => {
6
+    if (route.meta && route.meta.permission && permissions.indexOf(route.meta.permission) < 0) return false;
7
+
8
+    if (route.children) {
9
+      route.children = getAuthedRoutes(route.children, permissions);
10
+    }
11
+
12
+    return route;
13
+  }).filter(Boolean);
14
+}

+ 58
- 18
src/routes/routes.jsx Datei anzeigen

@@ -8,6 +8,7 @@ import {
8 8
   PieChartOutlined,
9 9
 } from '@ant-design/icons';
10 10
 import AuthLayout from "@/layouts/AuthLayout";
11
+import PageContainer from "@/layouts/PageContainer";
11 12
 import Login from '@/pages/login';
12 13
 import Page404 from '@/pages/404';
13 14
 import Home from "@/pages/sample/home";
@@ -18,11 +19,37 @@ import BasicTable from '@/pages/sample/table';
18 19
  * meta 用来扩展自定义数据数据
19 20
  * {
20 21
  *    title: 用于页面或者菜单的标题, 没有此字段, 菜单不会显示
21
- *    hiddenInMenu: 布尔值, 如果为 false, 菜单不会显示
22
+ *    hideInMenu: 布尔值, 如果为 false, 菜单不会显示
23
+ *    noLayout: 布尔值, 如果为 true, 将不会使用默认布局
24
+ *    noSiderBar: 布尔值, 如果为 true, 将没有左侧菜单栏
25
+ *    noFooter: 布尔值, 如果为 true, 将没有底部 footer
26
+ *    target: 字符串, 如果为 _blank, 将在新窗口打开
27
+ *    permission: 对应服务器端权限名称
22 28
  * }
23 29
  */
24 30
 
25
-export default [
31
+export const authRoutes = [
32
+  {
33
+    path: "form",
34
+    element: <BasicForm />,
35
+    meta: {
36
+      title: '表单',
37
+      icon: <AppstoreOutlined />,
38
+      permission: 'form',
39
+    },
40
+  },
41
+  {
42
+    path: "table",
43
+    element: <BasicTable />,
44
+    meta: {
45
+      title: '表格',
46
+      icon: <ContainerOutlined />,
47
+      permission: 'table',
48
+    },
49
+  },
50
+];
51
+
52
+export const defaultRoutes = [
26 53
   {
27 54
     path: "/",
28 55
     element: <AuthLayout />,
@@ -39,22 +66,6 @@ export default [
39 66
           icon: <DesktopOutlined />,
40 67
         },
41 68
       },
42
-      {
43
-        path: "form",
44
-        element: <BasicForm />,
45
-        meta: {
46
-          title: '表单',
47
-          icon: <AppstoreOutlined />,
48
-        },
49
-      },
50
-      {
51
-        path: "table",
52
-        element: <BasicTable />,
53
-        meta: {
54
-          title: '表格',
55
-          icon: <ContainerOutlined />,
56
-        },
57
-      },
58 69
       {
59 70
         path: '*',
60 71
         element: <Page404 />
@@ -70,3 +81,32 @@ export default [
70 81
     element: <Page404 />
71 82
   }
72 83
 ]
84
+
85
+export function mergeAuthRoutes (r1, r2) {
86
+  const r = r1.slice();
87
+  const children = r1[0].children.slice();
88
+  r[0].children = children.concat(r2);
89
+  return r;
90
+}
91
+
92
+// 全部路由
93
+export const routes = mergeAuthRoutes(defaultRoutes, authRoutes);
94
+function getPath (parent = "/", current = "") {
95
+  if (current.indexOf("/") === 0 || current.indexOf("http") === 0)
96
+    return current;
97
+  return `${parent}/${current}`.replace(/\/\//g, "/");
98
+}
99
+
100
+// 路由数组, 一维数组
101
+export const routeArr = (() => {
102
+  const flatten = (routes, parentPath = "/") => {
103
+    return routes.reduce((acc, route) => {
104
+      const path = getPath(parentPath, route.path);
105
+      const children = route.children ? flatten(route.children, path) : [];
106
+
107
+      return acc.concat([{ ...route, path }].concat(children));
108
+    }, []);
109
+  };
110
+
111
+  return flatten(routes);
112
+})();

+ 1
- 5
src/store/models/system.js Datei anzeigen

@@ -11,14 +11,10 @@ export default function useSystem() {
11 11
     company: '云致科技'
12 12
   });
13 13
 
14
-  // 页面标题
15
-  const [title, setTitle] = useState();
16
-
17 14
   return {
18 15
     theme,
19 16
     updateTheme,
20 17
     app,
21
-    title,
22
-    setTitle,
18
+    hashRoute: true,
23 19
   }
24 20
 }

+ 27
- 7
src/store/models/user.js Datei anzeigen

@@ -1,17 +1,37 @@
1
-import { useState } from "react";
1
+import { useState, useRef } from "react";
2
+import { defaultRoutes, authRoutes, mergeAuthRoutes } from '@/routes/routes';
3
+import { getMenuItems } from "@/routes/menus";
4
+import { getAuthedRoutes } from "@/routes/permissions";
5
+
6
+const queryCurrentUser = () => Promise.resolve({ id: 1, name: '管理员', resourcesList: [{ code: 'form' }, { code: 'table' }] });
2 7
 
3 8
 export default function useUser() {
9
+  const [user, setUser] = useState();
10
+  const menusRef = useRef();
11
+  const routesRef = useRef();
4 12
 
5
-  const [user, setUser] = useState()
13
+  const getCurrentUser = () => new Promise((resolve, reject) => {
14
+    queryCurrentUser().then(res => {
15
+      const permissions = (res.resourcesList || []).map(x => x.code);
6 16
 
7
-  const getCurrent = () => {
8
-    // mock api
9
-    setUser({ id: 1, name: '管理员' })
10
-  }
17
+      // authRoutes 是所有待验证授权的路由
18
+      // authedRoutes 是已经被授权的路由
19
+      const authedRoutes = getAuthedRoutes(authRoutes, permissions);
20
+
21
+      menusRef.current = getMenuItems(authedRoutes);
22
+      routesRef.current = mergeAuthRoutes(defaultRoutes, authedRoutes);
23
+
24
+      setUser(res);
25
+      resolve(res);
26
+    }).catch(reject);
27
+  });
11 28
 
12 29
   return {
13 30
     user,
14
-    getCurrent,
31
+    setUser,
32
+    getCurrentUser,
33
+    menus: menusRef.current || [],
34
+    routes: routesRef.current || [],
15 35
   }
16 36
 
17 37
 }

+ 61
- 0
src/utils/array.js Datei anzeigen

@@ -0,0 +1,61 @@
1
+
2
+/**
3
+ * 数组 转 Tree
4
+ * @param {*} arr 
5
+ * @param {*} parent 
6
+ * @param {*} key 
7
+ * @returns 
8
+ */
9
+export function arr2Tree(arr = [], parent = 'parentId', key = 'key') {
10
+  // 转换为字典
11
+  const dict = arr.reduce((acc, item) => {
12
+    return {
13
+      ...acc,
14
+      [item[key]]: {
15
+        ...item,
16
+        children: []
17
+      }
18
+    }
19
+  }, {});
20
+
21
+  // 挂载父子节点
22
+  const rootId = -1;
23
+  const tree = [];
24
+  for (let item of arr) {
25
+    const parentNodeId = item[parent];
26
+
27
+    if (parentNodeId === rootId) {
28
+      tree.push(dict[item[key]]);
29
+    } else {
30
+      const parentNode = dict[parentNodeId];
31
+      if (parentNode) {
32
+        parentNode.children.push(item);
33
+      }
34
+    }
35
+  }
36
+
37
+  return [tree, dict];
38
+}
39
+
40
+/**
41
+ * 深度展平数组
42
+ * @param {*} arr 
43
+ * @returns 
44
+ */
45
+export function flatten(arr = []) {
46
+  return arr.reduce((acc, it) => {
47
+    const list = Array.isArray(it) ? flatten(it) : it
48
+    return acc.concat(list);
49
+  }, []);
50
+}
51
+
52
+/**
53
+ * 深度数组去重
54
+ * @param {*} arr 
55
+ */
56
+export function uniq(arr = []) {
57
+  const list = flatten(arr);
58
+  return list.reduce((acc, it) => {
59
+    return acc.indexOf(it) > -1 ? acc : acc.concat(it)
60
+  }, []);
61
+}

+ 5
- 0
src/utils/float.js Datei anzeigen

@@ -0,0 +1,5 @@
1
+const epsilonN = N => num => Math.round( num * N + Number.EPSILON ) / N;
2
+
3
+// 可以处理丢失精度的问题
4
+// 比如 epsilon2(0.29 * 100)
5
+export const epsilon2 = epsilonN(1e2);

+ 13
- 0
src/utils/hooks/useBool.js Datei anzeigen

@@ -0,0 +1,13 @@
1
+import React from "react";
2
+
3
+export default function useLoading(initial = false) {
4
+  const [loading, setLoading] = React.useState(initial);
5
+  const loadingRef = React.useRef();
6
+  loadingRef.current = loading;
7
+
8
+  const setTrue = React.useCallback(() => setLoading(true), []);
9
+  const setFalse = React.useCallback(() => setLoading(false), []);
10
+  const toggle = React.useCallback(() => setLoading(!loadingRef.current), []);
11
+
12
+  return [loading, setTrue, setFalse, setLoading, toggle];
13
+}

+ 1
- 4
src/utils/hooks/useRoute.jsx Datei anzeigen

@@ -1,12 +1,9 @@
1 1
 import { useLocation } from "react-router-dom";
2
-import { getRouteArr } from '@/routes/menus';
2
+import { routeArr } from '@/routes/routes';
3 3
 
4 4
 // 获取当前的 route 信息
5 5
 export default function useRoute() {
6 6
   const location = useLocation();
7
-  const routeArr = getRouteArr();
8
-
9 7
   const currentRoute = routeArr.filter(x => x.path === location.pathname)[0];
10
-
11 8
   return currentRoute;
12 9
 }

+ 151
- 0
src/utils/request.js Datei anzeigen

@@ -0,0 +1,151 @@
1
+import axios from "axios";
2
+import { message } from 'antd';
3
+
4
+const instance = axios.create({
5
+  baseURL: import.meta.env.PROD ? SERVER_BASE : import.meta.env.VITE_SERVER_BASE,
6
+  timeout: 10000,
7
+});
8
+
9
+
10
+// 添加请求拦截器
11
+instance.interceptors.request.use(function (config) {
12
+  const { headers = {}, method = 'get', responseType = 'json', download = false, successTip } = config;
13
+  const token = localStorage.getItem('token') || '';
14
+
15
+  let tip = successTip;
16
+  if (tip === undefined) {
17
+    tip = method === 'get' ? false : true;
18
+  }
19
+
20
+  // 在发送请求之前做些什么
21
+  return {
22
+    ...config,
23
+    successTip : tip,
24
+    headers: {
25
+      ...headers,
26
+      Authorization: token,
27
+    },    
28
+    responseType: download ? 'blob' : responseType,
29
+  };
30
+}, function (error) {
31
+  // 对请求错误做些什么
32
+  return Promise.reject(error);
33
+});
34
+
35
+// 添加响应拦截器
36
+instance.interceptors.response.use(function (response) {
37
+  // 2xx 范围内的状态码都会触发该函数。
38
+  // 对响应数据做点什么
39
+
40
+  const { data, config } = response;
41
+  if (config.download && !data.code) {
42
+    return downloadBlob(response, '下载文件');
43
+  }
44
+  
45
+  if (data.code === 1000) {
46
+    if (data.data.token) {
47
+      localStorage.setItem('token', data.data.token);
48
+    }
49
+
50
+    if (config.successTip && !config.silent) {
51
+      message.success(typeof success === 'string' ? successTip : '操作成功');
52
+    }
53
+
54
+    return data.data;
55
+  } else if (data.code === 1001) {
56
+    if (!config.silent) {
57
+      message.error('未登录或者超时, 请重新登录');
58
+    }
59
+  } else {
60
+    if (!config.silent) {
61
+      const errMsg = data.message || '系统错误';
62
+      message.error(errMsg.indexOf('exception') > -1 ? '服务异常' : errMsg);
63
+    }
64
+  }
65
+
66
+  return Promise.reject(response);
67
+}, function (error) {
68
+  // 超出 2xx 范围的状态码都会触发该函数。
69
+  // 对响应错误做点什么
70
+
71
+  console.error(error);
72
+
73
+  return Promise.reject("网络异常, 请重试...");
74
+});
75
+
76
+export default instance;
77
+
78
+export function queryTable(apiRequest) {
79
+  return function (params) {
80
+    const { current, pageSize, ...leftParams } = params;
81
+    return apiRequest({
82
+      pageSize,
83
+      pageNum: params.current,
84
+      ...(leftParams || {}),
85
+    })
86
+      .then((res) => {
87
+        return {
88
+          data: res.records,
89
+          success: true,
90
+          total: res.total,
91
+        };
92
+      })
93
+      .catch((err) => {
94
+        return {
95
+          success: false,
96
+        };
97
+      });
98
+  };
99
+}
100
+
101
+export function queryDict(apiRequest) {
102
+  return function (params, labelKey = 'name', valueKey = 'id') {
103
+    const { current, pageSize, ...leftParams } = params || {};
104
+    return apiRequest({
105
+      pageSize: 9999,
106
+      pageNum: 1,
107
+      ...(leftParams || {}),
108
+    })
109
+      .then((res) => {
110
+        return res?.records?.map((x) => ({
111
+          label: x[labelKey],
112
+          value: x[valueKey],
113
+          ...x,
114
+        }));
115
+      })
116
+      .catch((err) => {
117
+        return {
118
+          success: false,
119
+        };
120
+      });
121
+  };
122
+}
123
+
124
+export function restful(url) {
125
+  const list = params => instance.get(url, { params, successTip: false });
126
+  const get = id => instance.get(`${url}/${id}`,{ successTip: false });
127
+  const add = data => instance.post(url, data);
128
+  const update = (id, data) => instance.put(`${url}/${id}`, data);
129
+  const del = id => instance.delete(`${url}/${id}`);
130
+
131
+  return [list, get, add, update, del];
132
+}
133
+
134
+function downloadBlob(response) {
135
+  let fileName = '未知文件';
136
+  const contentType = response.headers['content-type'];
137
+  const contentDisposition = response.headers['content-disposition'];
138
+  if (contentDisposition) {
139
+    const parts = contentDisposition.split(';filename=');
140
+    if (parts[1]) {
141
+      fileName = decodeURIComponent(parts[1]);
142
+    }
143
+  }
144
+
145
+  const url = window.URL.createObjectURL(new Blob([response.data], { type: contentType }));
146
+  const link = document.createElement('a');
147
+  link.href = url;
148
+  link.setAttribute('download', fileName);
149
+  link.click();
150
+  window.URL.revokeObjectURL(url);
151
+}

+ 3
- 0
vite.config.js Datei anzeigen

@@ -5,6 +5,9 @@ import vitePluginImp from 'vite-plugin-imp'
5 5
 
6 6
 // https://vitejs.dev/config/
7 7
 export default defineConfig({
8
+  server: {
9
+    port: 3000
10
+  },
8 11
   plugins: [
9 12
     react(),
10 13
     vitePluginImp({