Forráskód Böngészése

feature:基础模块
1.菜单管理
2.用户管理

ZZH-wl 3 éve
szülő
commit
398862f81a
39 módosított fájl, 2877 hozzáadás és 315 törlés
  1. 2295 0
      mock/controller/remixIcon.js
  2. 0 1
      mock/index.js
  3. 1 0
      package.json
  4. 39 3
      src/api/menu.js
  5. 19 0
      src/api/user.js
  6. 1 2
      src/extra/VabIconSelector/index.vue
  7. 5 0
      src/main.js
  8. 3 4
      src/store/modules/routes.js
  9. 11 2
      src/utils/index.js
  10. 1 2
      src/vab/components/VabAvatar/index.vue
  11. 6 12
      src/vab/components/VabColumnBar/index.vue
  12. 3 6
      src/vab/components/VabErrorLog/index.vue
  13. 1 2
      src/vab/components/VabFold/index.vue
  14. 1 2
      src/vab/components/VabFullScreen/index.vue
  15. 2 4
      src/vab/components/VabHeader/index.vue
  16. 2 4
      src/vab/components/VabLogo/index.vue
  17. 3 6
      src/vab/components/VabMenu/components/VabMenuItem.vue
  18. 2 4
      src/vab/components/VabMenu/components/VabSubmenu.vue
  19. 4 8
      src/vab/components/VabMenu/index.vue
  20. 2 4
      src/vab/components/VabNav/index.vue
  21. 1 2
      src/vab/components/VabRefresh/index.vue
  22. 7 8
      src/vab/components/VabSideBar/index.vue
  23. 8 16
      src/vab/components/VabTabs/index.vue
  24. 3 6
      src/vab/layouts/VabLayoutColumn/index.vue
  25. 4 8
      src/vab/layouts/VabLayoutCommon/index.vue
  26. 3 6
      src/vab/layouts/VabLayoutComprehensive/index.vue
  27. 2 4
      src/vab/layouts/VabLayoutFloat/index.vue
  28. 3 6
      src/vab/layouts/VabLayoutHorizontal/index.vue
  29. 4 8
      src/vab/layouts/VabLayoutVertical/index.vue
  30. 1 2
      src/vab/layouts/index.vue
  31. 2 4
      src/views/403.vue
  32. 2 4
      src/views/404.vue
  33. 6 12
      src/views/login/index.vue
  34. 2 2
      src/views/system/log.vue
  35. 306 74
      src/views/system/menu/components/MenuEdit.vue
  36. 69 59
      src/views/system/menu/index.vue
  37. 17 6
      src/views/system/user/components/UserEdit.vue
  38. 29 15
      src/views/system/user/index.vue
  39. 7 7
      src/views/test/index.vue

+ 2295 - 0
mock/controller/remixIcon.js

@@ -0,0 +1,2295 @@
+const List = [
+  '24-hours-fill',
+  '24-hours-line',
+  '4k-fill',
+  '4k-line',
+  'a-b',
+  'account-box-fill',
+  'account-box-line',
+  'account-circle-fill',
+  'account-circle-line',
+  'account-pin-box-fill',
+  'account-pin-box-line',
+  'account-pin-circle-fill',
+  'account-pin-circle-line',
+  'add-box-fill',
+  'add-box-line',
+  'add-circle-fill',
+  'add-circle-line',
+  'add-fill',
+  'add-line',
+  'admin-fill',
+  'admin-line',
+  /* "advertisement-fill",
+  "advertisement-line", */
+  'airplay-fill',
+  'airplay-line',
+  'alarm-fill',
+  'alarm-line',
+  'alarm-warning-fill',
+  'alarm-warning-line',
+  'album-fill',
+  'album-line',
+  'alert-fill',
+  'alert-line',
+  'aliens-fill',
+  'aliens-line',
+  'align-bottom',
+  'align-center',
+  'align-justify',
+  'align-left',
+  'align-right',
+  'align-top',
+  'align-vertically',
+  'alipay-fill',
+  'alipay-line',
+  'amazon-fill',
+  'amazon-line',
+  'anchor-fill',
+  'anchor-line',
+  'ancient-gate-fill',
+  'ancient-gate-line',
+  'ancient-pavilion-fill',
+  'ancient-pavilion-line',
+  'android-fill',
+  'android-line',
+  'angularjs-fill',
+  'angularjs-line',
+  'anticlockwise-2-fill',
+  'anticlockwise-2-line',
+  'anticlockwise-fill',
+  'anticlockwise-line',
+  'app-store-fill',
+  'app-store-line',
+  'apple-fill',
+  'apple-line',
+  'apps-2-fill',
+  'apps-2-line',
+  'apps-fill',
+  'apps-line',
+  'archive-drawer-fill',
+  'archive-drawer-line',
+  'archive-fill',
+  'archive-line',
+  'arrow-down-circle-fill',
+  'arrow-down-circle-line',
+  'arrow-down-fill',
+  'arrow-down-line',
+  'arrow-down-s-fill',
+  'arrow-down-s-line',
+  'arrow-drop-down-fill',
+  'arrow-drop-down-line',
+  'arrow-drop-left-fill',
+  'arrow-drop-left-line',
+  'arrow-drop-right-fill',
+  'arrow-drop-right-line',
+  'arrow-drop-up-fill',
+  'arrow-drop-up-line',
+  'arrow-go-back-fill',
+  'arrow-go-back-line',
+  'arrow-go-forward-fill',
+  'arrow-go-forward-line',
+  'arrow-left-circle-fill',
+  'arrow-left-circle-line',
+  'arrow-left-down-fill',
+  'arrow-left-down-line',
+  'arrow-left-fill',
+  'arrow-left-line',
+  'arrow-left-right-fill',
+  'arrow-left-right-line',
+  'arrow-left-s-fill',
+  'arrow-left-s-line',
+  'arrow-left-up-fill',
+  'arrow-left-up-line',
+  'arrow-right-circle-fill',
+  'arrow-right-circle-line',
+  'arrow-right-down-fill',
+  'arrow-right-down-line',
+  'arrow-right-fill',
+  'arrow-right-line',
+  'arrow-right-s-fill',
+  'arrow-right-s-line',
+  'arrow-right-up-fill',
+  'arrow-right-up-line',
+  'arrow-up-circle-fill',
+  'arrow-up-circle-line',
+  'arrow-up-down-fill',
+  'arrow-up-down-line',
+  'arrow-up-fill',
+  'arrow-up-line',
+  'arrow-up-s-fill',
+  'arrow-up-s-line',
+  'artboard-2-fill',
+  'artboard-2-line',
+  'artboard-fill',
+  'artboard-line',
+  'article-fill',
+  'article-line',
+  'aspect-ratio-fill',
+  'aspect-ratio-line',
+  'asterisk',
+  'at-fill',
+  'at-line',
+  'attachment-2',
+  'attachment-fill',
+  'attachment-line',
+  'auction-fill',
+  'auction-line',
+  'award-fill',
+  'award-line',
+  'baidu-fill',
+  'baidu-line',
+  'ball-pen-fill',
+  'ball-pen-line',
+  'bank-card-2-fill',
+  'bank-card-2-line',
+  'bank-card-fill',
+  'bank-card-line',
+  'bank-fill',
+  'bank-line',
+  'bar-chart-2-fill',
+  'bar-chart-2-line',
+  'bar-chart-box-fill',
+  'bar-chart-box-line',
+  'bar-chart-fill',
+  'bar-chart-grouped-fill',
+  'bar-chart-grouped-line',
+  'bar-chart-horizontal-fill',
+  'bar-chart-horizontal-line',
+  'bar-chart-line',
+  'barcode-box-fill',
+  'barcode-box-line',
+  'barcode-fill',
+  'barcode-line',
+  'barricade-fill',
+  'barricade-line',
+  'base-station-fill',
+  'base-station-line',
+  'basketball-fill',
+  'basketball-line',
+  'battery-2-charge-fill',
+  'battery-2-charge-line',
+  'battery-2-fill',
+  'battery-2-line',
+  'battery-charge-fill',
+  'battery-charge-line',
+  'battery-fill',
+  'battery-line',
+  'battery-low-fill',
+  'battery-low-line',
+  'battery-saver-fill',
+  'battery-saver-line',
+  'battery-share-fill',
+  'battery-share-line',
+  'bear-smile-fill',
+  'bear-smile-line',
+  'behance-fill',
+  'behance-line',
+  'bell-fill',
+  'bell-line',
+  'bike-fill',
+  'bike-line',
+  'bilibili-fill',
+  'bilibili-line',
+  'bill-fill',
+  'bill-line',
+  'billiards-fill',
+  'billiards-line',
+  'bit-coin-fill',
+  'bit-coin-line',
+  'blaze-fill',
+  'blaze-line',
+  'bluetooth-connect-fill',
+  'bluetooth-connect-line',
+  'bluetooth-fill',
+  'bluetooth-line',
+  'blur-off-fill',
+  'blur-off-line',
+  'body-scan-fill',
+  'body-scan-line',
+  'bold',
+  'book-2-fill',
+  'book-2-line',
+  'book-3-fill',
+  'book-3-line',
+  'book-fill',
+  'book-line',
+  'book-mark-fill',
+  'book-mark-line',
+  'book-open-fill',
+  'book-open-line',
+  'book-read-fill',
+  'book-read-line',
+  'booklet-fill',
+  'booklet-line',
+  'bookmark-2-fill',
+  'bookmark-2-line',
+  'bookmark-3-fill',
+  'bookmark-3-line',
+  'bookmark-fill',
+  'bookmark-line',
+  'boxing-fill',
+  'boxing-line',
+  'braces-fill',
+  'braces-line',
+  'brackets-fill',
+  'brackets-line',
+  'briefcase-2-fill',
+  'briefcase-2-line',
+  'briefcase-3-fill',
+  'briefcase-3-line',
+  'briefcase-4-fill',
+  'briefcase-4-line',
+  'briefcase-5-fill',
+  'briefcase-5-line',
+  'briefcase-fill',
+  'briefcase-line',
+  'bring-forward',
+  'bring-to-front',
+  'broadcast-fill',
+  'broadcast-line',
+  'brush-2-fill',
+  'brush-2-line',
+  'brush-3-fill',
+  'brush-3-line',
+  'brush-4-fill',
+  'brush-4-line',
+  'brush-fill',
+  'brush-line',
+  'bubble-chart-fill',
+  'bubble-chart-line',
+  'bug-2-fill',
+  'bug-2-line',
+  'bug-fill',
+  'bug-line',
+  'building-2-fill',
+  'building-2-line',
+  'building-3-fill',
+  'building-3-line',
+  'building-4-fill',
+  'building-4-line',
+  'building-fill',
+  'building-line',
+  'bus-2-fill',
+  'bus-2-line',
+  'bus-fill',
+  'bus-line',
+  'bus-wifi-fill',
+  'bus-wifi-line',
+  'cactus-fill',
+  'cactus-line',
+  'cake-2-fill',
+  'cake-2-line',
+  'cake-3-fill',
+  'cake-3-line',
+  'cake-fill',
+  'cake-line',
+  'calculator-fill',
+  'calculator-line',
+  'calendar-2-fill',
+  'calendar-2-line',
+  'calendar-check-fill',
+  'calendar-check-line',
+  'calendar-event-fill',
+  'calendar-event-line',
+  'calendar-fill',
+  'calendar-line',
+  'calendar-todo-fill',
+  'calendar-todo-line',
+  'camera-2-fill',
+  'camera-2-line',
+  'camera-3-fill',
+  'camera-3-line',
+  'camera-fill',
+  'camera-lens-fill',
+  'camera-lens-line',
+  'camera-line',
+  'camera-off-fill',
+  'camera-off-line',
+  'camera-switch-fill',
+  'camera-switch-line',
+  'capsule-fill',
+  'capsule-line',
+  'car-fill',
+  'car-line',
+  'car-washing-fill',
+  'car-washing-line',
+  'caravan-fill',
+  'caravan-line',
+  'cast-fill',
+  'cast-line',
+  'cellphone-fill',
+  'cellphone-line',
+  'celsius-fill',
+  'celsius-line',
+  'centos-fill',
+  'centos-line',
+  'character-recognition-fill',
+  'character-recognition-line',
+  'charging-pile-2-fill',
+  'charging-pile-2-line',
+  'charging-pile-fill',
+  'charging-pile-line',
+  'chat-1-fill',
+  'chat-1-line',
+  'chat-2-fill',
+  'chat-2-line',
+  'chat-3-fill',
+  'chat-3-line',
+  'chat-4-fill',
+  'chat-4-line',
+  'chat-check-fill',
+  'chat-check-line',
+  'chat-delete-fill',
+  'chat-delete-line',
+  'chat-download-fill',
+  'chat-download-line',
+  'chat-follow-up-fill',
+  'chat-follow-up-line',
+  'chat-forward-fill',
+  'chat-forward-line',
+  'chat-heart-fill',
+  'chat-heart-line',
+  'chat-history-fill',
+  'chat-history-line',
+  'chat-new-fill',
+  'chat-new-line',
+  'chat-off-fill',
+  'chat-off-line',
+  'chat-poll-fill',
+  'chat-poll-line',
+  'chat-private-fill',
+  'chat-private-line',
+  'chat-quote-fill',
+  'chat-quote-line',
+  'chat-settings-fill',
+  'chat-settings-line',
+  'chat-smile-2-fill',
+  'chat-smile-2-line',
+  'chat-smile-3-fill',
+  'chat-smile-3-line',
+  'chat-smile-fill',
+  'chat-smile-line',
+  'chat-upload-fill',
+  'chat-upload-line',
+  'chat-voice-fill',
+  'chat-voice-line',
+  'check-double-fill',
+  'check-double-line',
+  'check-fill',
+  'check-line',
+  'checkbox-blank-circle-fill',
+  'checkbox-blank-circle-line',
+  'checkbox-blank-fill',
+  'checkbox-blank-line',
+  'checkbox-circle-fill',
+  'checkbox-circle-line',
+  'checkbox-fill',
+  'checkbox-indeterminate-fill',
+  'checkbox-indeterminate-line',
+  'checkbox-line',
+  'checkbox-multiple-blank-fill',
+  'checkbox-multiple-blank-line',
+  'checkbox-multiple-fill',
+  'checkbox-multiple-line',
+  'china-railway-fill',
+  'china-railway-line',
+  'chrome-fill',
+  'chrome-line',
+  'clapperboard-fill',
+  'clapperboard-line',
+  'clipboard-fill',
+  'clipboard-line',
+  'clockwise-2-fill',
+  'clockwise-2-line',
+  'clockwise-fill',
+  'clockwise-line',
+  'close-circle-fill',
+  'close-circle-line',
+  'close-fill',
+  'close-line',
+  'closed-captioning-fill',
+  'closed-captioning-line',
+  'cloud-fill',
+  'cloud-line',
+  'cloud-off-fill',
+  'cloud-off-line',
+  'cloud-windy-fill',
+  'cloud-windy-line',
+  'cloudy-2-fill',
+  'cloudy-2-line',
+  'cloudy-fill',
+  'cloudy-line',
+  'code-box-fill',
+  'code-box-line',
+  'code-fill',
+  'code-line',
+  'code-s-fill',
+  'code-s-line',
+  'code-s-slash-fill',
+  'code-s-slash-line',
+  'code-view',
+  'codepen-fill',
+  'codepen-line',
+  'coin-fill',
+  'coin-line',
+  'coins-fill',
+  'coins-line',
+  'collage-fill',
+  'collage-line',
+  'command-fill',
+  'command-line',
+  'community-fill',
+  'community-line',
+  'compass-2-fill',
+  'compass-2-line',
+  'compass-3-fill',
+  'compass-3-line',
+  'compass-4-fill',
+  'compass-4-line',
+  'compass-discover-fill',
+  'compass-discover-line',
+  'compass-fill',
+  'compass-line',
+  'compasses-2-fill',
+  'compasses-2-line',
+  'compasses-fill',
+  'compasses-line',
+  'computer-fill',
+  'computer-line',
+  'contacts-book-2-fill',
+  'contacts-book-2-line',
+  'contacts-book-fill',
+  'contacts-book-line',
+  'contacts-book-upload-fill',
+  'contacts-book-upload-line',
+  'contacts-fill',
+  'contacts-line',
+  'contrast-2-fill',
+  'contrast-2-line',
+  'contrast-drop-2-fill',
+  'contrast-drop-2-line',
+  'contrast-drop-fill',
+  'contrast-drop-line',
+  'contrast-fill',
+  'contrast-line',
+  'copper-coin-fill',
+  'copper-coin-line',
+  'copper-diamond-fill',
+  'copper-diamond-line',
+  'copyleft-fill',
+  'copyleft-line',
+  'copyright-fill',
+  'copyright-line',
+  'coreos-fill',
+  'coreos-line',
+  'coupon-2-fill',
+  'coupon-2-line',
+  'coupon-3-fill',
+  'coupon-3-line',
+  'coupon-4-fill',
+  'coupon-4-line',
+  'coupon-5-fill',
+  'coupon-5-line',
+  'coupon-fill',
+  'coupon-line',
+  'cpu-fill',
+  'cpu-line',
+  'creative-commons-by-fill',
+  'creative-commons-by-line',
+  'creative-commons-fill',
+  'creative-commons-line',
+  'creative-commons-nc-fill',
+  'creative-commons-nc-line',
+  'creative-commons-nd-fill',
+  'creative-commons-nd-line',
+  'creative-commons-sa-fill',
+  'creative-commons-sa-line',
+  'creative-commons-zero-fill',
+  'creative-commons-zero-line',
+  'criminal-fill',
+  'criminal-line',
+  'crop-2-fill',
+  'crop-2-line',
+  'crop-fill',
+  'crop-line',
+  'css3-fill',
+  'css3-line',
+  'cup-fill',
+  'cup-line',
+  'currency-fill',
+  'currency-line',
+  'cursor-fill',
+  'cursor-line',
+  'customer-service-2-fill',
+  'customer-service-2-line',
+  'customer-service-fill',
+  'customer-service-line',
+  'dashboard-2-fill',
+  'dashboard-2-line',
+  'dashboard-3-fill',
+  'dashboard-3-line',
+  'dashboard-fill',
+  'dashboard-line',
+  'database-2-fill',
+  'database-2-line',
+  'database-fill',
+  'database-line',
+  'delete-back-2-fill',
+  'delete-back-2-line',
+  'delete-back-fill',
+  'delete-back-line',
+  'delete-bin-2-fill',
+  'delete-bin-2-line',
+  'delete-bin-3-fill',
+  'delete-bin-3-line',
+  'delete-bin-4-fill',
+  'delete-bin-4-line',
+  'delete-bin-5-fill',
+  'delete-bin-5-line',
+  'delete-bin-6-fill',
+  'delete-bin-6-line',
+  'delete-bin-7-fill',
+  'delete-bin-7-line',
+  'delete-bin-fill',
+  'delete-bin-line',
+  'delete-column',
+  'delete-row',
+  'device-fill',
+  'device-line',
+  'device-recover-fill',
+  'device-recover-line',
+  'dingding-fill',
+  'dingding-line',
+  'direction-fill',
+  'direction-line',
+  'disc-fill',
+  'disc-line',
+  'discord-fill',
+  'discord-line',
+  'discuss-fill',
+  'discuss-line',
+  'dislike-fill',
+  'dislike-line',
+  'disqus-fill',
+  'disqus-line',
+  'divide-fill',
+  'divide-line',
+  'donut-chart-fill',
+  'donut-chart-line',
+  'door-closed-fill',
+  'door-closed-line',
+  'door-fill',
+  'door-line',
+  'door-lock-box-fill',
+  'door-lock-box-line',
+  'door-lock-fill',
+  'door-lock-line',
+  'door-open-fill',
+  'door-open-line',
+  'dossier-fill',
+  'dossier-line',
+  'douban-fill',
+  'douban-line',
+  'double-quotes-l',
+  'double-quotes-r',
+  'download-2-fill',
+  'download-2-line',
+  'download-cloud-2-fill',
+  'download-cloud-2-line',
+  'download-cloud-fill',
+  'download-cloud-line',
+  'download-fill',
+  'download-line',
+  'draft-fill',
+  'draft-line',
+  'drag-drop-fill',
+  'drag-drop-line',
+  'drag-move-2-fill',
+  'drag-move-2-line',
+  'drag-move-fill',
+  'drag-move-line',
+  'dribbble-fill',
+  'dribbble-line',
+  'drive-fill',
+  'drive-line',
+  'drizzle-fill',
+  'drizzle-line',
+  'drop-fill',
+  'drop-line',
+  'dropbox-fill',
+  'dropbox-line',
+  'dual-sim-1-fill',
+  'dual-sim-1-line',
+  'dual-sim-2-fill',
+  'dual-sim-2-line',
+  'dv-fill',
+  'dv-line',
+  'dvd-fill',
+  'dvd-line',
+  'e-bike-2-fill',
+  'e-bike-2-line',
+  'e-bike-fill',
+  'e-bike-line',
+  'earth-fill',
+  'earth-line',
+  'earthquake-fill',
+  'earthquake-line',
+  'edge-fill',
+  'edge-line',
+  'edit-2-fill',
+  'edit-2-line',
+  'edit-box-fill',
+  'edit-box-line',
+  'edit-circle-fill',
+  'edit-circle-line',
+  'edit-fill',
+  'edit-line',
+  'eject-fill',
+  'eject-line',
+  'emotion-2-fill',
+  'emotion-2-line',
+  'emotion-fill',
+  'emotion-happy-fill',
+  'emotion-happy-line',
+  'emotion-laugh-fill',
+  'emotion-laugh-line',
+  'emotion-line',
+  'emotion-normal-fill',
+  'emotion-normal-line',
+  'emotion-sad-fill',
+  'emotion-sad-line',
+  'emotion-unhappy-fill',
+  'emotion-unhappy-line',
+  'empathize-fill',
+  'empathize-line',
+  'emphasis-cn',
+  'emphasis',
+  'english-input',
+  'equalizer-fill',
+  'equalizer-line',
+  'eraser-fill',
+  'eraser-line',
+  'error-warning-fill',
+  'error-warning-line',
+  'evernote-fill',
+  'evernote-line',
+  'exchange-box-fill',
+  'exchange-box-line',
+  'exchange-cny-fill',
+  'exchange-cny-line',
+  'exchange-dollar-fill',
+  'exchange-dollar-line',
+  'exchange-fill',
+  'exchange-funds-fill',
+  'exchange-funds-line',
+  'exchange-line',
+  'external-link-fill',
+  'external-link-line',
+  'eye-2-fill',
+  'eye-2-line',
+  'eye-close-fill',
+  'eye-close-line',
+  'eye-fill',
+  'eye-line',
+  'eye-off-fill',
+  'eye-off-line',
+  'facebook-box-fill',
+  'facebook-box-line',
+  'facebook-circle-fill',
+  'facebook-circle-line',
+  'facebook-fill',
+  'facebook-line',
+  'fahrenheit-fill',
+  'fahrenheit-line',
+  'feedback-fill',
+  'feedback-line',
+  'file-2-fill',
+  'file-2-line',
+  'file-3-fill',
+  'file-3-line',
+  'file-4-fill',
+  'file-4-line',
+  'file-add-fill',
+  'file-add-line',
+  'file-chart-2-fill',
+  'file-chart-2-line',
+  'file-chart-fill',
+  'file-chart-line',
+  'file-cloud-fill',
+  'file-cloud-line',
+  'file-code-fill',
+  'file-code-line',
+  'file-copy-2-fill',
+  'file-copy-2-line',
+  'file-copy-fill',
+  'file-copy-line',
+  'file-damage-fill',
+  'file-damage-line',
+  'file-download-fill',
+  'file-download-line',
+  'file-edit-fill',
+  'file-edit-line',
+  'file-excel-2-fill',
+  'file-excel-2-line',
+  'file-excel-fill',
+  'file-excel-line',
+  'file-fill',
+  'file-forbid-fill',
+  'file-forbid-line',
+  'file-gif-fill',
+  'file-gif-line',
+  'file-history-fill',
+  'file-history-line',
+  'file-hwp-fill',
+  'file-hwp-line',
+  'file-info-fill',
+  'file-info-line',
+  'file-line',
+  'file-list-2-fill',
+  'file-list-2-line',
+  'file-list-3-fill',
+  'file-list-3-line',
+  'file-list-fill',
+  'file-list-line',
+  'file-lock-fill',
+  'file-lock-line',
+  'file-mark-fill',
+  'file-mark-line',
+  'file-music-fill',
+  'file-music-line',
+  'file-paper-2-fill',
+  'file-paper-2-line',
+  'file-paper-fill',
+  'file-paper-line',
+  'file-pdf-fill',
+  'file-pdf-line',
+  'file-ppt-2-fill',
+  'file-ppt-2-line',
+  'file-ppt-fill',
+  'file-ppt-line',
+  'file-reduce-fill',
+  'file-reduce-line',
+  'file-search-fill',
+  'file-search-line',
+  'file-settings-fill',
+  'file-settings-line',
+  'file-shield-2-fill',
+  'file-shield-2-line',
+  'file-shield-fill',
+  'file-shield-line',
+  'file-shred-fill',
+  'file-shred-line',
+  'file-text-fill',
+  'file-text-line',
+  'file-transfer-fill',
+  'file-transfer-line',
+  'file-unknow-fill',
+  'file-unknow-line',
+  'file-upload-fill',
+  'file-upload-line',
+  'file-user-fill',
+  'file-user-line',
+  'file-warning-fill',
+  'file-warning-line',
+  'file-word-2-fill',
+  'file-word-2-line',
+  'file-word-fill',
+  'file-word-line',
+  'file-zip-fill',
+  'file-zip-line',
+  'film-fill',
+  'film-line',
+  'filter-2-fill',
+  'filter-2-line',
+  'filter-3-fill',
+  'filter-3-line',
+  'filter-fill',
+  'filter-line',
+  'filter-off-fill',
+  'filter-off-line',
+  'find-replace-fill',
+  'find-replace-line',
+  'finder-fill',
+  'finder-line',
+  'fingerprint-2-fill',
+  'fingerprint-2-line',
+  'fingerprint-fill',
+  'fingerprint-line',
+  'fire-fill',
+  'fire-line',
+  'firefox-fill',
+  'firefox-line',
+  'first-aid-kit-fill',
+  'first-aid-kit-line',
+  'flag-2-fill',
+  'flag-2-line',
+  'flag-fill',
+  'flag-line',
+  'flashlight-fill',
+  'flashlight-line',
+  'flask-fill',
+  'flask-line',
+  'flight-land-fill',
+  'flight-land-line',
+  'flight-takeoff-fill',
+  'flight-takeoff-line',
+  'flood-fill',
+  'flood-line',
+  'flow-chart',
+  'flutter-fill',
+  'flutter-line',
+  'focus-2-fill',
+  'focus-2-line',
+  'focus-3-fill',
+  'focus-3-line',
+  'focus-fill',
+  'focus-line',
+  'foggy-fill',
+  'foggy-line',
+  'folder-2-fill',
+  'folder-2-line',
+  'folder-3-fill',
+  'folder-3-line',
+  'folder-4-fill',
+  'folder-4-line',
+  'folder-5-fill',
+  'folder-5-line',
+  'folder-add-fill',
+  'folder-add-line',
+  'folder-chart-2-fill',
+  'folder-chart-2-line',
+  'folder-chart-fill',
+  'folder-chart-line',
+  'folder-download-fill',
+  'folder-download-line',
+  'folder-fill',
+  'folder-forbid-fill',
+  'folder-forbid-line',
+  'folder-history-fill',
+  'folder-history-line',
+  'folder-info-fill',
+  'folder-info-line',
+  'folder-keyhole-fill',
+  'folder-keyhole-line',
+  'folder-line',
+  'folder-lock-fill',
+  'folder-lock-line',
+  'folder-music-fill',
+  'folder-music-line',
+  'folder-open-fill',
+  'folder-open-line',
+  'folder-received-fill',
+  'folder-received-line',
+  'folder-reduce-fill',
+  'folder-reduce-line',
+  'folder-settings-fill',
+  'folder-settings-line',
+  'folder-shared-fill',
+  'folder-shared-line',
+  'folder-shield-2-fill',
+  'folder-shield-2-line',
+  'folder-shield-fill',
+  'folder-shield-line',
+  'folder-transfer-fill',
+  'folder-transfer-line',
+  'folder-unknow-fill',
+  'folder-unknow-line',
+  'folder-upload-fill',
+  'folder-upload-line',
+  'folder-user-fill',
+  'folder-user-line',
+  'folder-warning-fill',
+  'folder-warning-line',
+  'folder-zip-fill',
+  'folder-zip-line',
+  'folders-fill',
+  'folders-line',
+  'font-color',
+  'font-size-2',
+  'font-size',
+  'football-fill',
+  'football-line',
+  'footprint-fill',
+  'footprint-line',
+  'forbid-2-fill',
+  'forbid-2-line',
+  'forbid-fill',
+  'forbid-line',
+  'format-clear',
+  'fridge-fill',
+  'fridge-line',
+  'fullscreen-exit-fill',
+  'fullscreen-exit-line',
+  'fullscreen-fill',
+  'fullscreen-line',
+  'function-fill',
+  'function-line',
+  'functions',
+  'funds-box-fill',
+  'funds-box-line',
+  'funds-fill',
+  'funds-line',
+  'gallery-fill',
+  'gallery-line',
+  'gallery-upload-fill',
+  'gallery-upload-line',
+  'game-fill',
+  'game-line',
+  'gamepad-fill',
+  'gamepad-line',
+  'gas-station-fill',
+  'gas-station-line',
+  'gatsby-fill',
+  'gatsby-line',
+  'genderless-fill',
+  'genderless-line',
+  'ghost-2-fill',
+  'ghost-2-line',
+  'ghost-fill',
+  'ghost-line',
+  'ghost-smile-fill',
+  'ghost-smile-line',
+  'gift-2-fill',
+  'gift-2-line',
+  'gift-fill',
+  'gift-line',
+  'git-branch-fill',
+  'git-branch-line',
+  'git-commit-fill',
+  'git-commit-line',
+  'git-merge-fill',
+  'git-merge-line',
+  'git-pull-request-fill',
+  'git-pull-request-line',
+  'git-repository-commits-fill',
+  'git-repository-commits-line',
+  'git-repository-fill',
+  'git-repository-line',
+  'git-repository-private-fill',
+  'git-repository-private-line',
+  'github-fill',
+  'github-line',
+  'gitlab-fill',
+  'gitlab-line',
+  'global-fill',
+  'global-line',
+  'globe-fill',
+  'globe-line',
+  'goblet-fill',
+  'goblet-line',
+  'google-fill',
+  'google-line',
+  'google-play-fill',
+  'google-play-line',
+  'government-fill',
+  'government-line',
+  'gps-fill',
+  'gps-line',
+  'gradienter-fill',
+  'gradienter-line',
+  'grid-fill',
+  'grid-line',
+  'group-2-fill',
+  'group-2-line',
+  'group-fill',
+  'group-line',
+  'guide-fill',
+  'guide-line',
+  'h-1',
+  'h-2',
+  'h-3',
+  'h-4',
+  'h-5',
+  'h-6',
+  'hail-fill',
+  'hail-line',
+  'hammer-fill',
+  'hammer-line',
+  'hand-coin-fill',
+  'hand-coin-line',
+  'hand-heart-fill',
+  'hand-heart-line',
+  'hand-sanitizer-fill',
+  'hand-sanitizer-line',
+  'handbag-fill',
+  'handbag-line',
+  'hard-drive-2-fill',
+  'hard-drive-2-line',
+  'hard-drive-fill',
+  'hard-drive-line',
+  'hashtag',
+  'haze-2-fill',
+  'haze-2-line',
+  'haze-fill',
+  'haze-line',
+  'hd-fill',
+  'hd-line',
+  'heading',
+  'headphone-fill',
+  'headphone-line',
+  'health-book-fill',
+  'health-book-line',
+  'heart-2-fill',
+  'heart-2-line',
+  'heart-3-fill',
+  'heart-3-line',
+  'heart-add-fill',
+  'heart-add-line',
+  'heart-fill',
+  'heart-line',
+  'heart-pulse-fill',
+  'heart-pulse-line',
+  'hearts-fill',
+  'hearts-line',
+  'heavy-showers-fill',
+  'heavy-showers-line',
+  'history-fill',
+  'history-line',
+  'home-2-fill',
+  'home-2-line',
+  'home-3-fill',
+  'home-3-line',
+  'home-4-fill',
+  'home-4-line',
+  'home-5-fill',
+  'home-5-line',
+  'home-6-fill',
+  'home-6-line',
+  'home-7-fill',
+  'home-7-line',
+  'home-8-fill',
+  'home-8-line',
+  'home-fill',
+  'home-gear-fill',
+  'home-gear-line',
+  'home-heart-fill',
+  'home-heart-line',
+  'home-line',
+  'home-smile-2-fill',
+  'home-smile-2-line',
+  'home-smile-fill',
+  'home-smile-line',
+  'home-wifi-fill',
+  'home-wifi-line',
+  'honor-of-kings-fill',
+  'honor-of-kings-line',
+  'honour-fill',
+  'honour-line',
+  'hospital-fill',
+  'hospital-line',
+  'hotel-bed-fill',
+  'hotel-bed-line',
+  'hotel-fill',
+  'hotel-line',
+  'hotspot-fill',
+  'hotspot-line',
+  'hq-fill',
+  'hq-line',
+  'html5-fill',
+  'html5-line',
+  'ie-fill',
+  'ie-line',
+  'image-2-fill',
+  'image-2-line',
+  'image-add-fill',
+  'image-add-line',
+  'image-edit-fill',
+  'image-edit-line',
+  'image-fill',
+  'image-line',
+  'inbox-archive-fill',
+  'inbox-archive-line',
+  'inbox-fill',
+  'inbox-line',
+  'inbox-unarchive-fill',
+  'inbox-unarchive-line',
+  'increase-decrease-fill',
+  'increase-decrease-line',
+  'indent-decrease',
+  'indent-increase',
+  'indeterminate-circle-fill',
+  'indeterminate-circle-line',
+  'information-fill',
+  'information-line',
+  'infrared-thermometer-fill',
+  'infrared-thermometer-line',
+  'ink-bottle-fill',
+  'ink-bottle-line',
+  'input-cursor-move',
+  'input-method-fill',
+  'input-method-line',
+  'insert-column-left',
+  'insert-column-right',
+  'insert-row-bottom',
+  'insert-row-top',
+  'instagram-fill',
+  'instagram-line',
+  'install-fill',
+  'install-line',
+  'invision-fill',
+  'invision-line',
+  'italic',
+  'kakao-talk-fill',
+  'kakao-talk-line',
+  'key-2-fill',
+  'key-2-line',
+  'key-fill',
+  'key-line',
+  'keyboard-box-fill',
+  'keyboard-box-line',
+  'keyboard-fill',
+  'keyboard-line',
+  'keynote-fill',
+  'keynote-line',
+  'knife-blood-fill',
+  'knife-blood-line',
+  'knife-fill',
+  'knife-line',
+  'landscape-fill',
+  'landscape-line',
+  'layout-2-fill',
+  'layout-2-line',
+  'layout-3-fill',
+  'layout-3-line',
+  'layout-4-fill',
+  'layout-4-line',
+  'layout-5-fill',
+  'layout-5-line',
+  'layout-6-fill',
+  'layout-6-line',
+  'layout-bottom-2-fill',
+  'layout-bottom-2-line',
+  'layout-bottom-fill',
+  'layout-bottom-line',
+  'layout-column-fill',
+  'layout-column-line',
+  'layout-fill',
+  'layout-grid-fill',
+  'layout-grid-line',
+  'layout-left-2-fill',
+  'layout-left-2-line',
+  'layout-left-fill',
+  'layout-left-line',
+  'layout-line',
+  'layout-masonry-fill',
+  'layout-masonry-line',
+  'layout-right-2-fill',
+  'layout-right-2-line',
+  'layout-right-fill',
+  'layout-right-line',
+  'layout-row-fill',
+  'layout-row-line',
+  'layout-top-2-fill',
+  'layout-top-2-line',
+  'layout-top-fill',
+  'layout-top-line',
+  'leaf-fill',
+  'leaf-line',
+  'lifebuoy-fill',
+  'lifebuoy-line',
+  'lightbulb-fill',
+  'lightbulb-flash-fill',
+  'lightbulb-flash-line',
+  'lightbulb-line',
+  'line-chart-fill',
+  'line-chart-line',
+  'line-fill',
+  'line-height',
+  'line-line',
+  'link-m',
+  'link-unlink-m',
+  'link-unlink',
+  'link',
+  'linkedin-box-fill',
+  'linkedin-box-line',
+  'linkedin-fill',
+  'linkedin-line',
+  'links-fill',
+  'links-line',
+  'list-check-2',
+  'list-check',
+  'list-ordered',
+  'list-settings-fill',
+  'list-settings-line',
+  'list-unordered',
+  'live-fill',
+  'live-line',
+  'loader-2-fill',
+  'loader-2-line',
+  'loader-3-fill',
+  'loader-3-line',
+  'loader-4-fill',
+  'loader-4-line',
+  'loader-5-fill',
+  'loader-5-line',
+  'loader-fill',
+  'loader-line',
+  'lock-2-fill',
+  'lock-2-line',
+  'lock-fill',
+  'lock-line',
+  'lock-password-fill',
+  'lock-password-line',
+  'lock-unlock-fill',
+  'lock-unlock-line',
+  'login-box-fill',
+  'login-box-line',
+  'login-circle-fill',
+  'login-circle-line',
+  'logout-box-fill',
+  'logout-box-line',
+  'logout-box-r-fill',
+  'logout-box-r-line',
+  'logout-circle-fill',
+  'logout-circle-line',
+  'logout-circle-r-fill',
+  'logout-circle-r-line',
+  'luggage-cart-fill',
+  'luggage-cart-line',
+  'luggage-deposit-fill',
+  'luggage-deposit-line',
+  'lungs-fill',
+  'lungs-line',
+  'mac-fill',
+  'mac-line',
+  'macbook-fill',
+  'macbook-line',
+  'magic-fill',
+  'magic-line',
+  'mail-add-fill',
+  'mail-add-line',
+  'mail-check-fill',
+  'mail-check-line',
+  'mail-close-fill',
+  'mail-close-line',
+  'mail-download-fill',
+  'mail-download-line',
+  'mail-fill',
+  'mail-forbid-fill',
+  'mail-forbid-line',
+  'mail-line',
+  'mail-lock-fill',
+  'mail-lock-line',
+  'mail-open-fill',
+  'mail-open-line',
+  'mail-send-fill',
+  'mail-send-line',
+  'mail-settings-fill',
+  'mail-settings-line',
+  'mail-star-fill',
+  'mail-star-line',
+  'mail-unread-fill',
+  'mail-unread-line',
+  'mail-volume-fill',
+  'mail-volume-line',
+  'map-2-fill',
+  'map-2-line',
+  'map-fill',
+  'map-line',
+  'map-pin-2-fill',
+  'map-pin-2-line',
+  'map-pin-3-fill',
+  'map-pin-3-line',
+  'map-pin-4-fill',
+  'map-pin-4-line',
+  'map-pin-5-fill',
+  'map-pin-5-line',
+  'map-pin-add-fill',
+  'map-pin-add-line',
+  'map-pin-fill',
+  'map-pin-line',
+  'map-pin-range-fill',
+  'map-pin-range-line',
+  'map-pin-time-fill',
+  'map-pin-time-line',
+  'map-pin-user-fill',
+  'map-pin-user-line',
+  'mark-pen-fill',
+  'mark-pen-line',
+  'markdown-fill',
+  'markdown-line',
+  'markup-fill',
+  'markup-line',
+  'mastercard-fill',
+  'mastercard-line',
+  'mastodon-fill',
+  'mastodon-line',
+  'medal-2-fill',
+  'medal-2-line',
+  'medal-fill',
+  'medal-line',
+  'medicine-bottle-fill',
+  'medicine-bottle-line',
+  'medium-fill',
+  'medium-line',
+  'men-fill',
+  'men-line',
+  'mental-health-fill',
+  'mental-health-line',
+  'menu-2-fill',
+  'menu-2-line',
+  'menu-3-fill',
+  'menu-3-line',
+  'menu-4-fill',
+  'menu-4-line',
+  'menu-5-fill',
+  'menu-5-line',
+  'menu-add-fill',
+  'menu-add-line',
+  'menu-fill',
+  'menu-fold-fill',
+  'menu-fold-line',
+  'menu-line',
+  'menu-unfold-fill',
+  'menu-unfold-line',
+  'merge-cells-horizontal',
+  'merge-cells-vertical',
+  'message-2-fill',
+  'message-2-line',
+  'message-3-fill',
+  'message-3-line',
+  'message-fill',
+  'message-line',
+  'messenger-fill',
+  'messenger-line',
+  'meteor-fill',
+  'meteor-line',
+  'mic-2-fill',
+  'mic-2-line',
+  'mic-fill',
+  'mic-line',
+  'mic-off-fill',
+  'mic-off-line',
+  'mickey-fill',
+  'mickey-line',
+  'microscope-fill',
+  'microscope-line',
+  'microsoft-fill',
+  'microsoft-line',
+  'mind-map',
+  'mini-program-fill',
+  'mini-program-line',
+  'mist-fill',
+  'mist-line',
+  'money-cny-box-fill',
+  'money-cny-box-line',
+  'money-cny-circle-fill',
+  'money-cny-circle-line',
+  'money-dollar-box-fill',
+  'money-dollar-box-line',
+  'money-dollar-circle-fill',
+  'money-dollar-circle-line',
+  'money-euro-box-fill',
+  'money-euro-box-line',
+  'money-euro-circle-fill',
+  'money-euro-circle-line',
+  'money-pound-box-fill',
+  'money-pound-box-line',
+  'money-pound-circle-fill',
+  'money-pound-circle-line',
+  'moon-clear-fill',
+  'moon-clear-line',
+  'moon-cloudy-fill',
+  'moon-cloudy-line',
+  'moon-fill',
+  'moon-foggy-fill',
+  'moon-foggy-line',
+  'moon-line',
+  'more-2-fill',
+  'more-2-line',
+  'more-fill',
+  'more-line',
+  'motorbike-fill',
+  'motorbike-line',
+  'mouse-fill',
+  'mouse-line',
+  'movie-2-fill',
+  'movie-2-line',
+  'movie-fill',
+  'movie-line',
+  'music-2-fill',
+  'music-2-line',
+  'music-fill',
+  'music-line',
+  'mv-fill',
+  'mv-line',
+  'navigation-fill',
+  'navigation-line',
+  'netease-cloud-music-fill',
+  'netease-cloud-music-line',
+  'netflix-fill',
+  'netflix-line',
+  'newspaper-fill',
+  'newspaper-line',
+  'node-tree',
+  'notification-2-fill',
+  'notification-2-line',
+  'notification-3-fill',
+  'notification-3-line',
+  'notification-4-fill',
+  'notification-4-line',
+  'notification-badge-fill',
+  'notification-badge-line',
+  'notification-fill',
+  'notification-line',
+  'notification-off-fill',
+  'notification-off-line',
+  'npmjs-fill',
+  'npmjs-line',
+  'number-0',
+  'number-1',
+  'number-2',
+  'number-3',
+  'number-4',
+  'number-5',
+  'number-6',
+  'number-7',
+  'number-8',
+  'number-9',
+  'numbers-fill',
+  'numbers-line',
+  'nurse-fill',
+  'nurse-line',
+  'oil-fill',
+  'oil-line',
+  'omega',
+  'open-arm-fill',
+  'open-arm-line',
+  'open-source-fill',
+  'open-source-line',
+  'opera-fill',
+  'opera-line',
+  'order-play-fill',
+  'order-play-line',
+  'organization-chart',
+  'outlet-2-fill',
+  'outlet-2-line',
+  'outlet-fill',
+  'outlet-line',
+  'page-separator',
+  'pages-fill',
+  'pages-line',
+  'paint-brush-fill',
+  'paint-brush-line',
+  'paint-fill',
+  'paint-line',
+  'palette-fill',
+  'palette-line',
+  'pantone-fill',
+  'pantone-line',
+  'paragraph',
+  'parent-fill',
+  'parent-line',
+  'parentheses-fill',
+  'parentheses-line',
+  'parking-box-fill',
+  'parking-box-line',
+  'parking-fill',
+  'parking-line',
+  'passport-fill',
+  'passport-line',
+  'patreon-fill',
+  'patreon-line',
+  'pause-circle-fill',
+  'pause-circle-line',
+  'pause-fill',
+  'pause-line',
+  'pause-mini-fill',
+  'pause-mini-line',
+  'paypal-fill',
+  'paypal-line',
+  'pen-nib-fill',
+  'pen-nib-line',
+  'pencil-fill',
+  'pencil-line',
+  'pencil-ruler-2-fill',
+  'pencil-ruler-2-line',
+  'pencil-ruler-fill',
+  'pencil-ruler-line',
+  'percent-fill',
+  'percent-line',
+  'phone-camera-fill',
+  'phone-camera-line',
+  'phone-fill',
+  'phone-find-fill',
+  'phone-find-line',
+  'phone-line',
+  'phone-lock-fill',
+  'phone-lock-line',
+  'picture-in-picture-2-fill',
+  'picture-in-picture-2-line',
+  'picture-in-picture-exit-fill',
+  'picture-in-picture-exit-line',
+  'picture-in-picture-fill',
+  'picture-in-picture-line',
+  'pie-chart-2-fill',
+  'pie-chart-2-line',
+  'pie-chart-box-fill',
+  'pie-chart-box-line',
+  'pie-chart-fill',
+  'pie-chart-line',
+  'pin-distance-fill',
+  'pin-distance-line',
+  'ping-pong-fill',
+  'ping-pong-line',
+  'pinterest-fill',
+  'pinterest-line',
+  'pinyin-input',
+  'pixelfed-fill',
+  'pixelfed-line',
+  'plane-fill',
+  'plane-line',
+  'plant-fill',
+  'plant-line',
+  'play-circle-fill',
+  'play-circle-line',
+  'play-fill',
+  'play-line',
+  'play-list-2-fill',
+  'play-list-2-line',
+  'play-list-add-fill',
+  'play-list-add-line',
+  'play-list-fill',
+  'play-list-line',
+  'play-mini-fill',
+  'play-mini-line',
+  'playstation-fill',
+  'playstation-line',
+  'plug-2-fill',
+  'plug-2-line',
+  'plug-fill',
+  'plug-line',
+  'polaroid-2-fill',
+  'polaroid-2-line',
+  'polaroid-fill',
+  'polaroid-line',
+  'police-car-fill',
+  'police-car-line',
+  'price-tag-2-fill',
+  'price-tag-2-line',
+  'price-tag-3-fill',
+  'price-tag-3-line',
+  'price-tag-fill',
+  'price-tag-line',
+  'printer-cloud-fill',
+  'printer-cloud-line',
+  'printer-fill',
+  'printer-line',
+  'product-hunt-fill',
+  'product-hunt-line',
+  'profile-fill',
+  'profile-line',
+  'projector-2-fill',
+  'projector-2-line',
+  'projector-fill',
+  'projector-line',
+  'psychotherapy-fill',
+  'psychotherapy-line',
+  'pulse-fill',
+  'pulse-line',
+  'pushpin-2-fill',
+  'pushpin-2-line',
+  'pushpin-fill',
+  'pushpin-line',
+  'qq-fill',
+  'qq-line',
+  'qr-code-fill',
+  'qr-code-line',
+  'qr-scan-2-fill',
+  'qr-scan-2-line',
+  'qr-scan-fill',
+  'qr-scan-line',
+  'question-answer-fill',
+  'question-answer-line',
+  'question-fill',
+  'question-line',
+  'question-mark',
+  'questionnaire-fill',
+  'questionnaire-line',
+  'quill-pen-fill',
+  'quill-pen-line',
+  'radar-fill',
+  'radar-line',
+  'radio-2-fill',
+  'radio-2-line',
+  'radio-button-fill',
+  'radio-button-line',
+  'radio-fill',
+  'radio-line',
+  'rainbow-fill',
+  'rainbow-line',
+  'rainy-fill',
+  'rainy-line',
+  'reactjs-fill',
+  'reactjs-line',
+  'record-circle-fill',
+  'record-circle-line',
+  'record-mail-fill',
+  'record-mail-line',
+  'recycle-fill',
+  'recycle-line',
+  'red-packet-fill',
+  'red-packet-line',
+  'reddit-fill',
+  'reddit-line',
+  'refresh-fill',
+  'refresh-line',
+  'refund-2-fill',
+  'refund-2-line',
+  'refund-fill',
+  'refund-line',
+  'registered-fill',
+  'registered-line',
+  'remixicon-fill',
+  'remixicon-line',
+  'remote-control-2-fill',
+  'remote-control-2-line',
+  'remote-control-fill',
+  'remote-control-line',
+  'repeat-2-fill',
+  'repeat-2-line',
+  'repeat-fill',
+  'repeat-line',
+  'repeat-one-fill',
+  'repeat-one-line',
+  'reply-all-fill',
+  'reply-all-line',
+  'reply-fill',
+  'reply-line',
+  'reserved-fill',
+  'reserved-line',
+  'rest-time-fill',
+  'rest-time-line',
+  'restart-fill',
+  'restart-line',
+  'restaurant-2-fill',
+  'restaurant-2-line',
+  'restaurant-fill',
+  'restaurant-line',
+  'rewind-fill',
+  'rewind-line',
+  'rewind-mini-fill',
+  'rewind-mini-line',
+  'rhythm-fill',
+  'rhythm-line',
+  'riding-fill',
+  'riding-line',
+  'road-map-fill',
+  'road-map-line',
+  'roadster-fill',
+  'roadster-line',
+  'robot-fill',
+  'robot-line',
+  'rocket-2-fill',
+  'rocket-2-line',
+  'rocket-fill',
+  'rocket-line',
+  'rotate-lock-fill',
+  'rotate-lock-line',
+  'rounded-corner',
+  'route-fill',
+  'route-line',
+  'router-fill',
+  'router-line',
+  'rss-fill',
+  'rss-line',
+  'ruler-2-fill',
+  'ruler-2-line',
+  'ruler-fill',
+  'ruler-line',
+  'run-fill',
+  'run-line',
+  'safari-fill',
+  'safari-line',
+  'safe-2-fill',
+  'safe-2-line',
+  'safe-fill',
+  'safe-line',
+  'sailboat-fill',
+  'sailboat-line',
+  'save-2-fill',
+  'save-2-line',
+  'save-3-fill',
+  'save-3-line',
+  'save-fill',
+  'save-line',
+  'scales-2-fill',
+  'scales-2-line',
+  'scales-3-fill',
+  'scales-3-line',
+  'scales-fill',
+  'scales-line',
+  'scan-2-fill',
+  'scan-2-line',
+  'scan-fill',
+  'scan-line',
+  'scissors-2-fill',
+  'scissors-2-line',
+  'scissors-cut-fill',
+  'scissors-cut-line',
+  'scissors-fill',
+  'scissors-line',
+  'screenshot-2-fill',
+  'screenshot-2-line',
+  'screenshot-fill',
+  'screenshot-line',
+  'sd-card-fill',
+  'sd-card-line',
+  'sd-card-mini-fill',
+  'sd-card-mini-line',
+  'search-2-fill',
+  'search-2-line',
+  'search-eye-fill',
+  'search-eye-line',
+  'search-fill',
+  'search-line',
+  'secure-payment-fill',
+  'secure-payment-line',
+  'seedling-fill',
+  'seedling-line',
+  'send-backward',
+  'send-plane-2-fill',
+  'send-plane-2-line',
+  'send-plane-fill',
+  'send-plane-line',
+  'send-to-back',
+  'sensor-fill',
+  'sensor-line',
+  'separator',
+  'server-fill',
+  'server-line',
+  'service-fill',
+  'service-line',
+  'settings-2-fill',
+  'settings-2-line',
+  'settings-3-fill',
+  'settings-3-line',
+  'settings-4-fill',
+  'settings-4-line',
+  'settings-5-fill',
+  'settings-5-line',
+  'settings-6-fill',
+  'settings-6-line',
+  'settings-fill',
+  'settings-line',
+  'shape-2-fill',
+  'shape-2-line',
+  'shape-fill',
+  'shape-line',
+  'share-box-fill',
+  'share-box-line',
+  'share-circle-fill',
+  'share-circle-line',
+  'share-fill',
+  'share-forward-2-fill',
+  'share-forward-2-line',
+  'share-forward-box-fill',
+  'share-forward-box-line',
+  'share-forward-fill',
+  'share-forward-line',
+  'share-line',
+  'shield-check-fill',
+  'shield-check-line',
+  'shield-cross-fill',
+  'shield-cross-line',
+  'shield-fill',
+  'shield-flash-fill',
+  'shield-flash-line',
+  'shield-keyhole-fill',
+  'shield-keyhole-line',
+  'shield-line',
+  'shield-star-fill',
+  'shield-star-line',
+  'shield-user-fill',
+  'shield-user-line',
+  'ship-2-fill',
+  'ship-2-line',
+  'ship-fill',
+  'ship-line',
+  'shirt-fill',
+  'shirt-line',
+  'shopping-bag-2-fill',
+  'shopping-bag-2-line',
+  'shopping-bag-3-fill',
+  'shopping-bag-3-line',
+  'shopping-bag-fill',
+  'shopping-bag-line',
+  'shopping-basket-2-fill',
+  'shopping-basket-2-line',
+  'shopping-basket-fill',
+  'shopping-basket-line',
+  'shopping-cart-2-fill',
+  'shopping-cart-2-line',
+  'shopping-cart-fill',
+  'shopping-cart-line',
+  'showers-fill',
+  'showers-line',
+  'shuffle-fill',
+  'shuffle-line',
+  'shut-down-fill',
+  'shut-down-line',
+  'side-bar-fill',
+  'side-bar-line',
+  'signal-tower-fill',
+  'signal-tower-line',
+  'signal-wifi-1-fill',
+  'signal-wifi-1-line',
+  'signal-wifi-2-fill',
+  'signal-wifi-2-line',
+  'signal-wifi-3-fill',
+  'signal-wifi-3-line',
+  'signal-wifi-error-fill',
+  'signal-wifi-error-line',
+  'signal-wifi-fill',
+  'signal-wifi-line',
+  'signal-wifi-off-fill',
+  'signal-wifi-off-line',
+  'sim-card-2-fill',
+  'sim-card-2-line',
+  'sim-card-fill',
+  'sim-card-line',
+  'single-quotes-l',
+  'single-quotes-r',
+  'sip-fill',
+  'sip-line',
+  'skip-back-fill',
+  'skip-back-line',
+  'skip-back-mini-fill',
+  'skip-back-mini-line',
+  'skip-forward-fill',
+  'skip-forward-line',
+  'skip-forward-mini-fill',
+  'skip-forward-mini-line',
+  'skull-2-fill',
+  'skull-2-line',
+  'skull-fill',
+  'skull-line',
+  'skype-fill',
+  'skype-line',
+  'slack-fill',
+  'slack-line',
+  'slice-fill',
+  'slice-line',
+  'slideshow-2-fill',
+  'slideshow-2-line',
+  'slideshow-3-fill',
+  'slideshow-3-line',
+  'slideshow-4-fill',
+  'slideshow-4-line',
+  'slideshow-fill',
+  'slideshow-line',
+  'smartphone-fill',
+  'smartphone-line',
+  'snapchat-fill',
+  'snapchat-line',
+  'snowy-fill',
+  'snowy-line',
+  'sort-asc',
+  'sort-desc',
+  'sound-module-fill',
+  'sound-module-line',
+  'soundcloud-fill',
+  'soundcloud-line',
+  'space-ship-fill',
+  'space-ship-line',
+  'space',
+  'spam-2-fill',
+  'spam-2-line',
+  'spam-3-fill',
+  'spam-3-line',
+  'spam-fill',
+  'spam-line',
+  'speaker-2-fill',
+  'speaker-2-line',
+  'speaker-3-fill',
+  'speaker-3-line',
+  'speaker-fill',
+  'speaker-line',
+  'spectrum-fill',
+  'spectrum-line',
+  'speed-fill',
+  'speed-line',
+  'speed-mini-fill',
+  'speed-mini-line',
+  'split-cells-horizontal',
+  'split-cells-vertical',
+  'spotify-fill',
+  'spotify-line',
+  'spy-fill',
+  'spy-line',
+  'stack-fill',
+  'stack-line',
+  'stack-overflow-fill',
+  'stack-overflow-line',
+  'stackshare-fill',
+  'stackshare-line',
+  'star-fill',
+  'star-half-fill',
+  'star-half-line',
+  'star-half-s-fill',
+  'star-half-s-line',
+  'star-line',
+  'star-s-fill',
+  'star-s-line',
+  'star-smile-fill',
+  'star-smile-line',
+  'steam-fill',
+  'steam-line',
+  'steering-2-fill',
+  'steering-2-line',
+  'steering-fill',
+  'steering-line',
+  'stethoscope-fill',
+  'stethoscope-line',
+  'sticky-note-2-fill',
+  'sticky-note-2-line',
+  'sticky-note-fill',
+  'sticky-note-line',
+  'stock-fill',
+  'stock-line',
+  'stop-circle-fill',
+  'stop-circle-line',
+  'stop-fill',
+  'stop-line',
+  'stop-mini-fill',
+  'stop-mini-line',
+  'store-2-fill',
+  'store-2-line',
+  'store-3-fill',
+  'store-3-line',
+  'store-fill',
+  'store-line',
+  'strikethrough-2',
+  'strikethrough',
+  'subscript-2',
+  'subscript',
+  'subtract-fill',
+  'subtract-line',
+  'subway-fill',
+  'subway-line',
+  'subway-wifi-fill',
+  'subway-wifi-line',
+  'suitcase-2-fill',
+  'suitcase-2-line',
+  'suitcase-3-fill',
+  'suitcase-3-line',
+  'suitcase-fill',
+  'suitcase-line',
+  'sun-cloudy-fill',
+  'sun-cloudy-line',
+  'sun-fill',
+  'sun-foggy-fill',
+  'sun-foggy-line',
+  'sun-line',
+  'superscript-2',
+  'superscript',
+  'surgical-mask-fill',
+  'surgical-mask-line',
+  'surround-sound-fill',
+  'surround-sound-line',
+  'survey-fill',
+  'survey-line',
+  'swap-box-fill',
+  'swap-box-line',
+  'swap-fill',
+  'swap-line',
+  'switch-fill',
+  'switch-line',
+  'sword-fill',
+  'sword-line',
+  'syringe-fill',
+  'syringe-line',
+  't-box-fill',
+  't-box-line',
+  't-shirt-2-fill',
+  't-shirt-2-line',
+  't-shirt-air-fill',
+  't-shirt-air-line',
+  't-shirt-fill',
+  't-shirt-line',
+  'table-2',
+  'table-alt-fill',
+  'table-alt-line',
+  'table-fill',
+  'table-line',
+  'tablet-fill',
+  'tablet-line',
+  'takeaway-fill',
+  'takeaway-line',
+  'taobao-fill',
+  'taobao-line',
+  'tape-fill',
+  'tape-line',
+  'task-fill',
+  'task-line',
+  'taxi-fill',
+  'taxi-line',
+  'taxi-wifi-fill',
+  'taxi-wifi-line',
+  'team-fill',
+  'team-line',
+  'telegram-fill',
+  'telegram-line',
+  'temp-cold-fill',
+  'temp-cold-line',
+  'temp-hot-fill',
+  'temp-hot-line',
+  'terminal-box-fill',
+  'terminal-box-line',
+  'terminal-fill',
+  'terminal-line',
+  'terminal-window-fill',
+  'terminal-window-line',
+  'test-tube-fill',
+  'test-tube-line',
+  'text-direction-l',
+  'text-direction-r',
+  'text-spacing',
+  'text-wrap',
+  'text',
+  'thermometer-fill',
+  'thermometer-line',
+  'thumb-down-fill',
+  'thumb-down-line',
+  'thumb-up-fill',
+  'thumb-up-line',
+  'thunderstorms-fill',
+  'thunderstorms-line',
+  'ticket-2-fill',
+  'ticket-2-line',
+  'ticket-fill',
+  'ticket-line',
+  'time-fill',
+  'time-line',
+  'timer-2-fill',
+  'timer-2-line',
+  'timer-fill',
+  'timer-flash-fill',
+  'timer-flash-line',
+  'timer-line',
+  'todo-fill',
+  'todo-line',
+  'toggle-fill',
+  'toggle-line',
+  'tools-fill',
+  'tools-line',
+  'tornado-fill',
+  'tornado-line',
+  'trademark-fill',
+  'trademark-line',
+  'traffic-light-fill',
+  'traffic-light-line',
+  'train-fill',
+  'train-line',
+  'train-wifi-fill',
+  'train-wifi-line',
+  'translate-2',
+  'translate',
+  'travesti-fill',
+  'travesti-line',
+  'treasure-map-fill',
+  'treasure-map-line',
+  'trello-fill',
+  'trello-line',
+  'trophy-fill',
+  'trophy-line',
+  'truck-fill',
+  'truck-line',
+  'tumblr-fill',
+  'tumblr-line',
+  'tv-2-fill',
+  'tv-2-line',
+  'tv-fill',
+  'tv-line',
+  'twitch-fill',
+  'twitch-line',
+  'twitter-fill',
+  'twitter-line',
+  'typhoon-fill',
+  'typhoon-line',
+  'u-disk-fill',
+  'u-disk-line',
+  'ubuntu-fill',
+  'ubuntu-line',
+  'umbrella-fill',
+  'umbrella-line',
+  'underline',
+  'uninstall-fill',
+  'uninstall-line',
+  'unsplash-fill',
+  'unsplash-line',
+  'upload-2-fill',
+  'upload-2-line',
+  'upload-cloud-2-fill',
+  'upload-cloud-2-line',
+  'upload-cloud-fill',
+  'upload-cloud-line',
+  'upload-fill',
+  'upload-line',
+  'usb-fill',
+  'usb-line',
+  'user-2-fill',
+  'user-2-line',
+  'user-3-fill',
+  'user-3-line',
+  'user-4-fill',
+  'user-4-line',
+  'user-5-fill',
+  'user-5-line',
+  'user-6-fill',
+  'user-6-line',
+  'user-add-fill',
+  'user-add-line',
+  'user-fill',
+  'user-follow-fill',
+  'user-follow-line',
+  'user-heart-fill',
+  'user-heart-line',
+  'user-line',
+  'user-location-fill',
+  'user-location-line',
+  'user-received-2-fill',
+  'user-received-2-line',
+  'user-received-fill',
+  'user-received-line',
+  'user-search-fill',
+  'user-search-line',
+  'user-settings-fill',
+  'user-settings-line',
+  'user-shared-2-fill',
+  'user-shared-2-line',
+  'user-shared-fill',
+  'user-shared-line',
+  'user-smile-fill',
+  'user-smile-line',
+  'user-star-fill',
+  'user-star-line',
+  'user-unfollow-fill',
+  'user-unfollow-line',
+  'user-voice-fill',
+  'user-voice-line',
+  'video-add-fill',
+  'video-add-line',
+  'video-chat-fill',
+  'video-chat-line',
+  'video-download-fill',
+  'video-download-line',
+  'video-fill',
+  'video-line',
+  'video-upload-fill',
+  'video-upload-line',
+  'vidicon-2-fill',
+  'vidicon-2-line',
+  'vidicon-fill',
+  'vidicon-line',
+  'vimeo-fill',
+  'vimeo-line',
+  'vip-crown-2-fill',
+  'vip-crown-2-line',
+  'vip-crown-fill',
+  'vip-crown-line',
+  'vip-diamond-fill',
+  'vip-diamond-line',
+  'vip-fill',
+  'vip-line',
+  'virus-fill',
+  'virus-line',
+  'visa-fill',
+  'visa-line',
+  'voice-recognition-fill',
+  'voice-recognition-line',
+  'voiceprint-fill',
+  'voiceprint-line',
+  'volume-down-fill',
+  'volume-down-line',
+  'volume-mute-fill',
+  'volume-mute-line',
+  'volume-off-vibrate-fill',
+  'volume-off-vibrate-line',
+  'volume-up-fill',
+  'volume-up-line',
+  'volume-vibrate-fill',
+  'volume-vibrate-line',
+  'vuejs-fill',
+  'vuejs-line',
+  'walk-fill',
+  'walk-line',
+  'wallet-2-fill',
+  'wallet-2-line',
+  'wallet-3-fill',
+  'wallet-3-line',
+  'wallet-fill',
+  'wallet-line',
+  'water-flash-fill',
+  'water-flash-line',
+  'webcam-fill',
+  'webcam-line',
+  'wechat-2-fill',
+  'wechat-2-line',
+  'wechat-fill',
+  'wechat-line',
+  'wechat-pay-fill',
+  'wechat-pay-line',
+  'weibo-fill',
+  'weibo-line',
+  'whatsapp-fill',
+  'whatsapp-line',
+  'wheelchair-fill',
+  'wheelchair-line',
+  'wifi-fill',
+  'wifi-line',
+  'wifi-off-fill',
+  'wifi-off-line',
+  'window-2-fill',
+  'window-2-line',
+  'window-fill',
+  'window-line',
+  'windows-fill',
+  'windows-line',
+  'windy-fill',
+  'windy-line',
+  'wireless-charging-fill',
+  'wireless-charging-line',
+  'women-fill',
+  'women-line',
+  'wubi-input',
+  'xbox-fill',
+  'xbox-line',
+  'xing-fill',
+  'xing-line',
+  'youtube-fill',
+  'youtube-line',
+  'zcool-fill',
+  'zcool-line',
+  'zhihu-fill',
+  'zhihu-line',
+  'zoom-in-fill',
+  'zoom-in-line',
+  'zoom-out-fill',
+  'zoom-out-line',
+  'zzz-fill',
+  'zzz-line',
+]
+
+module.exports = [
+  {
+    url: '/remixIcon/getList',
+    type: 'get',
+    response(config) {
+      const { title, pageNo = 1, pageSize = 72 } = config.query
+      const mockList = List.filter(
+        (item) => !(title && item.indexOf(title) < 0)
+      )
+      const list = mockList.filter(
+        (item, index) =>
+          index < pageSize * pageNo && index >= pageSize * (pageNo - 1)
+      )
+      return {
+        code: 200,
+        msg: 'success',
+        data: { list, ...{ total: mockList.length } },
+      }
+    },
+  },
+]

+ 0 - 1
mock/index.js

@@ -6,7 +6,6 @@ const { mock } = require('mockjs')
 const { baseURL } = require('../src/config')
 const mockDir = path.join(process.cwd(), 'mock')
 const { handleMockArray } = require('./utils')
-const { log } = require('console')
 
 /**
  *

+ 1 - 0
package.json

@@ -13,6 +13,7 @@
     "template": "plop"
   },
   "dependencies": {
+    "@riophae/vue-treeselect": "^0.4.0",
     "axios": "^0.24.0",
     "core-js": "^3.19.3",
     "dayjs": "^1.10.7",

+ 39 - 3
src/api/menu.js

@@ -7,12 +7,48 @@ export default {
     return micro_request.postRequest(basePath, 'Menu', 'GetList', query)
   },
   getTree(query) {
-    return micro_request.postRequest(basePath, 'Menu', 'GetList', query)
+    return micro_request.postRequest(basePath, 'Menu', 'GetMenuTree', query)
+  },
+  doAdd(query) {
+    return micro_request.postRequest(basePath, 'Menu', 'Add', query)
   },
   doEdit(query) {
-    return micro_request.postRequest(basePath, 'Menu', 'GetList', query)
+    return micro_request.postRequest(basePath, 'Menu', 'UpdateById', query)
   },
   doDelete(query) {
-    return micro_request.postRequest(basePath, 'Menu', 'GetList', query)
+    return micro_request.postRequest(basePath, 'Menu', 'DeleteById', query)
   },
 }
+// import request from '@/utils/request'
+//
+// export default {
+//   // 获取列表
+//   getList(params) {
+//     return request({
+//       url: '/router/getList',
+//       method: 'get',
+//       params,
+//     })
+//   },
+//   getTree(params) {
+//     return request({
+//       url: '/menuManagement/getList',
+//       method: 'get',
+//       params,
+//     })
+//   },
+//   doEdit(data) {
+//     return request({
+//       url: '/menuManagement/doEdit',
+//       method: 'post',
+//       data,
+//     })
+//   },
+//   doDelete(data) {
+//     return request({
+//       url: '/menuManagement/doEdit',
+//       method: 'post',
+//       data,
+//     })
+//   },
+// }

+ 19 - 0
src/api/user.js

@@ -1,3 +1,22 @@
+import micro_request from '@/utils/micro_request'
+
+const basePath = process.env.VUE_APP_AdminPath
+export default {
+  // 获取列表
+  getList(query) {
+    return micro_request.postRequest(basePath, 'User', 'GetList', query)
+  },
+  doAdd(query) {
+    return micro_request.postRequest(basePath, 'User', 'Add', query)
+  },
+  doEdit(query) {
+    return micro_request.postRequest(basePath, 'User', 'UpdateById', query)
+  },
+  doDelete(query) {
+    return micro_request.postRequest(basePath, 'User', 'DeleteUserByIds', query)
+  },
+}
+
 import request from '@/utils/request'
 
 export async function login(data) {

+ 1 - 2
src/extra/VabIconSelector/index.vue

@@ -30,8 +30,7 @@
         :page-size="queryForm.pageSize"
         :total="total"
         @current-change="handleCurrentChange"
-        @size-change="handleSizeChange"
-      />
+        @size-change="handleSizeChange" />
     </el-col>
   </el-row>
 </template>

+ 5 - 0
src/main.js

@@ -5,6 +5,11 @@ import store from './store'
 import router from './router'
 import '@/vab'
 
+import { parseTime, translateDataToTree } from '@/utils'
+
+Vue.prototype.parseTime = parseTime
+Vue.prototype.translateDataToTree = translateDataToTree
+
 Vue.config.productionTip = false
 new Vue({
   el: '#app',

+ 3 - 4
src/store/modules/routes.js

@@ -3,7 +3,7 @@
  */
 import Vue from 'vue'
 import { asyncRoutes, constantRoutes, resetRouter } from '@/router'
-import { getList } from '@/api/router'
+import menuApi from '@/api/menu'
 import { convertRouter, filterRoutes } from '@/utils/routes'
 import { authentication, rolesControl } from '@/config'
 import { isArray } from '@/utils/validate'
@@ -64,9 +64,8 @@ const actions = {
     const control = mode === 'visit' ? false : rolesControl
     // 设置后端路由(不需要可以删除)
     if (authentication === 'all') {
-      const {
-        data: { list },
-      } = await getList()
+      const { data: data } = await menuApi.getTree()
+      let list = data
       if (!isArray(list))
         Vue.prototype.$baseMessage(
           '路由格式返回有误!',

+ 11 - 2
src/utils/index.js

@@ -8,6 +8,9 @@ export function parseTime(time, cFormat) {
   if (arguments.length === 0) {
     return null
   }
+  if (time === null || time === undefined || time === '') {
+    return null
+  }
   const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
   let date
   if (typeof time === 'object') {
@@ -114,10 +117,16 @@ export function paramObj(url) {
  */
 export function translateDataToTree(data) {
   const parent = data.filter(
-    (value) => value.parentId === 'undefined' || value.parentId === null
+    (value) =>
+      value.parentId === 'undefined' ||
+      value.parentId === null ||
+      value.parentId === 0
   )
   const children = data.filter(
-    (value) => value.parentId !== 'undefined' && value.parentId !== null
+    (value) =>
+      value.parentId !== 'undefined' &&
+      value.parentId !== null &&
+      value.parentId !== 0
   )
   const translator = (parent, children) => {
     parent.forEach((parent) => {

+ 1 - 2
src/vab/components/VabAvatar/index.vue

@@ -7,8 +7,7 @@
         <vab-icon
           class="vab-dropdown"
           :class="{ 'vab-dropdown-active': active }"
-          icon="arrow-down-s-line"
-        />
+          icon="arrow-down-s-line" />
       </div>
     </span>
     <template #dropdown>

+ 6 - 12
src/vab/components/VabColumnBar/index.vue

@@ -4,14 +4,12 @@
     :class="{
       'is-collapse': collapse,
       ['vab-column-bar-container-' + theme.columnStyle]: true,
-    }"
-  >
+    }">
     <vab-logo />
     <el-tabs
       v-model="extra.first"
       tab-position="left"
-      @tab-click="handleTabClick"
-    >
+      @tab-click="handleTabClick">
       <template v-for="(route, index) in handleRoutes">
         <el-tab-pane :key="index + route.name" :name="route.name">
           <template slot="label">
@@ -20,14 +18,12 @@
               :class="{
                 ['vab-column-grid-' + theme.columnStyle]: true,
               }"
-              :title="translateTitle(route.meta.title)"
-            >
+              :title="translateTitle(route.meta.title)">
               <div>
                 <vab-icon
                   v-if="route.meta.icon"
                   :icon="route.meta.icon"
-                  :is-custom-svg="route.meta.isCustomSvg"
-                />
+                  :is-custom-svg="route.meta.isCustomSvg" />
                 <span>
                   {{ translateTitle(route.meta.title) }}
                 </span>
@@ -43,8 +39,7 @@
       :default-active="activeMenu"
       :default-openeds="defaultOpeneds"
       mode="vertical"
-      :unique-opened="uniqueOpened"
-    >
+      :unique-opened="uniqueOpened">
       <el-divider>
         {{ translateTitle(handleGroupTitle) }}
       </el-divider>
@@ -52,8 +47,7 @@
         <vab-menu
           v-if="route.meta && !route.meta.hidden"
           :key="route.path"
-          :item="route"
-        />
+          :item="route" />
       </template>
     </el-menu>
   </el-scrollbar>

+ 3 - 6
src/vab/components/VabErrorLog/index.vue

@@ -2,8 +2,7 @@
   <div v-if="errorLogs.length > 0">
     <el-badge
       :value="errorLogs.length"
-      @click.native="dialogTableVisible = true"
-    >
+      @click.native="dialogTableVisible = true">
       <vab-icon icon="bug-line" />
     </el-badge>
 
@@ -11,8 +10,7 @@
       append-to-body
       title="admin-pro(vue-admin-beautiful pro 版本) 异常捕获(温馨提示:错误必须解决)"
       :visible.sync="dialogTableVisible"
-      width="70%"
-    >
+      width="70%">
       <el-table border :data="errorLogs">
         <el-table-column label="报错路由">
           <template #default="{ row }">
@@ -42,8 +40,7 @@
               v-for="(item, index) in searchList"
               :key="index"
               :href="item.url + row.err.message"
-              target="_blank"
-            >
+              target="_blank">
               <el-button type="primary">
                 {{ item.title }}
               </el-button>

+ 1 - 2
src/vab/components/VabFold/index.vue

@@ -2,8 +2,7 @@
   <vab-icon
     class="fold-unfold"
     :icon="collapse ? 'menu-unfold-line' : 'menu-fold-line'"
-    @click="toggleCollapse"
-  />
+    @click="toggleCollapse" />
 </template>
 
 <script>

+ 1 - 2
src/vab/components/VabFullScreen/index.vue

@@ -2,8 +2,7 @@
   <vab-icon
     v-if="theme.showFullScreen"
     :icon="isFullscreen ? 'fullscreen-exit-fill' : 'fullscreen-fill'"
-    @click="click"
-  />
+    @click="click" />
 </template>
 
 <script>

+ 2 - 4
src/vab/components/VabHeader/index.vue

@@ -14,15 +14,13 @@
               :default-active="activeMenu"
               menu-trigger="hover"
               mode="horizontal"
-              :text-color="variables['menu-color']"
-            >
+              :text-color="variables['menu-color']">
               <template v-for="(route, index) in handleRoutes">
                 <vab-menu
                   v-if="route.meta && !route.meta.hidden"
                   :key="index + route.name"
                   :item="route"
-                  :layout="layout"
-                />
+                  :layout="layout" />
               </template>
             </el-menu>
             <vab-error-log />

+ 2 - 4
src/vab/components/VabLogo/index.vue

@@ -3,8 +3,7 @@
     class="logo-container"
     :class="{
       ['logo-container-' + theme.layout]: true,
-    }"
-  >
+    }">
     <router-link to="/">
       <span class="logo">
         <!-- 使用自定义svg示例 -->
@@ -12,8 +11,7 @@
       </span>
       <span
         class="title"
-        :class="{ 'hidden-xs-only': theme.layout === 'horizontal' }"
-      >
+        :class="{ 'hidden-xs-only': theme.layout === 'horizontal' }">
         {{ title }}
       </span>
     </router-link>

+ 3 - 6
src/vab/components/VabMenu/components/VabMenuItem.vue

@@ -4,22 +4,19 @@
       v-if="itemOrMenu.meta && itemOrMenu.meta.icon"
       :icon="itemOrMenu.meta.icon"
       :is-custom-svg="itemOrMenu.meta.isCustomSvg"
-      :title="translateTitle(itemOrMenu.meta.title)"
-    />
+      :title="translateTitle(itemOrMenu.meta.title)" />
     <span :title="translateTitle(itemOrMenu.meta.title)">
       {{ translateTitle(itemOrMenu.meta.title) }}
     </span>
     <el-tag
       v-if="itemOrMenu.meta && itemOrMenu.meta.badge"
       effect="dark"
-      type="danger"
-    >
+      type="danger">
       {{ itemOrMenu.meta.badge }}
     </el-tag>
     <span
       v-if="itemOrMenu.meta && itemOrMenu.meta.dot"
-      class="vab-dot vab-dot-error"
-    >
+      class="vab-dot vab-dot-error">
       <span />
     </span>
   </el-menu-item>

+ 2 - 4
src/vab/components/VabMenu/components/VabSubmenu.vue

@@ -8,15 +8,13 @@
     v-else
     ref="subMenu"
     :index="itemOrMenu.path"
-    :popper-append-to-body="false"
-  >
+    :popper-append-to-body="false">
     <template slot="title">
       <vab-icon
         v-if="itemOrMenu.meta && itemOrMenu.meta.icon"
         :icon="itemOrMenu.meta.icon"
         :is-custom-svg="itemOrMenu.meta.isCustomSvg"
-        :title="translateTitle(itemOrMenu.meta.title)"
-      />
+        :title="translateTitle(itemOrMenu.meta.title)" />
       <span :title="translateTitle(itemOrMenu.meta.title)">
         {{ translateTitle(itemOrMenu.meta.title) }}
       </span>

+ 4 - 8
src/vab/components/VabMenu/index.vue

@@ -2,28 +2,24 @@
   <component
     :is="menuComponent"
     v-if="item.meta && !item.meta.hidden"
-    :item-or-menu="item"
-  >
+    :item-or-menu="item">
     <template v-if="item.children && item.children.length">
       <el-scrollbar
         v-if="
           (layout === 'horizontal' && item.children.length > 18) ||
           (layout !== 'horizontal' && collapse && item.children.length > 18)
         "
-        class="vab-menu-children-height"
-      >
+        class="vab-menu-children-height">
         <vab-menu
           v-for="route in item.children"
           :key="route.path"
-          :item="route"
-        />
+          :item="route" />
       </el-scrollbar>
       <template v-else>
         <vab-menu
           v-for="route in item.children"
           :key="route.path"
-          :item="route"
-        />
+          :item="route" />
       </template>
     </template>
   </component>

+ 2 - 4
src/vab/components/VabNav/index.vue

@@ -8,8 +8,7 @@
             v-if="layout === 'comprehensive'"
             v-model="extra.first"
             tab-position="top"
-            @tab-click="handleTabClick"
-          >
+            @tab-click="handleTabClick">
             <template v-for="(route, index) in handleRoutes">
               <el-tab-pane :key="index + route.name" :name="route.name">
                 <span slot="label">
@@ -17,8 +16,7 @@
                     v-if="route.meta.icon"
                     :icon="route.meta.icon"
                     :is-custom-svg="route.meta.isCustomSvg"
-                    style="min-width: 16px"
-                  />
+                    style="min-width: 16px" />
                   {{ translateTitle(route.meta.title) }}
                 </span>
               </el-tab-pane>

+ 1 - 2
src/vab/components/VabRefresh/index.vue

@@ -2,8 +2,7 @@
   <vab-icon
     v-if="theme.showRefresh"
     icon="refresh-line"
-    @click="refreshRoute"
-  />
+    @click="refreshRoute" />
 </template>
 
 <script>

+ 7 - 8
src/vab/components/VabSideBar/index.vue

@@ -1,15 +1,16 @@
 <template>
   <el-scrollbar
     class="vab-side-bar"
-    :class="{ 'is-collapse': collapse, 'side-bar-common': layout === 'common' }"
-  >
+    :class="{
+      'is-collapse': collapse,
+      'side-bar-common': layout === 'common',
+    }">
     <vab-logo
       v-if="
         layout === 'vertical' ||
         layout === 'comprehensive' ||
         layout === 'float'
-      "
-    />
+      " />
     <el-menu
       :active-text-color="variables['menu-color-active']"
       :background-color="variables['menu-background']"
@@ -20,14 +21,12 @@
       menu-trigger="click"
       mode="vertical"
       :text-color="variables['menu-color']"
-      :unique-opened="uniqueOpened"
-    >
+      :unique-opened="uniqueOpened">
       <template v-for="(route, index) in handleRoutes">
         <vab-menu
           v-if="route.meta && !route.meta.hidden"
           :key="index + route.name"
-          :item="route"
-        />
+          :item="route" />
       </template>
     </el-menu>
   </el-scrollbar>

+ 8 - 16
src/vab/components/VabTabs/index.vue

@@ -9,25 +9,21 @@
       }"
       type="card"
       @tab-click="handleTabClick"
-      @tab-remove="handleTabRemove"
-    >
+      @tab-remove="handleTabRemove">
       <el-tab-pane
         v-for="item in visitedRoutes"
         :key="item.path"
         :closable="!isNoClosable(item)"
-        :name="item.path"
-      >
+        :name="item.path">
         <span
           slot="label"
           style="display: inline-block"
-          @contextmenu.prevent="openMenu($event, item)"
-        >
+          @contextmenu.prevent="openMenu($event, item)">
           <template v-if="theme.showTabsIcon">
             <vab-icon
               v-if="item.meta && item.meta.icon"
               :icon="item.meta.icon"
-              :is-custom-svg="item.meta.isCustomSvg"
-            />
+              :is-custom-svg="item.meta.isCustomSvg" />
             <!--  如果没有图标那么取第二级的图标 -->
             <vab-icon v-else :icon="item.parentIcon" />
           </template>
@@ -75,21 +71,18 @@
     <ul
       v-if="visible"
       class="contextmenu el-dropdown-menu el-dropdown-menu--small"
-      :style="{ left: left + 'px', top: top + 'px' }"
-    >
+      :style="{ left: left + 'px', top: top + 'px' }">
       <li
         class="el-dropdown-menu__item"
         :class="{ 'is-disabled': visitedRoutes.length === 1 }"
-        @click="closeOthersTabs"
-      >
+        @click="closeOthersTabs">
         <vab-icon icon="close-line" />
         <span>{{ translateTitle('关闭其他') }}</span>
       </li>
       <li
         class="el-dropdown-menu__item"
         :class="{ 'is-disabled': !visitedRoutes.indexOf(hoverRoute) }"
-        @click="closeLeftTabs"
-      >
+        @click="closeLeftTabs">
         <vab-icon icon="arrow-left-line" />
         <span>{{ translateTitle('关闭左侧') }}</span>
       </li>
@@ -99,8 +92,7 @@
           'is-disabled':
             visitedRoutes.indexOf(hoverRoute) === visitedRoutes.length - 1,
         }"
-        @click="closeRightTabs"
-      >
+        @click="closeRightTabs">
         <vab-icon icon="arrow-right-line" />
         <span>{{ translateTitle('关闭右侧') }}</span>
       </li>

+ 3 - 6
src/vab/layouts/VabLayoutColumn/index.vue

@@ -5,22 +5,19 @@
     :class="{
       fixed: fixedHeader,
       'no-tabs-bar': !showTabs,
-    }"
-  >
+    }">
     <vab-column-bar />
     <div
       class="vab-main"
       :class="{
         ['vab-main-' + theme.columnStyle]: true,
         'is-collapse-main': collapse,
-      }"
-    >
+      }">
       <div
         class="vab-layout-header"
         :class="{
           'fixed-header': fixedHeader,
-        }"
-      >
+        }">
         <vab-nav />
         <vab-tabs v-show="showTabs" />
       </div>

+ 4 - 8
src/vab/layouts/VabLayoutCommon/index.vue

@@ -5,14 +5,12 @@
     :class="{
       fixed: fixedHeader,
       'no-tabs-bar': !showTabs,
-    }"
-  >
+    }">
     <div
       class="vab-layout-header"
       :class="{
         'fixed-header': fixedHeader,
-      }"
-    >
+      }">
       <vab-header layout="common" />
       <div>
         <vab-side-bar layout="common" />
@@ -21,8 +19,7 @@
           class="vab-main"
           :class="{
             'is-collapse-main': collapse,
-          }"
-        >
+          }">
           <vab-tabs layout="common" />
         </div>
       </div>
@@ -31,8 +28,7 @@
       class="vab-main main-padding"
       :class="{
         'is-collapse-main': collapse,
-      }"
-    >
+      }">
       <vab-app-main />
     </div>
   </div>

+ 3 - 6
src/vab/layouts/VabLayoutComprehensive/index.vue

@@ -5,21 +5,18 @@
     :class="{
       fixed: fixedHeader,
       'no-tabs-bar': !showTabs,
-    }"
-  >
+    }">
     <vab-side-bar layout="comprehensive" />
     <div
       class="vab-main"
       :class="{
         'is-collapse-main': collapse,
-      }"
-    >
+      }">
       <div
         class="vab-layout-header"
         :class="{
           'fixed-header': fixedHeader,
-        }"
-      >
+        }">
         <vab-nav layout="comprehensive" />
         <vab-tabs v-show="showTabs" />
       </div>

+ 2 - 4
src/vab/layouts/VabLayoutFloat/index.vue

@@ -5,16 +5,14 @@
     :class="{
       fixed: fixedHeader,
       'no-tabs-bar': !showTabs,
-    }"
-  >
+    }">
     <vab-side-bar layout="float" />
     <div class="vab-main">
       <div
         class="vab-layout-header"
         :class="{
           'fixed-header': fixedHeader,
-        }"
-      >
+        }">
         <vab-nav layout="float" />
         <vab-tabs v-show="showTabs" />
       </div>

+ 3 - 6
src/vab/layouts/VabLayoutHorizontal/index.vue

@@ -5,21 +5,18 @@
     :class="{
       fixed: fixedHeader,
       'no-tabs-bar': !showTabs,
-    }"
-  >
+    }">
     <div
       class="vab-layout-header"
       :class="{
         'fixed-header': fixedHeader,
-      }"
-    >
+      }">
       <vab-header />
       <div
         v-show="showTabs"
         :class="{
           'vab-tabs-horizontal': showTabs,
-        }"
-      >
+        }">
         <div class="vab-main">
           <vab-tabs />
         </div>

+ 4 - 8
src/vab/layouts/VabLayoutVertical/index.vue

@@ -5,26 +5,22 @@
     :class="{
       fixed: fixedHeader,
       'no-tabs-bar': !showTabs,
-    }"
-  >
+    }">
     <vab-side-bar />
     <div
       v-if="device === 'mobile' && !collapse"
       class="v-modal"
-      @click="handleFoldSideBar"
-    />
+      @click="handleFoldSideBar" />
     <div
       class="vab-main"
       :class="{
         'is-collapse-main': collapse,
-      }"
-    >
+      }">
       <div
         class="vab-layout-header"
         :class="{
           'fixed-header': fixedHeader,
-        }"
-      >
+        }">
         <vab-nav />
         <vab-tabs v-show="showTabs" />
       </div>

+ 1 - 2
src/vab/layouts/index.vue

@@ -5,8 +5,7 @@
       :collapse="collapse"
       :device="device"
       :fixed-header="theme.fixedHeader"
-      :show-tabs="theme.showTabs"
-    />
+      :show-tabs="theme.showTabs" />
     <el-backtop target="#app" />
   </div>
 </template>

+ 2 - 4
src/views/403.vue

@@ -6,12 +6,10 @@
           <div class="pic-error">
             <el-image
               class="pic-error-parent"
-              :src="require('@/assets/error_images/403.png')"
-            />
+              :src="require('@/assets/error_images/403.png')" />
             <el-image
               class="pic-error-child left"
-              :src="require('@/assets/error_images/cloud.png')"
-            />
+              :src="require('@/assets/error_images/cloud.png')" />
           </div>
         </el-col>
 

+ 2 - 4
src/views/404.vue

@@ -6,12 +6,10 @@
           <div class="pic-error">
             <el-image
               class="pic-error-parent"
-              :src="require('@/assets/error_images/404.png')"
-            />
+              :src="require('@/assets/error_images/404.png')" />
             <el-image
               class="pic-error-child left"
-              :src="require('@/assets/error_images/cloud.png')"
-            />
+              :src="require('@/assets/error_images/cloud.png')" />
           </div>
         </el-col>
 

+ 6 - 12
src/views/login/index.vue

@@ -10,8 +10,7 @@
           class="login-form"
           label-position="left"
           :model="form"
-          :rules="rules"
-        >
+          :rules="rules">
           <div class="title">hello !</div>
           <div class="title-tips">
             {{ translateTitle('欢迎来到') }}{{ title }}!
@@ -22,8 +21,7 @@
               v-focus
               :placeholder="translateTitle('请输入用户名')"
               tabindex="1"
-              type="text"
-            >
+              type="text">
               <template #prefix><vab-icon icon="user-line" /></template>
             </el-input>
           </el-form-item>
@@ -35,8 +33,7 @@
               :placeholder="translateTitle('请输入密码')"
               tabindex="2"
               :type="passwordType"
-              @keyup.enter.native="handleLogin"
-            >
+              @keyup.enter.native="handleLogin">
               <template #prefix>
                 <vab-icon icon="lock-line" />
               </template>
@@ -44,15 +41,13 @@
                 <vab-icon
                   class="show-password"
                   icon="eye-off-line"
-                  @click="handlePassword"
-                />
+                  @click="handlePassword" />
               </template>
               <template v-else #suffix>
                 <vab-icon
                   class="show-password"
                   icon="eye-line"
-                  @click="handlePassword"
-                />
+                  @click="handlePassword" />
               </template>
             </el-input>
           </el-form-item>
@@ -60,8 +55,7 @@
             class="login-btn"
             :loading="loading"
             type="primary"
-            @click="handleLogin"
-          >
+            @click="handleLogin">
             {{ translateTitle('登录') }}
           </el-button>
         </el-form>

+ 2 - 2
src/views/system/log.vue

@@ -32,9 +32,9 @@
     </vab-query-form>
 
     <el-table
-      :height="$baseTableHeight(1)"
       v-loading="listLoading"
-      :data="list">
+      :data="list"
+      :height="$baseTableHeight(1)">
       <el-table-column
         align="center"
         label="日志类型"

+ 306 - 74
src/views/system/menu/components/MenuEdit.vue

@@ -1,86 +1,285 @@
 <template>
+  <!-- 添加或修改菜单对话框 -->
   <el-dialog
+    append-to-body
     :title="title"
     :visible.sync="dialogFormVisible"
-    width="60%"
-    @close="close">
-    <el-form
-      ref="form"
-      :inline="true"
-      label-width="140px"
-      :model="form"
-      :rules="rules">
-      <el-form-item label="父级Id" prop="parentId">
-        <el-input v-model="form.parentId" />
-      </el-form-item>
-      <el-form-item label="name" prop="name">
-        <el-input v-model="form.name" />
-      </el-form-item>
-      <el-form-item label="路径" prop="path">
-        <el-input v-model="form.path" />
-      </el-form-item>
-      <el-form-item label="vue文件路径" prop="component">
-        <el-input v-model="form.component" />
-      </el-form-item>
-      <el-form-item label="重定向">
-        <el-input v-model="form.redirect" />
-      </el-form-item>
-      <el-form-item label="标题" prop="meta.title">
-        <el-input v-model="form.meta.title" />
-      </el-form-item>
-      <el-form-item label="图标">
-        <el-popover
-          popper-class="icon-selector-popper"
-          trigger="hover"
-          width="292">
-          <template #reference>
-            <el-input v-model="form.meta.icon" />
-          </template>
-          <vab-icon-selector @handle-icon="handleIcon" />
-        </el-popover>
-      </el-form-item>
-      <el-form-item label="badge">
-        <el-input v-model="form.meta.badge" />
-      </el-form-item>
-      <el-form-item label="dot">
-        <el-switch v-model="form.meta.dot" />
-      </el-form-item>
-      <el-form-item label="隐藏">
-        <el-switch v-model="form.meta.hidden" />
-      </el-form-item>
-      <el-form-item label="始终显示当前节点">
-        <el-switch v-model="form.meta.levelHidden" />
-      </el-form-item>
-      <el-form-item label="自定义svg图标">
-        <el-switch v-model="form.meta.isCustomSvg" />
-      </el-form-item>
-      <el-form-item label="固定">
-        <el-switch v-model="form.meta.noClosable" />
-      </el-form-item>
-      <el-form-item label="无缓存">
-        <el-switch v-model="form.meta.noKeepAlive" />
-      </el-form-item>
-      <el-form-item label="不显示当前标签页">
-        <el-switch v-model="form.meta.tabHidden" />
-      </el-form-item>
+    width="50%"
+    @close="close"
+    @open="open">
+    <el-form ref="form" label-width="100px" :model="form" :rules="rules">
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="上级菜单" prop="parentId">
+            <treeselect
+              v-model="form.parentId"
+              :normalizer="normalizer"
+              :options="menuOptions"
+              placeholder="选择上级菜单"
+              :show-count="true" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <el-form-item label="菜单类型" prop="menuType">
+            <el-radio-group v-model="form.menuType">
+              <el-radio label="M">目录</el-radio>
+              <el-radio label="C">菜单</el-radio>
+              <el-radio label="F">按钮</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col v-if="form.menuType != 'F'" :span="24">
+          <el-form-item label="菜单图标" prop="icon">
+            <el-popover
+              popper-class="icon-selector-popper"
+              trigger="hover"
+              width="292">
+              <template #reference>
+                <el-input v-model="form.icon" />
+              </template>
+              <vab-icon-selector @handle-icon="handleIcon" />
+            </el-popover>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="菜单名称" prop="menuName">
+            <el-input v-model="form.menuName" placeholder="请输入菜单名称" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="显示排序" prop="sort">
+            <el-input-number
+              v-model="form.sort"
+              controls-position="right"
+              :min="0" />
+          </el-form-item>
+        </el-col>
+        <el-col v-if="form.menuType != 'F'" :span="12">
+          <el-form-item prop="isFrame">
+            <span slot="label">
+              <el-tooltip
+                content="选择是外链则路由地址需要以`http(s)://`开头"
+                placement="top">
+                <i class="el-icon-question"></i>
+              </el-tooltip>
+              是否外链
+            </span>
+            <el-radio-group v-model="form.isFrame">
+              <el-radio :label="1">是</el-radio>
+              <el-radio :label="0">否</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col v-if="form.menuType != 'F'" :span="12">
+          <el-form-item prop="path">
+            <span slot="label">
+              <el-tooltip
+                content="访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头"
+                placement="top">
+                <i class="el-icon-question"></i>
+              </el-tooltip>
+              路由地址
+            </span>
+            <el-input v-model="form.path" placeholder="请输入路由地址" />
+          </el-form-item>
+        </el-col>
+        <el-col v-if="form.menuType == 'C'" :span="12">
+          <el-form-item prop="component">
+            <span slot="label">
+              <el-tooltip
+                content="访问的组件路径,如:`system/user/index`,默认在`views`目录下"
+                placement="top">
+                <i class="el-icon-question"></i>
+              </el-tooltip>
+              组件路径
+            </span>
+            <el-input v-model="form.component" placeholder="请输入组件路径" />
+          </el-form-item>
+        </el-col>
+        <el-col v-if="form.menuType != 'M'" :span="12">
+          <el-form-item prop="perms">
+            <el-input
+              v-model="form.perms"
+              maxlength="100"
+              placeholder="请输入权限标识" />
+            <span slot="label">
+              <el-tooltip
+                content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasPermi('system:user:list')`)"
+                placement="top">
+                <i class="el-icon-question"></i>
+              </el-tooltip>
+              权限字符
+            </span>
+          </el-form-item>
+        </el-col>
+        <el-col v-if="form.menuType == 'C'" :span="12">
+          <el-form-item prop="query">
+            <el-input
+              v-model="form.query"
+              maxlength="255"
+              placeholder="请输入路由参数" />
+            <span slot="label">
+              <el-tooltip
+                content='访问路由的默认传递参数,如:`{"id": 1, "name": "ry"}`'
+                placement="top">
+                <i class="el-icon-question"></i>
+              </el-tooltip>
+              路由参数
+            </span>
+          </el-form-item>
+        </el-col>
+        <el-col v-if="form.menuType == 'C'" :span="12">
+          <el-form-item prop="isCache">
+            <span slot="label">
+              <el-tooltip
+                content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致"
+                placement="top">
+                <i class="el-icon-question"></i>
+              </el-tooltip>
+              是否缓存
+            </span>
+            <el-radio-group v-model="form.isCache">
+              <el-radio :label="1">缓存</el-radio>
+              <el-radio :label="0">不缓存</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col v-if="form.menuType != 'F'" :span="12">
+          <el-form-item prop="visible">
+            <span slot="label">
+              <el-tooltip
+                content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问"
+                placement="top">
+                <i class="el-icon-question"></i>
+              </el-tooltip>
+              显示状态
+            </span>
+            <el-radio-group v-model="form.visible">
+              <el-radio label="10">显示</el-radio>
+              <el-radio label="20">隐藏</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+        <el-col v-if="form.menuType != 'F'" :span="12">
+          <el-form-item prop="status">
+            <span slot="label">
+              <el-tooltip
+                content="选择停用则路由将不会出现在侧边栏,也不能被访问"
+                placement="top">
+                <i class="el-icon-question"></i>
+              </el-tooltip>
+              菜单状态
+            </span>
+            <el-radio-group v-model="form.status">
+              <el-radio label="10">正常</el-radio>
+              <el-radio label="20">停用</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
     </el-form>
-    <template #footer>
-      <el-button @click="close">取 消</el-button>
+    <div slot="footer" class="dialog-footer">
       <el-button type="primary" @click="save">确 定</el-button>
-    </template>
+      <el-button @click="close">取 消</el-button>
+    </div>
   </el-dialog>
+  <!--  <el-dialog-->
+  <!--    :title="title"-->
+  <!--    :visible.sync="dialogFormVisible"-->
+  <!--    width="60%"-->
+  <!--    @close="close">-->
+  <!--    <el-form-->
+  <!--      ref="form"-->
+  <!--      :inline="true"-->
+  <!--      label-width="140px"-->
+  <!--      :model="form"-->
+  <!--      :rules="rules">-->
+  <!--      <el-form-item label="父级Id" prop="parentId">-->
+  <!--        <el-input v-model="form.parentId" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="name" prop="name">-->
+  <!--        <el-input v-model="form.name" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="路径" prop="path">-->
+  <!--        <el-input v-model="form.path" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="vue文件路径" prop="component">-->
+  <!--        <el-input v-model="form.component" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="重定向">-->
+  <!--        <el-input v-model="form.redirect" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="标题" prop="meta.title">-->
+  <!--        <el-input v-model="form.meta.title" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="图标">-->
+  <!--        <el-popover-->
+  <!--          popper-class="icon-selector-popper"-->
+  <!--          trigger="hover"-->
+  <!--          width="292">-->
+  <!--          <template #reference>-->
+  <!--            <el-input v-model="form.meta.icon" />-->
+  <!--          </template>-->
+  <!--          <vab-icon-selector @handle-icon="handleIcon" />-->
+  <!--        </el-popover>-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="badge">-->
+  <!--        <el-input v-model="form.meta.badge" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="dot">-->
+  <!--        <el-switch v-model="form.meta.dot" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="隐藏">-->
+  <!--        <el-switch v-model="form.meta.hidden" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="始终显示当前节点">-->
+  <!--        <el-switch v-model="form.meta.levelHidden" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="自定义svg图标">-->
+  <!--        <el-switch v-model="form.meta.isCustomSvg" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="固定">-->
+  <!--        <el-switch v-model="form.meta.noClosable" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="无缓存">-->
+  <!--        <el-switch v-model="form.meta.noKeepAlive" />-->
+  <!--      </el-form-item>-->
+  <!--      <el-form-item label="不显示当前标签页">-->
+  <!--        <el-switch v-model="form.meta.tabHidden" />-->
+  <!--      </el-form-item>-->
+  <!--    </el-form>-->
+  <!--    <template #footer>-->
+  <!--      <el-button @click="close">取 消</el-button>-->
+  <!--      <el-button type="primary" @click="save">确 定</el-button>-->
+  <!--    </template>-->
+  <!--  </el-dialog>-->
 </template>
 
 <script>
-  import VabIconSelector from '@/extra/VabIconSelector'
   import menuApi from '@/api/menu'
+  import VabIconSelector from '@/extra/VabIconSelector'
+  import Treeselect from '@riophae/vue-treeselect'
+  import '@riophae/vue-treeselect/dist/vue-treeselect.css'
 
   export default {
     name: 'MenuEdit',
-    components: { VabIconSelector },
+    components: { Treeselect, VabIconSelector },
     data() {
       return {
         form: {
+          id: undefined,
+          parentId: 0,
+          menuName: undefined,
+          icon: undefined,
+          menuType: 'M',
+          sort: undefined,
+          isFrame: 0,
+          path: '',
+          component: '',
+          perms: '',
+          isCache: 0,
+          visible: '10',
+          status: '10',
           meta: {
             title: '',
             icon: '',
@@ -98,17 +297,23 @@
           parentId: [
             { required: true, trigger: 'blur', message: '请输入父级id' },
           ],
-          name: [{ required: true, trigger: 'blur', message: '请输入name' }],
-          path: [{ required: true, trigger: 'blur', message: '请输入path' }],
-          component: [
-            { required: true, trigger: 'blur', message: '请输入component' },
+          menuName: [
+            { required: true, trigger: 'blur', message: '请输入菜单名称' },
+          ],
+          path: [
+            { required: true, trigger: 'blur', message: '请输入路由地址' },
           ],
-          'meta.title': [
-            { required: true, trigger: 'blur', message: '请输入标题' },
+          component: [
+            { required: true, trigger: 'blur', message: '请输入组件路径' },
           ],
+          // 'meta.title': [
+          //   { required: true, trigger: 'blur', message: '请输入标题' },
+          // ],
         },
         title: '',
         dialogFormVisible: false,
+        // 菜单树选项
+        menuOptions: [],
       }
     },
     methods: {
@@ -124,6 +329,9 @@
         }
         this.dialogFormVisible = true
       },
+      open() {
+        this.getTreeselect()
+      },
       close() {
         this.$refs['form'].resetFields()
         this.form = this.$options.data().form
@@ -132,13 +340,37 @@
       save() {
         this.$refs['form'].validate(async (valid) => {
           if (valid) {
-            const { msg } = await menuApi.doEdit(this.form)
-            this.$baseMessage(msg, 'success', 'vab-hey-message-success')
+            let res
+            if (this.form.id) {
+              res = await menuApi.doEdit(this.form)
+            } else {
+              res = await menuApi.doAdd(this.form)
+            }
+            this.$baseMessage(res.msg, 'success', 'vab-hey-message-success')
             this.$emit('fetch-data')
             this.close()
           }
         })
       },
+      /** 转换菜单数据结构 */
+      normalizer(node) {
+        if (node.children && !node.children.length) {
+          delete node.children
+        }
+        return {
+          id: node.id,
+          label: node.menuName,
+          children: node.children,
+        }
+      },
+      /** 查询菜单下拉树结构 */
+      async getTreeselect() {
+        const { data: data } = await menuApi.getList()
+        this.menuOptions = []
+        const menu = { id: 0, menuName: '主类目', children: [] }
+        menu.children = this.translateDataToTree(data)
+        this.menuOptions.push(menu)
+      },
     },
   }
 </script>

+ 69 - 59
src/views/system/menu/index.vue

@@ -29,71 +29,85 @@
             :data="list"
             default-expand-all
             :height="$noPagingTableHeight(1)"
-            row-key="path"
+            row-key="id"
             :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
             <el-table-column
-              label="标题"
-              prop="meta.title"
+              label="菜单名称"
+              prop="menuName"
               show-overflow-tooltip />
-            <el-table-column label="name" prop="name" show-overflow-tooltip />
             <el-table-column label="路径" prop="path" show-overflow-tooltip />
-            <el-table-column label="是否隐藏" show-overflow-tooltip>
-              <template #default="{ row }">
-                {{ row.meta.hidden ? '是' : '否' }}
-              </template>
-            </el-table-column>
             <el-table-column
-              label="是否隐藏当前节点"
-              show-overflow-tooltip
-              width="100">
-              <template #default="{ row }">
-                {{ row.meta.levelHidden ? '是' : '否' }}
-              </template>
-            </el-table-column>
-            <el-table-column
-              label="vue文件路径"
+              label="组件路径"
               prop="component"
               show-overflow-tooltip />
-            <el-table-column label="重定向" show-overflow-tooltip>
-              <template #default="{ row }">
-                {{ row.redirect ? row.redirect : '无' }}
-              </template>
-            </el-table-column>
+            <el-table-column
+              label="权限标识"
+              prop="perms"
+              show-overflow-tooltip />
+            <el-table-column label="排序" prop="sort" width="60" />
             <el-table-column label="图标" show-overflow-tooltip>
               <template #default="{ row }">
-                <vab-icon
-                  v-if="row.meta && row.meta.icon"
-                  :icon="row.meta.icon" />
+                <vab-icon v-if="row.icon" :icon="row.icon" />
               </template>
             </el-table-column>
-            <el-table-column label="是否固定" show-overflow-tooltip>
+            <el-table-column label="菜单状态" prop="status" width="80">
               <template #default="{ row }">
-                {{ row.meta && row.meta.noClosable ? '是' : '否' }}
+                {{ row.status === '10' ? '正常' : '停用' }}
               </template>
             </el-table-column>
-            <el-table-column
-              label="是否无缓存"
-              show-overflow-tooltip
-              width="120">
+            <el-table-column label="显示状态" prop="visible" width="80">
               <template #default="{ row }">
-                {{ row.meta && row.meta.noKeepAlive ? '是' : '否' }}
+                {{ row.status === '10' ? '显示' : '隐藏' }}
               </template>
             </el-table-column>
-            <el-table-column label="badge" show-overflow-tooltip>
+            <el-table-column label="缓存" show-overflow-tooltip width="60">
               <template #default="{ row }">
-                <el-tag
-                  v-if="row.meta && row.meta.badge"
-                  effect="dark"
-                  type="danger">
-                  {{ row.meta.badge }}
-                </el-tag>
+                {{ row.isCache ? '是' : '否' }}
               </template>
             </el-table-column>
-            <el-table-column label="dot" show-overflow-tooltip>
-              <template #default="{ row }">
-                {{ row.meta && row.meta.dot ? '是' : '否' }}
+            <el-table-column align="center" label="创建时间" prop="createdTime">
+              <template #default="scope">
+                <span>{{ parseTime(scope.row.createdTime) }}</span>
               </template>
             </el-table-column>
+            <!--            <el-table-column label="重定向" show-overflow-tooltip>-->
+            <!--              <template #default="{ row }">-->
+            <!--                {{ row.redirect ? row.redirect : '无' }}-->
+            <!--              </template>-->
+            <!--            </el-table-column>-->
+            <!--            <el-table-column label="是否隐藏" show-overflow-tooltip>-->
+            <!--              <template #default="{ row }">-->
+            <!--                {{ row.meta.hidden ? '是' : '否' }}-->
+            <!--              </template>-->
+            <!--            </el-table-column>-->
+            <!--            <el-table-column-->
+            <!--              label="是否隐藏当前节点"-->
+            <!--              show-overflow-tooltip-->
+            <!--              width="100">-->
+            <!--              <template #default="{ row }">-->
+            <!--                {{ row.meta.levelHidden ? '是' : '否' }}-->
+            <!--              </template>-->
+            <!--            </el-table-column>-->
+            <!--            <el-table-column label="是否固定" show-overflow-tooltip>-->
+            <!--              <template #default="{ row }">-->
+            <!--                {{ row.meta && row.meta.noClosable ? '是' : '否' }}-->
+            <!--              </template>-->
+            <!--            </el-table-column>-->
+            <!--            <el-table-column label="badge" show-overflow-tooltip>-->
+            <!--              <template #default="{ row }">-->
+            <!--                <el-tag-->
+            <!--                  v-if="row.meta && row.meta.badge"-->
+            <!--                  effect="dark"-->
+            <!--                  type="danger">-->
+            <!--                  {{ row.meta.badge }}-->
+            <!--                </el-tag>-->
+            <!--              </template>-->
+            <!--            </el-table-column>-->
+            <!--            <el-table-column label="dot" show-overflow-tooltip>-->
+            <!--              <template #default="{ row }">-->
+            <!--                {{ row.meta && row.meta.dot ? '是' : '否' }}-->
+            <!--              </template>-->
+            <!--            </el-table-column>-->
             <el-table-column
               fixed="right"
               label="操作"
@@ -142,35 +156,31 @@
       }
     },
     async created() {
-      const {
-        data: { list },
-      } = await menuApi.getTree()
-      this.data = list
+      // const {
+      //   data: { list },
+      // } = await menuApi.getTree()
+      // this.data = list
       await this.fetchData()
     },
     methods: {
       handleEdit(row) {
-        if (row && row.path) {
+        if (row && row.id) {
           this.$refs['edit'].showEdit(row)
         } else {
           this.$refs['edit'].showEdit()
         }
       },
       handleDelete(row) {
-        if (row.path) {
-          this.$baseConfirm('你确定要删除当前项吗', null, async () => {
-            const { msg } = await menuApi.doDelete({ paths: row.path })
-            this.$baseMessage(msg, 'success', 'vab-hey-message-success')
-            await this.fetchData()
-          })
-        }
+        this.$baseConfirm('你确定要删除当前项吗', null, async () => {
+          const { msg } = await menuApi.doDelete({ id: row.id })
+          this.$baseMessage(msg, 'success', 'vab-hey-message-success')
+          await this.fetchData()
+        })
       },
       async fetchData(role) {
         this.listLoading = true
-        const {
-          data: { list },
-        } = await menuApi.getList({ role })
-        this.list = list
+        const { data: data } = await menuApi.getList({ role })
+        this.list = this.translateDataToTree(data)
         this.listLoading = false
       },
       handleNodeClick({ role }) {

+ 17 - 6
src/views/system/user/components/UserEdit.vue

@@ -5,12 +5,18 @@
     width="500px"
     @close="close">
     <el-form ref="form" label-width="80px" :model="form" :rules="rules">
-      <el-form-item label="用户名" prop="username">
-        <el-input v-model.trim="form.username" />
+      <el-form-item label="用户名" prop="userName">
+        <el-input v-model.trim="form.userName" />
       </el-form-item>
       <el-form-item label="密码" prop="password">
         <el-input v-model.trim="form.password" type="password" />
       </el-form-item>
+      <el-form-item label="用户昵称" prop="nickName">
+        <el-input v-model.trim="form.nickName" />
+      </el-form-item>
+      <el-form-item label="手机号" prop="phone">
+        <el-input v-model.trim="form.phone" />
+      </el-form-item>
       <el-form-item label="邮箱" prop="email">
         <el-input v-model.trim="form.email" />
       </el-form-item>
@@ -29,7 +35,7 @@
 </template>
 
 <script>
-  import { doEdit } from '@/api/user'
+  import userApi from '@/api/user'
 
   export default {
     name: 'UserEdit',
@@ -39,7 +45,7 @@
           roles: [],
         },
         rules: {
-          username: [
+          userName: [
             { required: true, trigger: 'blur', message: '请输入用户名' },
           ],
           password: [
@@ -70,8 +76,13 @@
       save() {
         this.$refs['form'].validate(async (valid) => {
           if (valid) {
-            const { msg } = await doEdit(this.form)
-            this.$baseMessage(msg, 'success', 'vab-hey-message-success')
+            if (this.form.id) {
+              const { msg } = await userApi.doEdit(this.form)
+              this.$baseMessage(msg, 'success', 'vab-hey-message-success')
+            } else {
+              const { msg } = await userApi.doAdd(this.form)
+              this.$baseMessage(msg, 'success', 'vab-hey-message-success')
+            }
             this.$emit('fetch-data')
             this.close()
           }

+ 29 - 15
src/views/system/user/index.vue

@@ -19,7 +19,7 @@
         <el-form :inline="true" :model="queryForm" @submit.native.prevent>
           <el-form-item>
             <el-input
-              v-model.trim="queryForm.username"
+              v-model.trim="queryForm.userName"
               clearable
               placeholder="请输入用户名" />
           </el-form-item>
@@ -39,11 +39,11 @@
       :height="height"
       @selection-change="setSelectRows">
       <el-table-column align="center" show-overflow-tooltip type="selection" />
-      <el-table-column align="center" label="序号" width="55">
+      <!--      <el-table-column align="center" label="序号" width="55">
         <template #default="{ $index }">
           {{ $index + 1 }}
         </template>
-      </el-table-column>
+      </el-table-column>-->
       <el-table-column
         align="center"
         label="id"
@@ -52,14 +52,28 @@
       <el-table-column
         align="center"
         label="用户名"
-        prop="username"
+        prop="userName"
+        show-overflow-tooltip />
+      <el-table-column
+        align="center"
+        label="昵称"
+        prop="nickName"
+        show-overflow-tooltip />
+      <el-table-column
+        align="center"
+        label="手机号"
+        prop="phone"
         show-overflow-tooltip />
       <el-table-column
         align="center"
         label="邮箱"
         prop="email"
         show-overflow-tooltip />
-
+      <el-table-column
+        align="center"
+        label="部门"
+        prop="email"
+        show-overflow-tooltip />
       <el-table-column align="center" label="角色" show-overflow-tooltip>
         <template #default="{ row }">
           <el-tag v-for="(item, index) in row.roles" :key="index">
@@ -68,11 +82,11 @@
         </template>
       </el-table-column>
 
-      <el-table-column
-        align="center"
-        label="修改时间"
-        prop="datatime"
-        show-overflow-tooltip />
+      <el-table-column align="center" label="创建时间" prop="createdTime">
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.createdTime) }}</span>
+        </template>
+      </el-table-column>
       <el-table-column
         align="center"
         label="操作"
@@ -102,7 +116,7 @@
 </template>
 
 <script>
-  import { doDelete, getList } from '@/api/user'
+  import userApi from '@/api/user'
   import Edit from './components/UserEdit'
 
   export default {
@@ -118,7 +132,7 @@
         queryForm: {
           pageNo: 1,
           pageSize: 10,
-          username: '',
+          userName: '',
         },
       }
     },
@@ -144,7 +158,7 @@
       handleDelete(row) {
         if (row.id) {
           this.$baseConfirm('你确定要删除当前项吗', null, async () => {
-            const { msg } = await doDelete({ ids: row.id })
+            const { msg } = await userApi.doDelete({ ids: [row.id] })
             this.$baseMessage(msg, 'success', 'vab-hey-message-success')
             await this.fetchData()
           })
@@ -152,7 +166,7 @@
           if (this.selectRows.length > 0) {
             const ids = this.selectRows.map((item) => item.id).join()
             this.$baseConfirm('你确定要删除选中项吗', null, async () => {
-              const { msg } = await doDelete({ ids })
+              const { msg } = await userApi.doDelete({ ids })
               this.$baseMessage(msg, 'success', 'vab-hey-message-success')
               await this.fetchData()
             })
@@ -177,7 +191,7 @@
         this.listLoading = true
         const {
           data: { list, total },
-        } = await getList(this.queryForm)
+        } = await userApi.getList(this.queryForm)
         this.list = list
         this.total = total
         this.listLoading = false

+ 7 - 7
src/views/test/index.vue

@@ -35,8 +35,8 @@
     <el-table
       v-loading="listLoading"
       border
-      default-expand-all
       :data="list"
+      default-expand-all
       :height="height"
       row-key="id"
       :tree-props="{ children: 'children' }"
@@ -82,6 +82,9 @@
   import { getList } from '@/api/test'
   import Edit from './components/Edit'
   export default {
+    components: {
+      Edit,
+    },
     data() {
       return {
         list: [],
@@ -96,17 +99,14 @@
         },
       }
     },
-    components: {
-      Edit,
-    },
-    mounted() {
-      this.fetchData()
-    },
     computed: {
       height() {
         return this.$baseTableHeight(1)
       },
     },
+    mounted() {
+      this.fetchData()
+    },
     methods: {
       setSelectRows(val) {
         this.selectRows = val