Browse Source

refactor ts

LiuHao 1 year ago
parent
commit
251d2411f2
100 changed files with 3979 additions and 2324 deletions
  1. 1 0
      .env.development
  2. 3 1
      .env.production
  3. 17 0
      .eslintignore
  4. 281 0
      .eslintrc-auto-import.json
  5. 41 0
      .eslintrc.js
  6. 9 0
      .prettierignore
  7. 46 0
      .prettierrc.cjs
  8. 63 9
      README.md
  9. 24 0
      Vite/plugins/auto-import.ts
  10. 17 0
      Vite/plugins/components.ts
  11. 8 0
      Vite/plugins/icons.ts
  12. 18 0
      Vite/plugins/index.ts
  13. 9 0
      Vite/plugins/svg-icon.ts
  14. 13 0
      Vite/plugins/unocss.ts
  15. 22 0
      commitlint.config.js
  16. 0 19
      html/ie.html
  17. 215 213
      index.html
  18. 78 41
      package.json
  19. BIN
      public/favicon.ico
  20. 2 2
      src/App.vue
  21. 48 0
      src/animate.ts
  22. 0 54
      src/api/demo/demo.js
  23. 55 0
      src/api/demo/demo.ts
  24. 0 44
      src/api/demo/tree.js
  25. 46 0
      src/api/demo/tree.ts
  26. 55 0
      src/api/demo/types.ts
  27. 0 83
      src/api/login.js
  28. 81 0
      src/api/login.ts
  29. 0 9
      src/api/menu.js
  30. 11 0
      src/api/menu.ts
  31. 0 57
      src/api/monitor/cache.js
  32. 59 0
      src/api/monitor/cache/index.ts
  33. 7 0
      src/api/monitor/cache/types.ts
  34. 36 0
      src/api/monitor/loginInfo/index.ts
  35. 20 0
      src/api/monitor/loginInfo/types.ts
  36. 0 34
      src/api/monitor/logininfor.js
  37. 0 18
      src/api/monitor/online.js
  38. 20 0
      src/api/monitor/online/index.ts
  39. 15 0
      src/api/monitor/online/types.ts
  40. 0 26
      src/api/monitor/operlog.js
  41. 28 0
      src/api/monitor/operlog/index.ts
  42. 52 0
      src/api/monitor/operlog/types.ts
  43. 0 72
      src/api/system/config.js
  44. 74 0
      src/api/system/config/index.ts
  45. 23 0
      src/api/system/config/types.ts
  46. 0 52
      src/api/system/dept.js
  47. 62 0
      src/api/system/dept/index.ts
  48. 45 0
      src/api/system/dept/types.ts
  49. 0 52
      src/api/system/dict/data.js
  50. 53 0
      src/api/system/dict/data/index.ts
  51. 29 0
      src/api/system/dict/data/types.ts
  52. 0 60
      src/api/system/dict/type.js
  53. 62 0
      src/api/system/dict/type/index.ts
  54. 21 0
      src/api/system/dict/type/types.ts
  55. 0 68
      src/api/system/menu.js
  56. 70 0
      src/api/system/menu/index.ts
  57. 69 0
      src/api/system/menu/types.ts
  58. 0 44
      src/api/system/notice.js
  59. 45 0
      src/api/system/notice/index.ts
  60. 26 0
      src/api/system/notice/types.ts
  61. 0 27
      src/api/system/oss.js
  62. 28 0
      src/api/system/oss/index.ts
  63. 22 0
      src/api/system/oss/types.ts
  64. 0 58
      src/api/system/ossConfig.js
  65. 60 0
      src/api/system/ossConfig/index.ts
  66. 38 0
      src/api/system/ossConfig/types.ts
  67. 0 44
      src/api/system/post.js
  68. 46 0
      src/api/system/post/index.ts
  69. 23 0
      src/api/system/post/types.ts
  70. 0 119
      src/api/system/role.js
  71. 144 0
      src/api/system/role/index.ts
  72. 52 0
      src/api/system/role/types.ts
  73. 0 88
      src/api/system/tenant.js
  74. 89 0
      src/api/system/tenant/index.ts
  75. 46 0
      src/api/system/tenant/types.ts
  76. 0 58
      src/api/system/tenantPackage.js
  77. 59 0
      src/api/system/tenantPackage/index.ts
  78. 22 0
      src/api/system/tenantPackage/types.ts
  79. 0 135
      src/api/system/user.js
  80. 180 0
      src/api/system/user/index.ts
  81. 84 0
      src/api/system/user/types.ts
  82. 0 85
      src/api/tool/gen.js
  83. 87 0
      src/api/tool/gen/index.ts
  84. 178 0
      src/api/tool/gen/types.ts
  85. 54 0
      src/api/types.ts
  86. BIN
      src/assets/images/login-background.jpg
  87. BIN
      src/assets/images/profile.jpg
  88. BIN
      src/assets/logo/logo.png
  89. 66 66
      src/assets/styles/btn.scss
  90. 55 50
      src/assets/styles/element-ui.scss
  91. 104 90
      src/assets/styles/index.scss
  92. 46 52
      src/assets/styles/mixin.scss
  93. 52 39
      src/assets/styles/ruoyi.scss
  94. 230 232
      src/assets/styles/sidebar.scss
  95. 13 13
      src/assets/styles/transition.scss
  96. 26 26
      src/assets/styles/variables.module.scss
  97. 27 29
      src/components/Breadcrumb/index.vue
  98. 34 31
      src/components/DictTag/index.vue
  99. 53 51
      src/components/Editor/index.vue
  100. 82 73
      src/components/FileUpload/index.vue

+ 1 - 0
.env.development

@@ -15,3 +15,4 @@ VITE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/applications'
 
 # xxl-job 控制台地址
 VITE_APP_XXL_JOB_ADMIN = 'http://localhost:9100/xxl-job-admin'
+VITE_APP_PORT = 3000

+ 3 - 1
.env.production

@@ -17,4 +17,6 @@ VITE_APP_XXL_JOB_ADMIN = '/xxl-job-admin'
 VITE_APP_BASE_API = '/prod-api'
 
 # 是否在打包时开启压缩,支持 gzip 和 brotli
-VITE_BUILD_COMPRESS = gzip
+VITE_BUILD_COMPRESS = gzip
+
+VITE_APP_PORT = 3000

+ 17 - 0
.eslintignore

@@ -0,0 +1,17 @@
+*.sh
+node_modules
+*.md
+*.woff
+*.ttf
+.vscode
+.idea
+dist
+/public
+/docs
+.husky
+.local
+/bin
+.eslintrc.js
+prettier.config.js
+src/assets
+tailwind.config.js

+ 281 - 0
.eslintrc-auto-import.json

@@ -0,0 +1,281 @@
+{
+	"globals": {
+		"useRouter": true,
+		"useRoute": true,
+		"EffectScope": true,
+		"ElTable": true,
+		"ElSelect": true,
+		"ElUpload": true,
+		"ElForm": true,
+		"ElTree": true,
+		"ElMessage": true,
+		"ElMessageBox": true,
+		"asyncComputed": true,
+		"autoResetRef": true,
+		"computed": true,
+		"computedAsync": true,
+		"computedEager": true,
+		"computedInject": true,
+		"computedWithControl": true,
+		"controlledComputed": true,
+		"controlledRef": true,
+		"createApp": true,
+		"createEventHook": true,
+		"createGlobalState": true,
+		"createInjectionState": true,
+		"createReactiveFn": true,
+		"createSharedComposable": true,
+		"createUnrefFn": true,
+		"customRef": true,
+		"debouncedRef": true,
+		"debouncedWatch": true,
+		"defineAsyncComponent": true,
+		"defineComponent": true,
+		"eagerComputed": true,
+		"effectScope": true,
+		"extendRef": true,
+		"getCurrentInstance": true,
+		"getCurrentScope": true,
+		"h": true,
+		"ignorableWatch": true,
+		"inject": true,
+		"isDefined": true,
+		"isProxy": true,
+		"isReactive": true,
+		"isReadonly": true,
+		"isRef": true,
+		"makeDestructurable": true,
+		"markRaw": true,
+		"nextTick": true,
+		"onActivated": true,
+		"onBeforeMount": true,
+		"onBeforeUnmount": true,
+		"onBeforeUpdate": true,
+		"onClickOutside": true,
+		"onDeactivated": true,
+		"onErrorCaptured": true,
+		"onKeyStroke": true,
+		"onLongPress": true,
+		"onMounted": true,
+		"onRenderTracked": true,
+		"onRenderTriggered": true,
+		"onScopeDispose": true,
+		"onServerPrefetch": true,
+		"onStartTyping": true,
+		"onUnmounted": true,
+		"onUpdated": true,
+		"pausableWatch": true,
+		"provide": true,
+		"reactify": true,
+		"reactifyObject": true,
+		"reactive": true,
+		"reactiveComputed": true,
+		"reactiveOmit": true,
+		"reactivePick": true,
+		"readonly": true,
+		"ref": true,
+		"refAutoReset": true,
+		"refDebounced": true,
+		"refDefault": true,
+		"refThrottled": true,
+		"refWithControl": true,
+		"resolveComponent": true,
+		"resolveDirective": true,
+		"resolveRef": true,
+		"resolveUnref": true,
+		"shallowReactive": true,
+		"shallowReadonly": true,
+		"shallowRef": true,
+		"syncRef": true,
+		"syncRefs": true,
+		"templateRef": true,
+		"throttledRef": true,
+		"throttledWatch": true,
+		"toRaw": true,
+		"toReactive": true,
+		"toRef": true,
+		"toRefs": true,
+		"triggerRef": true,
+		"tryOnBeforeMount": true,
+		"tryOnBeforeUnmount": true,
+		"tryOnMounted": true,
+		"tryOnScopeDispose": true,
+		"tryOnUnmounted": true,
+		"unref": true,
+		"unrefElement": true,
+		"until": true,
+		"useActiveElement": true,
+		"useArrayEvery": true,
+		"useArrayFilter": true,
+		"useArrayFind": true,
+		"useArrayFindIndex": true,
+		"useArrayFindLast": true,
+		"useArrayJoin": true,
+		"useArrayMap": true,
+		"useArrayReduce": true,
+		"useArraySome": true,
+		"useArrayUnique": true,
+		"useAsyncQueue": true,
+		"useAsyncState": true,
+		"useAttrs": true,
+		"useBase64": true,
+		"useBattery": true,
+		"useBluetooth": true,
+		"useBreakpoints": true,
+		"useBroadcastChannel": true,
+		"useBrowserLocation": true,
+		"useCached": true,
+		"useClipboard": true,
+		"useCloned": true,
+		"useColorMode": true,
+		"useConfirmDialog": true,
+		"useCounter": true,
+		"useCssModule": true,
+		"useCssVar": true,
+		"useCssVars": true,
+		"useCurrentElement": true,
+		"useCycleList": true,
+		"useDark": true,
+		"useDateFormat": true,
+		"useDebounce": true,
+		"useDebounceFn": true,
+		"useDebouncedRefHistory": true,
+		"useDeviceMotion": true,
+		"useDeviceOrientation": true,
+		"useDevicePixelRatio": true,
+		"useDevicesList": true,
+		"useDisplayMedia": true,
+		"useDocumentVisibility": true,
+		"useDraggable": true,
+		"useDropZone": true,
+		"useElementBounding": true,
+		"useElementByPoint": true,
+		"useElementHover": true,
+		"useElementSize": true,
+		"useElementVisibility": true,
+		"useEventBus": true,
+		"useEventListener": true,
+		"useEventSource": true,
+		"useEyeDropper": true,
+		"useFavicon": true,
+		"useFetch": true,
+		"useFileDialog": true,
+		"useFileSystemAccess": true,
+		"useFocus": true,
+		"useFocusWithin": true,
+		"useFps": true,
+		"useFullscreen": true,
+		"useGamepad": true,
+		"useGeolocation": true,
+		"useIdle": true,
+		"useImage": true,
+		"useInfiniteScroll": true,
+		"useIntersectionObserver": true,
+		"useInterval": true,
+		"useIntervalFn": true,
+		"useKeyModifier": true,
+		"useLastChanged": true,
+		"useLocalStorage": true,
+		"useMagicKeys": true,
+		"useManualRefHistory": true,
+		"useMediaControls": true,
+		"useMediaQuery": true,
+		"useMemoize": true,
+		"useMemory": true,
+		"useMounted": true,
+		"useMouse": true,
+		"useMouseInElement": true,
+		"useMousePressed": true,
+		"useMutationObserver": true,
+		"useNavigatorLanguage": true,
+		"useNetwork": true,
+		"useNow": true,
+		"useObjectUrl": true,
+		"useOffsetPagination": true,
+		"useOnline": true,
+		"usePageLeave": true,
+		"useParallax": true,
+		"usePermission": true,
+		"usePointer": true,
+		"usePointerLock": true,
+		"usePointerSwipe": true,
+		"usePreferredColorScheme": true,
+		"usePreferredContrast": true,
+		"usePreferredDark": true,
+		"usePreferredLanguages": true,
+		"usePreferredReducedMotion": true,
+		"usePrevious": true,
+		"useRafFn": true,
+		"useRefHistory": true,
+		"useResizeObserver": true,
+		"useScreenOrientation": true,
+		"useScreenSafeArea": true,
+		"useScriptTag": true,
+		"useScroll": true,
+		"useScrollLock": true,
+		"useSessionStorage": true,
+		"useShare": true,
+		"useSlots": true,
+		"useSorted": true,
+		"useSpeechRecognition": true,
+		"useSpeechSynthesis": true,
+		"useStepper": true,
+		"useStorage": true,
+		"useStorageAsync": true,
+		"useStyleTag": true,
+		"useSupported": true,
+		"useSwipe": true,
+		"useTemplateRefsList": true,
+		"useTextDirection": true,
+		"useTextSelection": true,
+		"useTextareaAutosize": true,
+		"useThrottle": true,
+		"useThrottleFn": true,
+		"useThrottledRefHistory": true,
+		"useTimeAgo": true,
+		"useTimeout": true,
+		"useTimeoutFn": true,
+		"useTimeoutPoll": true,
+		"useTimestamp": true,
+		"useTitle": true,
+		"useToNumber": true,
+		"useToString": true,
+		"useToggle": true,
+		"useTransition": true,
+		"useUrlSearchParams": true,
+		"useUserMedia": true,
+		"useVModel": true,
+		"useVModels": true,
+		"useVibrate": true,
+		"useVirtualList": true,
+		"useWakeLock": true,
+		"useWebNotification": true,
+		"useWebSocket": true,
+		"useWebWorker": true,
+		"useWebWorkerFn": true,
+		"useWindowFocus": true,
+		"useWindowScroll": true,
+		"useWindowSize": true,
+		"watch": true,
+		"watchArray": true,
+		"watchAtMost": true,
+		"watchDebounced": true,
+		"watchEffect": true,
+		"watchIgnorable": true,
+		"watchOnce": true,
+		"watchPausable": true,
+		"watchPostEffect": true,
+		"watchSyncEffect": true,
+		"watchThrottled": true,
+		"watchTriggerable": true,
+		"watchWithFilter": true,
+		"whenever": true,
+		"ImportOption": true,
+		"TreeType": true,
+		"FieldOption": true,
+		"PageData": true,
+		"storeToRefs": true,
+		"DictDataOption": true,
+		"UploadOption": true
+	}
+}

+ 41 - 0
.eslintrc.js

@@ -0,0 +1,41 @@
+module.exports = {
+	env: {
+		browser: true,
+		es2021: true,
+		node: true
+	},
+	parser: 'vue-eslint-parser',
+	extends: [
+		'eslint:recommended',
+		'plugin:vue/vue3-essential',
+		'plugin:@typescript-eslint/recommended',
+		'./.eslintrc-auto-import.json',
+		'plugin:prettier/recommended'
+	],
+	parserOptions: {
+		ecmaVersion: '2020',
+		sourceType: 'module',
+		parser: '@typescript-eslint/parser'
+	},
+	plugins: ['vue', '@typescript-eslint'],
+	rules: {
+		'vue/multi-word-component-names': 'off',
+		'@typescript-eslint/no-empty-function': 'off',
+		'@typescript-eslint/no-explicit-any': 'off',
+		'vue/no-v-model-argument': 'off',
+		'@typescript-eslint/ban-types': [
+			'error',
+			{
+				// 关闭空类型检查 {}
+				extendDefaults: true,
+				types: {
+					'{}': false
+				}
+			}
+		]
+	},
+	globals: {
+		DialogOption: 'readonly',
+		OptionType: 'readonly'
+	}
+};

+ 9 - 0
.prettierignore

@@ -0,0 +1,9 @@
+/dist/*
+.local
+.output.js
+/node_modules/**
+
+**/*.svg
+**/*.sh
+
+/public/*

+ 46 - 0
.prettierrc.cjs

@@ -0,0 +1,46 @@
+/**
+ * 代码格式化配置
+ */
+module.exports = {
+	// 一行最多多少个字符
+	printWidth: 150,
+	// 指定每个缩进级别的空格数
+	tabWidth: 2,
+	// 使用制表符而不是空格缩进行
+	useTabs: true,
+	// 在语句末尾是否需要分号
+	semi: true,
+	// 是否使用单引号
+	singleQuote: true,
+	// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
+	quoteProps: 'as-needed',
+	// 在JSX中使用单引号而不是双引号
+	jsxSingleQuote: false,
+	// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none
+	trailingComma: 'none',
+	// 在对象文字中的括号之间打印空格
+	bracketSpacing: true,
+	// jsx 标签的反尖括号需要换行
+	jsxBracketSameLine: false,
+	embeddedLanguageFormatting: 'off',
+	// 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
+	arrowParens: 'always',
+	// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
+	rangeStart: 0,
+	rangeEnd: Infinity,
+	// 指定要使用的解析器,不需要写文件开头的 @prettier
+	requirePragma: false,
+	// 不需要自动在文件开头插入 @prettier
+	insertPragma: false,
+	// 使用默认的折行标准 always\never\preserve
+	proseWrap: 'preserve',
+	// 指定HTML文件的全局空格敏感度 css\strict\ignore
+	htmlWhitespaceSensitivity: 'css',
+	// Vue文件脚本和样式标签缩进
+	vueIndentScriptAndStyle: false,
+	//在 windows 操作系统中换行符通常是回车 (CR) 加换行分隔符 (LF),也就是回车换行(CRLF),
+	//然而在 Linux 和 Unix 中只使用简单的换行分隔符 (LF)。
+	//对应的控制字符为 "\n" (LF) 和 "\r\n"(CRLF)。auto意为保持现有的行尾
+	// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
+	endOfLine: 'auto'
+};

+ 63 - 9
README.md

@@ -1,9 +1,62 @@
 ## 平台简介
 
-* 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
-* 配套后端代码仓库地址 
-* [RuoYi-Vue-Plus 5.X(注意版本号)](https://gitee.com/dromara/RuoYi-Vue-Plus)
-* [RuoYi-Cloud-Plus 2.X(注意版本号)](https://gitee.com/dromara/RuoYi-Cloud-Plus)
+## 平台简介
+
+- 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
+- 配套后端代码仓库地址
+- [RuoYi-Vue-Plus 5.X(注意版本号)](https://gitee.com/dromara/RuoYi-Vue-Plus)
+- [RuoYi-Cloud-Plus 2.X(注意版本号)](https://gitee.com/dromara/RuoYi-Cloud-Plus)
+
+## 前端运行
+
+```bash
+# 克隆项目
+git clone https://gitee.com/JavaLionLi/plus-ui.git
+
+# 安装依赖
+npm install --registry=https://registry.npmmirror.com
+
+# 启动服务
+npm run dev
+
+# 构建测试环境 yarn build:stage
+# 构建生产环境 yarn build:prod
+# 前端访问地址 http://localhost:80
+```
+
+## 本框架与 RuoYi 的业务差异
+
+| 业务         | 功能说明                                                        | 本框架 | RuoYi                          |
+| ------------ | --------------------------------------------------------------- | ------ | ------------------------------ |
+| 租户管理     | 系统内租户的管理 如:租户套餐、过期时间、用户数量、企业信息等    | 支持   | 无                             |
+| 租户套餐管理 | 系统内租户所能使用的套餐管理 如:套餐内所包含的菜单等            | 支持   | 无                             |
+| 用户管理     | 用户的管理配置 如:新增用户、分配用户所属部门、角色、岗位等      | 支持   | 支持                           |
+| 部门管理     | 配置系统组织机构(公司、部门、小组) 树结构展现支持数据权限     | 支持   | 支持                           |
+| 岗位管理     | 配置系统用户所属担任职务                                        | 支持   | 支持                           |
+| 菜单管理     | 配置系统菜单、操作权限、按钮权限标识等                          | 支持   | 支持                           |
+| 角色管理     | 角色菜单权限分配、设置角色按机构进行数据范围权限划分            | 支持   | 支持                           |
+| 字典管理     | 对系统中经常使用的一些较为固定的数据进行维护                    | 支持   | 支持                           |
+| 参数管理     | 对系统动态配置常用参数                                          | 支持   | 支持                           |
+| 通知公告     | 系统通知公告信息发布维护                                        | 支持   | 支持                           |
+| 操作日志     | 系统正常操作日志记录和查询 系统异常信息日志记录和查询           | 支持   | 支持                           |
+| 登录日志     | 系统登录日志记录查询包含登录异常                                | 支持   | 支持                           |
+| 文件管理     | 系统文件展示、上传、下载、删除等管理                            | 支持   | 无                             |
+| 文件配置管理 | 系统文件上传、下载所需要的配置信息动态添加、修改、删除等管理    | 支持   | 无                             |
+| 在线用户管理 | 已登录系统的在线用户信息监控与强制踢出操作                      | 支持   | 支持                           |
+| 定时任务     | 运行报表、任务管理(添加、修改、删除)、日志管理、执行器管理等    | 支持   | 仅支持任务与日志管理           |
+| 代码生成     | 多数据源前后端代码的生成(java、html、xml、sql)支持 CRUD 下载  | 支持   | 仅支持单数据源                 |
+| 系统接口     | 根据业务代码自动生成相关的 api 接口文档                         | 支持   | 支持                           |
+| 服务监控     | 监视集群系统 CPU、内存、磁盘、堆栈、在线日志、Spring 相关配置等 | 支持   | 仅支持单机 CPU、内存、磁盘监控 |
+| 缓存监控     | 对系统的缓存信息查询,命令统计等。                              | 支持   | 支持                           |
+| 在线构建器   | 拖动表单元素生成相应的 HTML 代码。                              | 支持   | 支持                           |
+| 使用案例     | 系统的一些功能案例                                              | 支持   | 不支持                         |
+
+## 演示图
+
+- 本仓库为前端技术栈 [Vue3](https://v3.cn.vuejs.org) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 版本。
+- 配套后端代码仓库地址
+- [RuoYi-Vue-Plus 5.X(注意版本号)](https://gitee.com/dromara/RuoYi-Vue-Plus)
+- [RuoYi-Cloud-Plus 2.X(注意版本号)](https://gitee.com/dromara/RuoYi-Cloud-Plus)
 
 ## 前端运行
 
@@ -23,6 +76,7 @@ npm run dev
 ```
 
 ## 后端改造
+
 参考后端代码内 `ruoyi-gen/resources/vm/vue/v3/readme.txt` 说明
 
 ## 内置功能
@@ -40,11 +94,11 @@ npm run dev
 11. 登录日志:系统登录日志记录查询包含登录异常。
 12. 在线用户:当前系统中活跃用户状态监控。
 13. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
-14. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
-15. 系统接口:根据业务代码自动生成相关的api接口文档。
-16. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
+14. 代码生成:前后端代码的生成(java、html、xml、sql)支持 CRUD 下载 。
+15. 系统接口:根据业务代码自动生成相关的 api 接口文档。
+16. 服务监控:监视当前系统 CPU、内存、磁盘、堆栈等相关信息。
 17. 缓存监控:对系统的缓存信息查询,命令统计等。
-18. 在线构建器:拖动表单元素生成相应的HTML代码。
+18. 在线构建器:拖动表单元素生成相应的 HTML 代码。
 
 ## 演示图
 
@@ -81,4 +135,4 @@ npm run dev
         <td><img src="https://oscimg.oschina.net/oscnet/b6115bc8c31de52951982e509930b20684a.jpg"/></td>
         <td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
     </tr>
-</table>
+</table>

+ 24 - 0
Vite/plugins/auto-import.ts

@@ -0,0 +1,24 @@
+import AutoImport from 'unplugin-auto-import/vite';
+import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
+import IconsResolver from 'unplugin-icons/resolver';
+
+export default (path: any) => {
+	return AutoImport({
+		// 自动导入 Vue 相关函数
+		imports: ['vue', 'vue-router', '@vueuse/core', 'pinia'],
+		eslintrc: {
+			enabled: false,
+			filepath: './.eslintrc-auto-import.json',
+			globalsPropValue: true
+		},
+		resolvers: [
+			// 自动导入 Element Plus 相关函数ElMessage, ElMessageBox... (带样式)
+			ElementPlusResolver(),
+			IconsResolver({
+				prefix: 'Icon'
+			})
+		],
+		vueTemplate: true, // 是否在 vue 模板中自动导入
+		dts: path.resolve(path.resolve(__dirname, '../../src'), 'types', 'auto-imports.d.ts')
+	});
+};

+ 17 - 0
Vite/plugins/components.ts

@@ -0,0 +1,17 @@
+import Components from 'unplugin-vue-components/vite';
+import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
+import IconsResolver from 'unplugin-icons/resolver';
+
+export default (path: any) => {
+	return Components({
+		resolvers: [
+			// 自动导入 Element Plus 组件
+			ElementPlusResolver(),
+			// 自动注册图标组件
+			IconsResolver({
+				enabledCollections: ['ep']
+			})
+		],
+		dts: path.resolve(path.resolve(__dirname, '../../src'), 'types', 'components.d.ts')
+	});
+};

+ 8 - 0
Vite/plugins/icons.ts

@@ -0,0 +1,8 @@
+import Icons from 'unplugin-icons/vite';
+
+export default () => {
+	return Icons({
+		// 自动安装图标库
+		autoInstall: true
+	});
+};

+ 18 - 0
Vite/plugins/index.ts

@@ -0,0 +1,18 @@
+import vue from '@vitejs/plugin-vue';
+import createUnoCss from './unocss';
+import createAutoImport from './auto-import';
+import createComponents from './components';
+import createIcons from './icons';
+import createSvgIconsPlugin from './svg-icon';
+import path from 'path';
+
+export default (viteEnv, isBuild = false): [] => {
+	const vitePlusgins: any = [];
+	vitePlusgins.push(vue());
+	vitePlusgins.push(createUnoCss());
+	vitePlusgins.push(createAutoImport(path));
+	vitePlusgins.push(createComponents(path));
+	vitePlusgins.push(createIcons());
+	vitePlusgins.push(createSvgIconsPlugin(path));
+	return vitePlusgins;
+};

+ 9 - 0
Vite/plugins/svg-icon.ts

@@ -0,0 +1,9 @@
+import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
+export default (path: any) => {
+	return createSvgIconsPlugin({
+		// 指定需要缓存的图标文件夹
+		iconDirs: [path.resolve(path.resolve(__dirname, '../../src'), 'assets/icons/svg')],
+		// 指定symbolId格式
+		symbolId: 'icon-[dir]-[name]'
+	});
+};

+ 13 - 0
Vite/plugins/unocss.ts

@@ -0,0 +1,13 @@
+import UnoCss from 'unocss/vite';
+import { presetUno, presetAttributify, presetIcons } from 'unocss';
+
+export default () => {
+	return UnoCss({
+		presets: [presetUno(), presetAttributify(), presetIcons()],
+		// rules: [['search', {}]],
+		shortcuts: {
+			'panel-title':
+				'pb-[5px] font-sans leading-[1.1] font-medium text-base text-[#6379bb] border-b border-b-solid border-[var(--el-border-color-light)] mb-5 mt-0'
+		}
+	});
+};

+ 22 - 0
commitlint.config.js

@@ -0,0 +1,22 @@
+module.exports = {
+	extends: ['@commitlint/config-conventional'],
+	rules: {
+		'type-enum': [
+			2,
+			'always',
+			[
+				'feat', // 新功能 feature
+				'fix', // 修复 bug
+				'docs', // 文档注释
+				'style', // 代码格式
+				'refactor', // 重构
+				'perf', // 性能优化
+				'test', // 增加测试
+				'chore', // 构建过程或辅助工具的变动
+				'revert', // 回退
+				'build' // 打包
+			]
+		],
+		'subject-case': [0]
+	}
+};

File diff suppressed because it is too large
+ 0 - 19
html/ie.html


+ 215 - 213
index.html

@@ -1,215 +1,217 @@
 <!DOCTYPE html>
 <html>
-
-<head>
-  <meta charset="utf-8">
-  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-  <meta name="renderer" content="webkit">
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
-  <link rel="icon" href="/favicon.ico">
-  <title>RuoYi-Vue-Plus多租户管理系统</title>
-  <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
-  <style>
-    html,
-    body,
-    #app {
-      height: 100%;
-      margin: 0px;
-      padding: 0px;
-    }
-
-    .chromeframe {
-      margin: 0.2em 0;
-      background: #ccc;
-      color: #000;
-      padding: 0.2em 0;
-    }
-
-    #loader-wrapper {
-      position: fixed;
-      top: 0;
-      left: 0;
-      width: 100%;
-      height: 100%;
-      z-index: 999999;
-    }
-
-    #loader {
-      display: block;
-      position: relative;
-      left: 50%;
-      top: 50%;
-      width: 150px;
-      height: 150px;
-      margin: -75px 0 0 -75px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      border-top-color: #FFF;
-      -webkit-animation: spin 2s linear infinite;
-      -ms-animation: spin 2s linear infinite;
-      -moz-animation: spin 2s linear infinite;
-      -o-animation: spin 2s linear infinite;
-      animation: spin 2s linear infinite;
-      z-index: 1001;
-    }
-
-    #loader:before {
-      content: "";
-      position: absolute;
-      top: 5px;
-      left: 5px;
-      right: 5px;
-      bottom: 5px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      border-top-color: #FFF;
-      -webkit-animation: spin 3s linear infinite;
-      -moz-animation: spin 3s linear infinite;
-      -o-animation: spin 3s linear infinite;
-      -ms-animation: spin 3s linear infinite;
-      animation: spin 3s linear infinite;
-    }
-
-    #loader:after {
-      content: "";
-      position: absolute;
-      top: 15px;
-      left: 15px;
-      right: 15px;
-      bottom: 15px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      border-top-color: #FFF;
-      -moz-animation: spin 1.5s linear infinite;
-      -o-animation: spin 1.5s linear infinite;
-      -ms-animation: spin 1.5s linear infinite;
-      -webkit-animation: spin 1.5s linear infinite;
-      animation: spin 1.5s linear infinite;
-    }
-
-
-    @-webkit-keyframes spin {
-      0% {
-        -webkit-transform: rotate(0deg);
-        -ms-transform: rotate(0deg);
-        transform: rotate(0deg);
-      }
-
-      100% {
-        -webkit-transform: rotate(360deg);
-        -ms-transform: rotate(360deg);
-        transform: rotate(360deg);
-      }
-    }
-
-    @keyframes spin {
-      0% {
-        -webkit-transform: rotate(0deg);
-        -ms-transform: rotate(0deg);
-        transform: rotate(0deg);
-      }
-
-      100% {
-        -webkit-transform: rotate(360deg);
-        -ms-transform: rotate(360deg);
-        transform: rotate(360deg);
-      }
-    }
-
-
-    #loader-wrapper .loader-section {
-      position: fixed;
-      top: 0;
-      width: 51%;
-      height: 100%;
-      background: #7171C6;
-      z-index: 1000;
-      -webkit-transform: translateX(0);
-      -ms-transform: translateX(0);
-      transform: translateX(0);
-    }
-
-    #loader-wrapper .loader-section.section-left {
-      left: 0;
-    }
-
-    #loader-wrapper .loader-section.section-right {
-      right: 0;
-    }
-
-
-    .loaded #loader-wrapper .loader-section.section-left {
-      -webkit-transform: translateX(-100%);
-      -ms-transform: translateX(-100%);
-      transform: translateX(-100%);
-      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-    }
-
-    .loaded #loader-wrapper .loader-section.section-right {
-      -webkit-transform: translateX(100%);
-      -ms-transform: translateX(100%);
-      transform: translateX(100%);
-      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-    }
-
-    .loaded #loader {
-      opacity: 0;
-      -webkit-transition: all 0.3s ease-out;
-      transition: all 0.3s ease-out;
-    }
-
-    .loaded #loader-wrapper {
-      visibility: hidden;
-      -webkit-transform: translateY(-100%);
-      -ms-transform: translateY(-100%);
-      transform: translateY(-100%);
-      -webkit-transition: all 0.3s 1s ease-out;
-      transition: all 0.3s 1s ease-out;
-    }
-
-    .no-js #loader-wrapper {
-      display: none;
-    }
-
-    .no-js h1 {
-      color: #222222;
-    }
-
-    #loader-wrapper .load_title {
-      font-family: 'Open Sans';
-      color: #FFF;
-      font-size: 19px;
-      width: 100%;
-      text-align: center;
-      z-index: 9999999999999;
-      position: absolute;
-      top: 60%;
-      opacity: 1;
-      line-height: 30px;
-    }
-
-    #loader-wrapper .load_title span {
-      font-weight: normal;
-      font-style: italic;
-      font-size: 13px;
-      color: #FFF;
-      opacity: 0.5;
-    }
-  </style>
-</head>
-
-<body>
-  <div id="app">
-    <div id="loader-wrapper">
-      <div id="loader"></div>
-      <div class="loader-section section-left"></div>
-      <div class="loader-section section-right"></div>
-      <div class="load_title">正在加载系统资源,请耐心等待</div>
-    </div>
-  </div>
-  <script type="module" src="/src/main.js"></script>
-</body>
-
-</html>
+	<head>
+		<meta charset="utf-8" />
+		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+		<meta name="renderer" content="webkit" />
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
+		<link rel="icon" href="/favicon.ico" />
+		<title>RuoYi-Vue-Plus多租户管理系统</title>
+		<!--[if lt IE 11
+			]><script>
+				window.location.href='/html/ie.html';
+			</script><!
+		[endif]-->
+		<style>
+			html,
+			body,
+			#app {
+			  height: 100%;
+			  margin: 0px;
+			  padding: 0px;
+			}
+
+			.chromeframe {
+			  margin: 0.2em 0;
+			  background: #ccc;
+			  color: #000;
+			  padding: 0.2em 0;
+			}
+
+			#loader-wrapper {
+			  position: fixed;
+			  top: 0;
+			  left: 0;
+			  width: 100%;
+			  height: 100%;
+			  z-index: 999999;
+			}
+
+			#loader {
+			  display: block;
+			  position: relative;
+			  left: 50%;
+			  top: 50%;
+			  width: 150px;
+			  height: 150px;
+			  margin: -75px 0 0 -75px;
+			  border-radius: 50%;
+			  border: 3px solid transparent;
+			  border-top-color: #FFF;
+			  -webkit-animation: spin 2s linear infinite;
+			  -ms-animation: spin 2s linear infinite;
+			  -moz-animation: spin 2s linear infinite;
+			  -o-animation: spin 2s linear infinite;
+			  animation: spin 2s linear infinite;
+			  z-index: 1001;
+			}
+
+			#loader:before {
+			  content: "";
+			  position: absolute;
+			  top: 5px;
+			  left: 5px;
+			  right: 5px;
+			  bottom: 5px;
+			  border-radius: 50%;
+			  border: 3px solid transparent;
+			  border-top-color: #FFF;
+			  -webkit-animation: spin 3s linear infinite;
+			  -moz-animation: spin 3s linear infinite;
+			  -o-animation: spin 3s linear infinite;
+			  -ms-animation: spin 3s linear infinite;
+			  animation: spin 3s linear infinite;
+			}
+
+			#loader:after {
+			  content: "";
+			  position: absolute;
+			  top: 15px;
+			  left: 15px;
+			  right: 15px;
+			  bottom: 15px;
+			  border-radius: 50%;
+			  border: 3px solid transparent;
+			  border-top-color: #FFF;
+			  -moz-animation: spin 1.5s linear infinite;
+			  -o-animation: spin 1.5s linear infinite;
+			  -ms-animation: spin 1.5s linear infinite;
+			  -webkit-animation: spin 1.5s linear infinite;
+			  animation: spin 1.5s linear infinite;
+			}
+
+
+			@-webkit-keyframes spin {
+			  0% {
+			    -webkit-transform: rotate(0deg);
+			    -ms-transform: rotate(0deg);
+			    transform: rotate(0deg);
+			  }
+
+			  100% {
+			    -webkit-transform: rotate(360deg);
+			    -ms-transform: rotate(360deg);
+			    transform: rotate(360deg);
+			  }
+			}
+
+			@keyframes spin {
+			  0% {
+			    -webkit-transform: rotate(0deg);
+			    -ms-transform: rotate(0deg);
+			    transform: rotate(0deg);
+			  }
+
+			  100% {
+			    -webkit-transform: rotate(360deg);
+			    -ms-transform: rotate(360deg);
+			    transform: rotate(360deg);
+			  }
+			}
+
+
+			#loader-wrapper .loader-section {
+			  position: fixed;
+			  top: 0;
+			  width: 51%;
+			  height: 100%;
+			  background: #7171C6;
+			  z-index: 1000;
+			  -webkit-transform: translateX(0);
+			  -ms-transform: translateX(0);
+			  transform: translateX(0);
+			}
+
+			#loader-wrapper .loader-section.section-left {
+			  left: 0;
+			}
+
+			#loader-wrapper .loader-section.section-right {
+			  right: 0;
+			}
+
+
+			.loaded #loader-wrapper .loader-section.section-left {
+			  -webkit-transform: translateX(-100%);
+			  -ms-transform: translateX(-100%);
+			  transform: translateX(-100%);
+			  -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+			  transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+			}
+
+			.loaded #loader-wrapper .loader-section.section-right {
+			  -webkit-transform: translateX(100%);
+			  -ms-transform: translateX(100%);
+			  transform: translateX(100%);
+			  -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+			  transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
+			}
+
+			.loaded #loader {
+			  opacity: 0;
+			  -webkit-transition: all 0.3s ease-out;
+			  transition: all 0.3s ease-out;
+			}
+
+			.loaded #loader-wrapper {
+			  visibility: hidden;
+			  -webkit-transform: translateY(-100%);
+			  -ms-transform: translateY(-100%);
+			  transform: translateY(-100%);
+			  -webkit-transition: all 0.3s 1s ease-out;
+			  transition: all 0.3s 1s ease-out;
+			}
+
+			.no-js #loader-wrapper {
+			  display: none;
+			}
+
+			.no-js h1 {
+			  color: #222222;
+			}
+
+			#loader-wrapper .load_title {
+			  font-family: 'Open Sans';
+			  color: #FFF;
+			  font-size: 19px;
+			  width: 100%;
+			  text-align: center;
+			  z-index: 9999999999999;
+			  position: absolute;
+			  top: 60%;
+			  opacity: 1;
+			  line-height: 30px;
+			}
+
+			#loader-wrapper .load_title span {
+			  font-weight: normal;
+			  font-style: italic;
+			  font-size: 13px;
+			  color: #FFF;
+			  opacity: 0.5;
+			}
+		</style>
+	</head>
+
+	<body>
+		<div id="app">
+			<div id="loader-wrapper">
+				<div id="loader"></div>
+				<div class="loader-section section-left"></div>
+				<div class="loader-section section-right"></div>
+				<div class="load_title">正在加载系统资源,请耐心等待</div>
+			</div>
+		</div>
+		<script type="module" src="/src/main.ts"></script>
+	</body>
+</html>

+ 78 - 41
package.json

@@ -1,43 +1,80 @@
 {
-  "name": "ruoyi-vue-plus",
-  "version": "5.0.0-SNAPSHOT",
-  "description": "RuoYi-Vue-Plus多租户管理系统",
-  "author": "LionLi",
-  "license": "MIT",
-  "scripts": {
-    "dev": "vite",
-    "build:prod": "vite build",
-    "preview": "vite preview"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://gitee.com/JavaLionLi/plus-ui.git"
-  },
-  "dependencies": {
-    "@element-plus/icons-vue": "2.0.10",
-    "@vueup/vue-quill": "1.1.0",
-    "@vueuse/core": "9.5.0",
-    "axios": "0.27.2",
-    "echarts": "5.4.0",
-    "element-plus": "2.2.27",
-    "file-saver": "2.0.5",
-    "fuse.js": "6.6.2",
-    "js-cookie": "3.0.1",
-    "jsencrypt": "3.3.1",
-    "nprogress": "0.2.0",
-    "pinia": "2.0.22",
-    "vue": "3.2.45",
-    "vue-cropper": "1.0.3",
-    "vue-router": "4.1.4"
-  },
-  "devDependencies": {
-    "@vitejs/plugin-vue": "3.1.0",
-    "@vue/compiler-sfc": "3.2.45",
-    "sass": "1.56.1",
-    "unplugin-auto-import": "0.11.4",
-    "vite": "3.2.3",
-    "vite-plugin-compression": "0.5.1",
-    "vite-plugin-svg-icons": "2.0.1",
-    "vite-plugin-vue-setup-extend": "0.4.0"
-  }
+	"name": "ruoyi-vue-plus",
+	"version": "5.0.0-SNAPSHOT",
+	"description": "RuoYi-Vue-Plus多租户管理系统",
+	"author": "LionLi",
+	"license": "MIT",
+	"scripts": {
+		"dev": "vite serve --mode development",
+		"build:prod": "vite build --mode production &&vue-tsc --noEmit",
+		"preview": "vite preview",
+		"lint": "eslint src/**/*.{ts,js,vue} --fix",
+		"prepare": "husky install",
+		"prettier": "prettier --write ."
+	},
+	"repository": {
+		"type": "git",
+		"url": "https://gitee.com/JavaLionLi/plus-ui.git"
+	},
+	"dependencies": {
+		"@element-plus/icons-vue": "2.1.0",
+		"@vueup/vue-quill": "1.1.0",
+		"@vueuse/core": "9.5.0",
+		"animate.css": "4.1.1",
+		"await-to-js": "^3.0.0",
+		"axios": "^1.3.4",
+		"echarts": "5.4.0",
+		"element-plus": "2.2.27",
+		"file-saver": "2.0.5",
+		"fuse.js": "6.6.2",
+		"js-cookie": "3.0.1",
+		"jsencrypt": "3.3.1",
+		"nprogress": "0.2.0",
+		"path-browserify": "1.0.1",
+		"path-to-regexp": "6.2.0",
+		"pinia": "2.0.22",
+		"screenfull": "6.0.0",
+		"vue": "3.2.45",
+		"vue-cropper": "1.0.3",
+		"vue-i18n": "9.2.2",
+		"vue-router": "4.1.4"
+	},
+	"devDependencies": {
+		"@iconify/json": "^2.2.40",
+		"@intlify/unplugin-vue-i18n": "0.8.2",
+		"@types/file-saver": "2.0.5",
+		"@types/js-cookie": "3.0.3",
+		"@types/node": "18.14.2",
+		"@types/nprogress": "0.2.0",
+		"@types/path-browserify": "^1.0.0",
+		"@typescript-eslint/eslint-plugin": "5.56.0",
+		"@typescript-eslint/parser": "5.56.0",
+		"@unocss/preset-attributify": "^0.50.6",
+		"@unocss/preset-icons": "^0.50.6",
+		"@unocss/preset-uno": "^0.50.6",
+		"@vitejs/plugin-vue": "4.0.0",
+		"@vue/compiler-sfc": "3.2.45",
+		"autoprefixer": "10.4.14",
+		"eslint": "8.36.0",
+		"eslint-config-prettier": "8.8.0",
+		"eslint-plugin-prettier": "4.2.1",
+		"eslint-plugin-vue": "9.9.0",
+		"fast-glob": "^3.2.11",
+		"husky": "7.0.4",
+		"postcss": "^8.4.21",
+		"prettier": "2.8.6",
+		"sass": "1.56.1",
+		"typescript": "4.9.5",
+		"unocss": "^0.50.6",
+		"unplugin-auto-import": "0.13.0",
+		"unplugin-icons": "0.15.1",
+		"unplugin-vue-components": "0.23.0",
+		"vite": "4.1.4",
+		"vite-plugin-compression": "0.5.1",
+		"vite-plugin-svg-icons": "2.0.1",
+		"vite-plugin-vue-setup-extend": "0.4.0",
+		"vitest": "^0.29.7",
+		"vue-eslint-parser": "9.1.0",
+		"vue-tsc": "0.35.0"
+	}
 }

BIN
public/favicon.ico


+ 2 - 2
src/App.vue

@@ -1,8 +1,8 @@
 <template>
-  <router-view />
+	<router-view />
 </template>
 
-<script setup>
+<script setup lang="ts">
 import useSettingsStore from '@/store/modules/settings'
 import { handleThemeStyle } from '@/utils/theme'
 

+ 48 - 0
src/animate.ts

@@ -0,0 +1,48 @@
+// 前缀
+const animatePrefix = 'animate__animated ';
+// 开启随机动画 随机动画值
+const animateList: string[] = [
+	animatePrefix + 'animate__pulse',
+	animatePrefix + 'animate__rubberBand',
+	animatePrefix + 'animate__bounceIn',
+	animatePrefix + 'animate__bounceInLeft',
+	animatePrefix + 'animate__fadeIn',
+	animatePrefix + 'animate__fadeInLeft',
+	animatePrefix + 'animate__fadeInDown',
+	animatePrefix + 'animate__fadeInUp',
+	animatePrefix + 'animate__flipInX',
+	animatePrefix + 'animate__lightSpeedInLeft',
+	animatePrefix + 'animate__rotateInDownLeft',
+	animatePrefix + 'animate__rollIn',
+	animatePrefix + 'animate__rotateInDownLeft',
+	animatePrefix + 'animate__zoomIn',
+	animatePrefix + 'animate__zoomInDown',
+	animatePrefix + 'animate__slideInLeft',
+	animatePrefix + 'animate__lightSpeedIn'
+];
+// 关闭随机动画后的默认效果
+const defaultAnimate = animatePrefix + 'animate__bounceIn';
+// 搜索隐藏显示动画
+const searchAnimate = {
+	enter: animatePrefix + 'animate__flipInX',
+	leave: animatePrefix + 'animate__bounceOut'
+};
+
+// 菜单搜索动画
+const menuSearchAnimate = {
+	enter: animatePrefix + 'animate__fadeInLeft',
+	leave: animatePrefix + 'animate__fadeOutLeft'
+};
+// logo动画
+const logoAnimate = {
+	enter: animatePrefix + 'animate__bounceIn',
+	leave: animatePrefix + 'animate__bounceOut'
+};
+
+export default {
+	animateList,
+	defaultAnimate,
+	searchAnimate,
+	menuSearchAnimate,
+	logoAnimate
+};

+ 0 - 54
src/api/demo/demo.js

@@ -1,54 +0,0 @@
-import request from '@/utils/request'
-
-// 查询测试单表列表
-export function listDemo(query) {
-  return request({
-    url: '/demo/demo/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 自定义分页接口
-export function pageDemo(query) {
-  return request({
-    url: '/demo/demo/page',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询测试单表详细
-export function getDemo(id) {
-  return request({
-    url: '/demo/demo/' + id,
-    method: 'get'
-  })
-}
-
-// 新增测试单表
-export function addDemo(data) {
-  return request({
-    url: '/demo/demo',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改测试单表
-export function updateDemo(data) {
-  return request({
-    url: '/demo/demo',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除测试单表
-export function delDemo(id) {
-  return request({
-    url: '/demo/demo/' + id,
-    method: 'delete'
-  })
-}
-

+ 55 - 0
src/api/demo/demo.ts

@@ -0,0 +1,55 @@
+import request from '@/utils/request';
+import { DemoForm, DemoQuery, DemoVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询测试单表列表
+export function listDemo(query: DemoQuery): AxiosPromise<DemoVO[]> {
+	return request({
+		url: '/demo/demo/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 自定义分页接口
+export function pageDemo(query: DemoQuery): AxiosPromise<DemoVO[]> {
+	return request({
+		url: '/demo/demo/page',
+		method: 'get',
+		params: query
+	});
+}
+
+// 查询测试单表详细
+export function getDemo(id: string | number): AxiosPromise<DemoVO> {
+	return request({
+		url: '/demo/demo/' + id,
+		method: 'get'
+	});
+}
+
+// 新增测试单表
+export function addDemo(data: DemoForm) {
+	return request({
+		url: '/demo/demo',
+		method: 'post',
+		data: data
+	});
+}
+
+// 修改测试单表
+export function updateDemo(data: DemoForm) {
+	return request({
+		url: '/demo/demo',
+		method: 'put',
+		data: data
+	});
+}
+
+// 删除测试单表
+export function delDemo(id: string | number | Array<string | number>) {
+	return request({
+		url: '/demo/demo/' + id,
+		method: 'delete'
+	});
+}

+ 0 - 44
src/api/demo/tree.js

@@ -1,44 +0,0 @@
-import request from '@/utils/request'
-
-// 查询测试树表列表
-export function listTree(query) {
-  return request({
-    url: '/demo/tree/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询测试树表详细
-export function getTree(id) {
-  return request({
-    url: '/demo/tree/' + id,
-    method: 'get'
-  })
-}
-
-// 新增测试树表
-export function addTree(data) {
-  return request({
-    url: '/demo/tree',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改测试树表
-export function updateTree(data) {
-  return request({
-    url: '/demo/tree',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除测试树表
-export function delTree(id) {
-  return request({
-    url: '/demo/tree/' + id,
-    method: 'delete'
-  })
-}

+ 46 - 0
src/api/demo/tree.ts

@@ -0,0 +1,46 @@
+import { AxiosPromise } from 'axios';
+import request from '@/utils/request';
+import { DemoTreeForm, DemoTreeVO, DemoTreeQuery } from './types';
+
+// 查询测试树表列表
+export function listTree(query?: DemoTreeQuery): AxiosPromise<DemoTreeVO[]> {
+	return request({
+		url: '/demo/tree/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 查询测试树表详细
+export function getTree(id: string | number): AxiosPromise<DemoTreeVO> {
+	return request({
+		url: '/demo/tree/' + id,
+		method: 'get'
+	});
+}
+
+// 新增测试树表
+export function addTree(data: DemoTreeForm) {
+	return request({
+		url: '/demo/tree',
+		method: 'post',
+		data: data
+	});
+}
+
+// 修改测试树表
+export function updateTree(data: DemoTreeForm) {
+	return request({
+		url: '/demo/tree',
+		method: 'put',
+		data: data
+	});
+}
+
+// 删除测试树表
+export function delTree(id: string | number | Array<string | number>) {
+	return request({
+		url: '/demo/tree/' + id,
+		method: 'delete'
+	});
+}

+ 55 - 0
src/api/demo/types.ts

@@ -0,0 +1,55 @@
+export interface DemoVO extends BaseEntity {
+	id: number | string;
+	deptId: number | string;
+	userId: number | string;
+	orderNum: number;
+	testKey: string;
+	value: string;
+	createByName: string;
+	updateByName?: any;
+}
+
+export interface DemoQuery extends PageQuery {
+	testKey: string;
+	value: string;
+	createTime: string;
+}
+export interface DemoForm {
+	id: string | number | undefined;
+	deptId: string | number | undefined;
+	userId: string | number | undefined;
+	orderNum: number;
+	testKey: string;
+	value: string;
+	version: string;
+	ossConfigId: string | number | undefined;
+	createTime?: string;
+}
+
+export interface DemoTreeVO extends BaseEntity {
+	id: number | string;
+	parentId: number | string;
+	deptId: number | string;
+	userId: number | string;
+	treeName: string;
+	children?: DemoTreeVO[];
+}
+
+export interface DemoTreeQuery {
+	treeName: string;
+	createTime: string;
+}
+
+export interface DemoTreeForm {
+	id: string | number | undefined;
+	parentId: string | number | undefined;
+	deptId: string | number | undefined;
+	userId: string | number | undefined;
+	treeName: string;
+}
+
+export interface DemoTreeOptionsType {
+	id: string | number;
+	treeName: string;
+	children?: DemoTreeOptionsType[];
+}

+ 0 - 83
src/api/login.js

@@ -1,83 +0,0 @@
-import request from '@/utils/request'
-
-// 登录方法
-export function login(tenantId, username, password, code, uuid) {
-  const data = {
-    tenantId,
-    username,
-    password,
-    code,
-    uuid
-  }
-  return request({
-    url: '/auth/login',
-    headers: {
-      isToken: false
-    },
-    method: 'post',
-    data: data
-  })
-}
-
-// 注册方法
-export function register(data) {
-  return request({
-    url: '/auth/register',
-    headers: {
-      isToken: false
-    },
-    method: 'post',
-    data: data
-  })
-}
-
-// 获取用户详细信息
-export function getInfo() {
-  return request({
-    url: '/system/user/getInfo',
-    method: 'get'
-  })
-}
-
-// 退出方法
-export function logout() {
-  return request({
-    url: '/auth/logout',
-    method: 'post'
-  })
-}
-
-// 获取验证码
-export function getCodeImg() {
-  return request({
-    url: '/code',
-    headers: {
-      isToken: false
-    },
-    method: 'get',
-    timeout: 20000
-  })
-}
-
-// 短信验证码
-export function getCodeSms() {
-  return request({
-    url: '/sms/code',
-    headers: {
-      isToken: false
-    },
-    method: 'get',
-    timeout: 20000
-  })
-}
-
-// 获取租户列表
-export function getTenantList() {
-  return request({
-    url: '/auth/tenant/list',
-    headers: {
-      isToken: false
-    },
-    method: 'get'
-  })
-}

+ 81 - 0
src/api/login.ts

@@ -0,0 +1,81 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { LoginData, LoginResult, VerifyCodeResult, TenantInfo } from './types';
+import { UserInfo } from '@/api/system/user/types';
+
+/**
+ * @param data {LoginData}
+ * @returns
+ */
+export function login(data: LoginData): AxiosPromise<LoginResult> {
+	const params = {
+		tenantId: data.tenantId,
+		username: data.username.trim(),
+		password: data.password,
+		code: data.code,
+		uuid: data.uuid
+	};
+	return request({
+		url: '/auth/login',
+		headers: {
+			isToken: false
+		},
+		method: 'post',
+		data: params
+	});
+}
+
+// 注册方法
+export function register(data: any) {
+	return request({
+		url: '/auth/register',
+		headers: {
+			isToken: false
+		},
+		method: 'post',
+		data: data
+	});
+}
+
+/**
+ * 注销
+ */
+export function logout() {
+	return request({
+		url: '/auth/logout',
+		method: 'post'
+	});
+}
+
+/**
+ * 获取验证码
+ */
+export function getCodeImg(): AxiosPromise<VerifyCodeResult> {
+	return request({
+		url: '/code',
+		headers: {
+			isToken: false
+		},
+		method: 'get',
+		timeout: 20000
+	});
+}
+
+// 获取用户详细信息
+export function getInfo(): AxiosPromise<UserInfo> {
+	return request({
+		url: '/system/user/getInfo',
+		method: 'get'
+	});
+}
+
+// 获取租户列表
+export function getTenantList(): AxiosPromise<TenantInfo> {
+	return request({
+		url: '/auth/tenant/list',
+		headers: {
+			isToken: false
+		},
+		method: 'get'
+	});
+}

+ 0 - 9
src/api/menu.js

@@ -1,9 +0,0 @@
-import request from '@/utils/request'
-
-// 获取路由
-export const getRouters = () => {
-  return request({
-    url: '/system/menu/getRouters',
-    method: 'get'
-  })
-}

+ 11 - 0
src/api/menu.ts

@@ -0,0 +1,11 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { RouteRecordRaw } from 'vue-router';
+
+// 获取路由
+export function getRouters(): AxiosPromise<RouteRecordRaw[]> {
+	return request({
+		url: '/system/menu/getRouters',
+		method: 'get'
+	});
+}

+ 0 - 57
src/api/monitor/cache.js

@@ -1,57 +0,0 @@
-import request from '@/utils/request'
-
-// 查询缓存详细
-export function getCache() {
-  return request({
-    url: '/monitor/cache',
-    method: 'get'
-  })
-}
-
-// 查询缓存名称列表
-export function listCacheName() {
-  return request({
-    url: '/monitor/cache/getNames',
-    method: 'get'
-  })
-}
-
-// 查询缓存键名列表
-export function listCacheKey(cacheName) {
-  return request({
-    url: '/monitor/cache/getKeys/' + cacheName,
-    method: 'get'
-  })
-}
-
-// 查询缓存内容
-export function getCacheValue(cacheName, cacheKey) {
-  return request({
-    url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey,
-    method: 'get'
-  })
-}
-
-// 清理指定名称缓存
-export function clearCacheName(cacheName) {
-  return request({
-    url: '/monitor/cache/clearCacheName/' + cacheName,
-    method: 'delete'
-  })
-}
-
-// 清理指定键名缓存
-export function clearCacheKey(cacheName, cacheKey) {
-  return request({
-    url: '/monitor/cache/clearCacheKey/' + cacheName + '/'  + cacheKey,
-    method: 'delete'
-  })
-}
-
-// 清理全部缓存
-export function clearCacheAll() {
-  return request({
-    url: '/monitor/cache/clearCacheAll',
-    method: 'delete'
-  })
-}

+ 59 - 0
src/api/monitor/cache/index.ts

@@ -0,0 +1,59 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { CacheVO } from './types';
+
+// 查询缓存详细
+export function getCache(): AxiosPromise<CacheVO> {
+	return request({
+		url: '/monitor/cache',
+		method: 'get'
+	});
+}
+
+// 查询缓存名称列表
+export function listCacheName() {
+	return request({
+		url: '/monitor/cache/getNames',
+		method: 'get'
+	});
+}
+
+// 查询缓存键名列表
+export function listCacheKey(cacheName: string) {
+	return request({
+		url: '/monitor/cache/getKeys/' + cacheName,
+		method: 'get'
+	});
+}
+
+// 查询缓存内容
+export function getCacheValue(cacheName: string, cacheKey: string) {
+	return request({
+		url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey,
+		method: 'get'
+	});
+}
+
+// 清理指定名称缓存
+export function clearCacheName(cacheName: string) {
+	return request({
+		url: '/monitor/cache/clearCacheName/' + cacheName,
+		method: 'delete'
+	});
+}
+
+// 清理指定键名缓存
+export function clearCacheKey(cacheName: string, cacheKey: string) {
+	return request({
+		url: '/monitor/cache/clearCacheKey/' + cacheName + '/' + cacheKey,
+		method: 'delete'
+	});
+}
+
+// 清理全部缓存
+export function clearCacheAll() {
+	return request({
+		url: '/monitor/cache/clearCacheAll',
+		method: 'delete'
+	});
+}

+ 7 - 0
src/api/monitor/cache/types.ts

@@ -0,0 +1,7 @@
+export interface CacheVO {
+	commandStats: Array<{ name: string; value: string }>;
+
+	dbSize: number;
+
+	info: { [key: string]: string };
+}

+ 36 - 0
src/api/monitor/loginInfo/index.ts

@@ -0,0 +1,36 @@
+import request from '@/utils/request';
+import { LoginInfoQuery, LoginInfoVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询登录日志列表
+export function list(query: LoginInfoQuery): AxiosPromise<LoginInfoVO[]> {
+	return request({
+		url: '/monitor/logininfor/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 删除登录日志
+export function delLoginInfo(infoId: string | number | Array<string | number>) {
+	return request({
+		url: '/monitor/logininfor/' + infoId,
+		method: 'delete'
+	});
+}
+
+// 解锁用户登录状态
+export function unlockLoginInfo(userName: string | Array<string>) {
+	return request({
+		url: '/monitor/logininfor/unlock/' + userName,
+		method: 'get'
+	});
+}
+
+// 清空登录日志
+export function cleanLoginInfo() {
+	return request({
+		url: '/monitor/logininfor/clean',
+		method: 'delete'
+	});
+}

+ 20 - 0
src/api/monitor/loginInfo/types.ts

@@ -0,0 +1,20 @@
+export interface LoginInfoVO {
+	infoId: string | number;
+	tenantId: string | number;
+	userName: string;
+	status: string;
+	ipaddr: string;
+	loginLocation: string;
+	browser: string;
+	os: string;
+	msg: string;
+	loginTime: string;
+}
+
+export interface LoginInfoQuery extends PageQuery {
+	ipaddr: string;
+	userName: string;
+	status: string;
+	orderByColumn: string;
+	isAsc: string;
+}

+ 0 - 34
src/api/monitor/logininfor.js

@@ -1,34 +0,0 @@
-import request from '@/utils/request'
-
-// 查询登录日志列表
-export function list(query) {
-  return request({
-    url: '/monitor/logininfor/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 删除登录日志
-export function delLogininfor(infoId) {
-  return request({
-    url: '/monitor/logininfor/' + infoId,
-    method: 'delete'
-  })
-}
-
-// 解锁用户登录状态
-export function unlockLogininfor(userName) {
-  return request({
-    url: '/monitor/logininfor/unlock/' + userName,
-    method: 'get'
-  })
-}
-
-// 清空登录日志
-export function cleanLogininfor() {
-  return request({
-    url: '/monitor/logininfor/clean',
-    method: 'delete'
-  })
-}

+ 0 - 18
src/api/monitor/online.js

@@ -1,18 +0,0 @@
-import request from '@/utils/request'
-
-// 查询在线用户列表
-export function list(query) {
-  return request({
-    url: '/monitor/online/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 强退用户
-export function forceLogout(tokenId) {
-  return request({
-    url: '/monitor/online/' + tokenId,
-    method: 'delete'
-  })
-}

+ 20 - 0
src/api/monitor/online/index.ts

@@ -0,0 +1,20 @@
+import request from '@/utils/request';
+import { OnlineQuery, OnlineVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询在线用户列表
+export function list(query: OnlineQuery): AxiosPromise<OnlineVO[]> {
+	return request({
+		url: '/monitor/online/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 强退用户
+export function forceLogout(tokenId: string) {
+	return request({
+		url: '/monitor/online/' + tokenId,
+		method: 'delete'
+	});
+}

+ 15 - 0
src/api/monitor/online/types.ts

@@ -0,0 +1,15 @@
+export interface OnlineQuery extends PageQuery {
+	ipaddr: string;
+	userName: string;
+}
+
+export interface OnlineVO extends BaseEntity {
+	tokenId: string;
+	deptName: string;
+	userName: string;
+	ipaddr: string;
+	loginLocation: string;
+	browser: string;
+	os: string;
+	loginTime: number;
+}

+ 0 - 26
src/api/monitor/operlog.js

@@ -1,26 +0,0 @@
-import request from '@/utils/request'
-
-// 查询操作日志列表
-export function list(query) {
-  return request({
-    url: '/monitor/operlog/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 删除操作日志
-export function delOperlog(operId) {
-  return request({
-    url: '/monitor/operlog/' + operId,
-    method: 'delete'
-  })
-}
-
-// 清空操作日志
-export function cleanOperlog() {
-  return request({
-    url: '/monitor/operlog/clean',
-    method: 'delete'
-  })
-}

+ 28 - 0
src/api/monitor/operlog/index.ts

@@ -0,0 +1,28 @@
+import request from '@/utils/request';
+import { OperLogQuery, OperLogVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询操作日志列表
+export function list(query: OperLogQuery): AxiosPromise<OperLogVO[]> {
+	return request({
+		url: '/monitor/operlog/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 删除操作日志
+export function delOperlog(operId: string | number | Array<string | number>) {
+	return request({
+		url: '/monitor/operlog/' + operId,
+		method: 'delete'
+	});
+}
+
+// 清空操作日志
+export function cleanOperlog() {
+	return request({
+		url: '/monitor/operlog/clean',
+		method: 'delete'
+	});
+}

+ 52 - 0
src/api/monitor/operlog/types.ts

@@ -0,0 +1,52 @@
+export interface OperLogQuery extends PageQuery {
+	title: string;
+	operName: string;
+	businessType: string;
+	status: string;
+	orderByColumn: string;
+	isAsc: string;
+}
+
+export interface OperLogVO extends BaseEntity {
+	operId: string | number;
+	tenantId: string;
+	title: string;
+	businessType: number;
+	businessTypes: number[] | undefined;
+	method: string;
+	requestMethod: string;
+	operatorType: number;
+	operName: string;
+	deptName: string;
+	operUrl: string;
+	operIp: string;
+	operLocation: string;
+	operParam: string;
+	jsonResult: string;
+	status: number;
+	errorMsg: string;
+	operTime: string;
+	costTime: number;
+}
+
+export interface OperLogForm {
+	operId: number | string | undefined;
+	tenantId: string | number | undefined;
+	title: string;
+	businessType: number;
+	businessTypes: number[] | undefined;
+	method: string;
+	requestMethod: string;
+	operatorType: number;
+	operName: string;
+	deptName: string;
+	operUrl: string;
+	operIp: string;
+	operLocation: string;
+	operParam: string;
+	jsonResult: string;
+	status: number;
+	errorMsg: string;
+	operTime: string;
+	costTime: number;
+}

+ 0 - 72
src/api/system/config.js

@@ -1,72 +0,0 @@
-import request from '@/utils/request'
-
-// 查询参数列表
-export function listConfig(query) {
-  return request({
-    url: '/system/config/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询参数详细
-export function getConfig(configId) {
-  return request({
-    url: '/system/config/' + configId,
-    method: 'get'
-  })
-}
-
-// 根据参数键名查询参数值
-export function getConfigKey(configKey) {
-  return request({
-    url: '/system/config/configKey/' + configKey,
-    method: 'get'
-  })
-}
-
-// 新增参数配置
-export function addConfig(data) {
-  return request({
-    url: '/system/config',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改参数配置
-export function updateConfig(data) {
-  return request({
-    url: '/system/config',
-    method: 'put',
-    data: data
-  })
-}
-
-// 修改参数配置
-export function updateConfigByKey(key, value) {
-  return request({
-    url: '/system/config/updateByKey',
-    method: 'put',
-    data: {
-      configKey: key,
-      configValue: value
-    }
-  })
-}
-
-// 删除参数配置
-export function delConfig(configId) {
-  return request({
-    url: '/system/config/' + configId,
-    method: 'delete'
-  })
-}
-
-// 刷新参数缓存
-export function refreshCache() {
-  return request({
-    url: '/system/config/refreshCache',
-    method: 'delete'
-  })
-}

+ 74 - 0
src/api/system/config/index.ts

@@ -0,0 +1,74 @@
+import request from '@/utils/request';
+import { ConfigForm, ConfigQuery, ConfigVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询参数列表
+export function listConfig(query: ConfigQuery): AxiosPromise<ConfigVO[]> {
+	return request({
+		url: '/system/config/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 查询参数详细
+export function getConfig(configId: string | number): AxiosPromise<ConfigVO> {
+	return request({
+		url: '/system/config/' + configId,
+		method: 'get'
+	});
+}
+
+// 根据参数键名查询参数值
+export function getConfigKey(configKey: string): AxiosPromise<ConfigVO> {
+	return request({
+		url: '/system/config/configKey/' + configKey,
+		method: 'get'
+	});
+}
+
+// 新增参数配置
+export function addConfig(data: ConfigForm) {
+	return request({
+		url: '/system/config',
+		method: 'post',
+		data: data
+	});
+}
+
+// 修改参数配置
+export function updateConfig(data: ConfigForm) {
+	return request({
+		url: '/system/config',
+		method: 'put',
+		data: data
+	});
+}
+
+// 修改参数配置
+export function updateConfigByKey(key: string, value: any) {
+	return request({
+		url: '/system/config/updateByKey',
+		method: 'put',
+		data: {
+			configKey: key,
+			configValue: value
+		}
+	});
+}
+
+// 删除参数配置
+export function delConfig(configId: string | number | Array<string | number>) {
+	return request({
+		url: '/system/config/' + configId,
+		method: 'delete'
+	});
+}
+
+// 刷新参数缓存
+export function refreshCache() {
+	return request({
+		url: '/system/config/refreshCache',
+		method: 'delete'
+	});
+}

+ 23 - 0
src/api/system/config/types.ts

@@ -0,0 +1,23 @@
+export interface ConfigVO extends BaseEntity {
+	configId: number | string;
+	configName: string;
+	configKey: string;
+	configValue: string;
+	configType: string;
+	remark: string;
+}
+
+export interface ConfigForm {
+	configId: number | string | undefined;
+	configName: string;
+	configKey: string;
+	configValue: string;
+	configType: string;
+	remark: string;
+}
+
+export interface ConfigQuery extends PageQuery {
+	configName: string;
+	configKey: string;
+	configType: string;
+}

+ 0 - 52
src/api/system/dept.js

@@ -1,52 +0,0 @@
-import request from '@/utils/request'
-
-// 查询部门列表
-export function listDept(query) {
-  return request({
-    url: '/system/dept/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询部门列表(排除节点)
-export function listDeptExcludeChild(deptId) {
-  return request({
-    url: '/system/dept/list/exclude/' + deptId,
-    method: 'get'
-  })
-}
-
-// 查询部门详细
-export function getDept(deptId) {
-  return request({
-    url: '/system/dept/' + deptId,
-    method: 'get'
-  })
-}
-
-// 新增部门
-export function addDept(data) {
-  return request({
-    url: '/system/dept',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改部门
-export function updateDept(data) {
-  return request({
-    url: '/system/dept',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除部门
-export function delDept(deptId) {
-  return request({
-    url: '/system/dept/' + deptId,
-    method: 'delete'
-  })
-}

+ 62 - 0
src/api/system/dept/index.ts

@@ -0,0 +1,62 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { DeptForm, DeptQuery, DeptVO } from './types';
+
+// 查询部门列表
+export const listDept = (query?: DeptQuery) => {
+	return request({
+		url: '/system/dept/list',
+		method: 'get',
+		params: query
+	});
+};
+
+// 查询部门列表(排除节点)
+export const listDeptExcludeChild = (deptId: string | number): AxiosPromise<DeptVO[]> => {
+	return request({
+		url: '/system/dept/list/exclude/' + deptId,
+		method: 'get'
+	});
+};
+
+// 查询部门详细
+export const getDept = (deptId: string | number): AxiosPromise<DeptVO> => {
+	return request({
+		url: '/system/dept/' + deptId,
+		method: 'get'
+	});
+};
+
+// 查询部门下拉树结构
+export const treeselect = (): AxiosPromise<DeptVO[]> => {
+	return request({
+		url: '/system/dept/treeselect',
+		method: 'get'
+	});
+};
+
+// 新增部门
+export const addDept = (data: DeptForm) => {
+	return request({
+		url: '/system/dept',
+		method: 'post',
+		data: data
+	});
+};
+
+// 修改部门
+export const updateDept = (data: DeptForm) => {
+	return request({
+		url: '/system/dept',
+		method: 'put',
+		data: data
+	});
+};
+
+// 删除部门
+export const delDept = (deptId: number | string) => {
+	return request({
+		url: '/system/dept/' + deptId,
+		method: 'delete'
+	});
+};

+ 45 - 0
src/api/system/dept/types.ts

@@ -0,0 +1,45 @@
+/**
+ * 部门查询参数
+ */
+export interface DeptQuery extends PageQuery {
+	deptName?: string;
+	status?: number;
+}
+
+/**
+ * 部门类型
+ */
+export interface DeptVO extends BaseEntity {
+	id: number | string;
+	parentName: string;
+	parentId: number | string;
+	children: DeptVO[];
+	deptId: number | string;
+	deptName: string;
+	orderNum: number;
+	leader: string;
+	phone: string;
+	email: string;
+	status: string;
+	delFlag: string;
+	ancestors: string;
+	menuId: string | number;
+}
+
+/**
+ * 部门表单类型
+ */
+export interface DeptForm {
+	parentName?: string;
+	parentId?: number | string;
+	children?: DeptForm[];
+	deptId?: number | string;
+	deptName?: string;
+	orderNum?: number;
+	leader?: string;
+	phone?: string;
+	email?: string;
+	status?: string;
+	delFlag?: string;
+	ancestors?: string;
+}

+ 0 - 52
src/api/system/dict/data.js

@@ -1,52 +0,0 @@
-import request from '@/utils/request'
-
-// 查询字典数据列表
-export function listData(query) {
-  return request({
-    url: '/system/dict/data/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询字典数据详细
-export function getData(dictCode) {
-  return request({
-    url: '/system/dict/data/' + dictCode,
-    method: 'get'
-  })
-}
-
-// 根据字典类型查询字典数据信息
-export function getDicts(dictType) {
-  return request({
-    url: '/system/dict/data/type/' + dictType,
-    method: 'get'
-  })
-}
-
-// 新增字典数据
-export function addData(data) {
-  return request({
-    url: '/system/dict/data',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改字典数据
-export function updateData(data) {
-  return request({
-    url: '/system/dict/data',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除字典数据
-export function delData(dictCode) {
-  return request({
-    url: '/system/dict/data/' + dictCode,
-    method: 'delete'
-  })
-}

+ 53 - 0
src/api/system/dict/data/index.ts

@@ -0,0 +1,53 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { DictDataForm, DictDataQuery, DictDataVO } from './types';
+// 根据字典类型查询字典数据信息
+export function getDicts(dictType: string): AxiosPromise<DictDataVO[]> {
+	return request({
+		url: '/system/dict/data/type/' + dictType,
+		method: 'get'
+	});
+}
+
+// 查询字典数据列表
+export function listData(query: DictDataQuery): AxiosPromise<DictDataVO[]> {
+	return request({
+		url: '/system/dict/data/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 查询字典数据详细
+export function getData(dictCode: string | number): AxiosPromise<DictDataVO> {
+	return request({
+		url: '/system/dict/data/' + dictCode,
+		method: 'get'
+	});
+}
+
+// 新增字典数据
+export function addData(data: DictDataForm) {
+	return request({
+		url: '/system/dict/data',
+		method: 'post',
+		data: data
+	});
+}
+
+// 修改字典数据
+export function updateData(data: DictDataForm) {
+	return request({
+		url: '/system/dict/data',
+		method: 'put',
+		data: data
+	});
+}
+
+// 删除字典数据
+export function delData(dictCode: string | number | Array<string | number>) {
+	return request({
+		url: '/system/dict/data/' + dictCode,
+		method: 'delete'
+	});
+}

+ 29 - 0
src/api/system/dict/data/types.ts

@@ -0,0 +1,29 @@
+export interface DictDataQuery extends PageQuery {
+	dictName: string;
+	dictType: string;
+	status: string;
+	dictLabel: string;
+}
+
+export interface DictDataVO extends BaseEntity {
+	dictCode: string;
+	dictLabel: string;
+	dictValue: string;
+	cssClass: string;
+	listClass: ElTagType;
+	dictSort: number;
+	status: string;
+	remark: string;
+}
+
+export interface DictDataForm {
+	dictType?: string;
+	dictCode: string | undefined;
+	dictLabel: string;
+	dictValue: string;
+	cssClass: string;
+	listClass: ElTagType;
+	dictSort: number;
+	status: string;
+	remark: string;
+}

+ 0 - 60
src/api/system/dict/type.js

@@ -1,60 +0,0 @@
-import request from '@/utils/request'
-
-// 查询字典类型列表
-export function listType(query) {
-  return request({
-    url: '/system/dict/type/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询字典类型详细
-export function getType(dictId) {
-  return request({
-    url: '/system/dict/type/' + dictId,
-    method: 'get'
-  })
-}
-
-// 新增字典类型
-export function addType(data) {
-  return request({
-    url: '/system/dict/type',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改字典类型
-export function updateType(data) {
-  return request({
-    url: '/system/dict/type',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除字典类型
-export function delType(dictId) {
-  return request({
-    url: '/system/dict/type/' + dictId,
-    method: 'delete'
-  })
-}
-
-// 刷新字典缓存
-export function refreshCache() {
-  return request({
-    url: '/system/dict/type/refreshCache',
-    method: 'delete'
-  })
-}
-
-// 获取字典选择框列表
-export function optionselect() {
-  return request({
-    url: '/system/dict/type/optionselect',
-    method: 'get'
-  })
-}

+ 62 - 0
src/api/system/dict/type/index.ts

@@ -0,0 +1,62 @@
+import request from '@/utils/request';
+import { DictTypeForm, DictTypeVO, DictTypeQuery } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询字典类型列表
+export function listType(query: DictTypeQuery): AxiosPromise<DictTypeVO[]> {
+	return request({
+		url: '/system/dict/type/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 查询字典类型详细
+export function getType(dictId: number | string): AxiosPromise<DictTypeVO> {
+	return request({
+		url: '/system/dict/type/' + dictId,
+		method: 'get'
+	});
+}
+
+// 新增字典类型
+export function addType(data: DictTypeForm) {
+	return request({
+		url: '/system/dict/type',
+		method: 'post',
+		data: data
+	});
+}
+
+// 修改字典类型
+export function updateType(data: DictTypeForm) {
+	return request({
+		url: '/system/dict/type',
+		method: 'put',
+		data: data
+	});
+}
+
+// 删除字典类型
+export function delType(dictId: string | number | Array<string | number>) {
+	return request({
+		url: '/system/dict/type/' + dictId,
+		method: 'delete'
+	});
+}
+
+// 刷新字典缓存
+export function refreshCache() {
+	return request({
+		url: '/system/dict/type/refreshCache',
+		method: 'delete'
+	});
+}
+
+// 获取字典选择框列表
+export function optionselect(): AxiosPromise<DictTypeVO[]> {
+	return request({
+		url: '/system/dict/type/optionselect',
+		method: 'get'
+	});
+}

+ 21 - 0
src/api/system/dict/type/types.ts

@@ -0,0 +1,21 @@
+export interface DictTypeVO extends BaseEntity {
+	dictId: number | string;
+	dictName: string;
+	dictType: string;
+	status: string;
+	remark: string;
+}
+
+export interface DictTypeForm {
+	dictId: number | string | undefined;
+	dictName: string;
+	dictType: string;
+	status: string;
+	remark: string;
+}
+
+export interface DictTypeQuery extends PageQuery {
+	dictName: string;
+	dictType: string;
+	status: string;
+}

+ 0 - 68
src/api/system/menu.js

@@ -1,68 +0,0 @@
-import request from '@/utils/request'
-
-// 查询菜单列表
-export function listMenu(query) {
-  return request({
-    url: '/system/menu/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询菜单详细
-export function getMenu(menuId) {
-  return request({
-    url: '/system/menu/' + menuId,
-    method: 'get'
-  })
-}
-
-// 查询菜单下拉树结构
-export function treeselect() {
-  return request({
-    url: '/system/menu/treeselect',
-    method: 'get'
-  })
-}
-
-// 根据角色ID查询菜单下拉树结构
-export function roleMenuTreeselect(roleId) {
-  return request({
-    url: '/system/menu/roleMenuTreeselect/' + roleId,
-    method: 'get'
-  })
-}
-
-// 根据角色ID查询菜单下拉树结构
-export function tenantPackageMenuTreeselect(packageId) {
-  return request({
-    url: '/system/menu/tenantPackageMenuTreeselect/' + packageId,
-    method: 'get'
-  })
-}
-
-// 新增菜单
-export function addMenu(data) {
-  return request({
-    url: '/system/menu',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改菜单
-export function updateMenu(data) {
-  return request({
-    url: '/system/menu',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除菜单
-export function delMenu(menuId) {
-  return request({
-    url: '/system/menu/' + menuId,
-    method: 'delete'
-  })
-}

+ 70 - 0
src/api/system/menu/index.ts

@@ -0,0 +1,70 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { MenuQuery, MenuVO, MenuForm, MenuTreeOption, RoleMenuTree } from './types';
+
+// 查询菜单列表
+export const listMenu = (query?: MenuQuery): AxiosPromise<MenuVO[]> => {
+	return request({
+		url: '/system/menu/list',
+		method: 'get',
+		params: query
+	});
+};
+
+// 查询菜单详细
+export const getMenu = (menuId: string | number): AxiosPromise<MenuVO> => {
+	return request({
+		url: '/system/menu/' + menuId,
+		method: 'get'
+	});
+};
+
+// 查询菜单下拉树结构
+export const treeselect = (): AxiosPromise<MenuTreeOption[]> => {
+	return request({
+		url: '/system/menu/treeselect',
+		method: 'get'
+	});
+};
+
+// 根据角色ID查询菜单下拉树结构
+export const roleMenuTreeselect = (roleId: string | number): AxiosPromise<RoleMenuTree> => {
+	return request({
+		url: '/system/menu/roleMenuTreeselect/' + roleId,
+		method: 'get'
+	});
+};
+
+// 根据角色ID查询菜单下拉树结构
+export const tenantPackageMenuTreeselect = (packageId: string | number): AxiosPromise<RoleMenuTree> => {
+	return request({
+		url: '/system/menu/tenantPackageMenuTreeselect/' + packageId,
+		method: 'get'
+	});
+};
+
+// 新增菜单
+export const addMenu = (data: MenuForm) => {
+	return request({
+		url: '/system/menu',
+		method: 'post',
+		data: data
+	});
+};
+
+// 修改菜单
+export const updateMenu = (data: MenuForm) => {
+	return request({
+		url: '/system/menu',
+		method: 'put',
+		data: data
+	});
+};
+
+// 删除菜单
+export const delMenu = (menuId: string | number) => {
+	return request({
+		url: '/system/menu/' + menuId,
+		method: 'delete'
+	});
+};

+ 69 - 0
src/api/system/menu/types.ts

@@ -0,0 +1,69 @@
+import { MenuTypeEnum } from '@/enums/MenuTypeEnum';
+
+/**
+ * 菜单树形结构类型
+ */
+export interface MenuTreeOption {
+	id: string | number;
+	label: string;
+	parentId: string | number;
+	weight: number;
+	children?: MenuTreeOption[];
+}
+
+export interface RoleMenuTree {
+	menus: MenuTreeOption[];
+	checkedKeys: string[];
+}
+
+/**
+ * 菜单查询参数类型
+ */
+export interface MenuQuery {
+	keywords?: string;
+	menuName?: string;
+	status?: string;
+}
+
+/**
+ * 菜单视图对象类型
+ */
+export interface MenuVO extends BaseEntity {
+	parentName: string;
+	parentId: string | number;
+	children: MenuVO[];
+	menuId: string | number;
+	menuName: string;
+	orderNum: number;
+	path: string;
+	component: string;
+	queryParam: string;
+	isFrame: string;
+	isCache: string;
+	menuType: MenuTypeEnum;
+	visible: string;
+	status: string;
+	icon: string;
+	remark: string;
+}
+
+export interface MenuForm {
+	parentName?: string;
+	parentId?: string | number;
+	children?: MenuForm[];
+	menuId?: string | number;
+	menuName: string;
+	orderNum: number;
+	path: string;
+	component?: string;
+	queryParam?: string;
+	isFrame?: string;
+	isCache?: string;
+	menuType?: MenuTypeEnum;
+	visible?: string;
+	status?: string;
+	icon?: string;
+	remark?: string;
+	query?: string;
+	perms?: string;
+}

+ 0 - 44
src/api/system/notice.js

@@ -1,44 +0,0 @@
-import request from '@/utils/request'
-
-// 查询公告列表
-export function listNotice(query) {
-  return request({
-    url: '/system/notice/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询公告详细
-export function getNotice(noticeId) {
-  return request({
-    url: '/system/notice/' + noticeId,
-    method: 'get'
-  })
-}
-
-// 新增公告
-export function addNotice(data) {
-  return request({
-    url: '/system/notice',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改公告
-export function updateNotice(data) {
-  return request({
-    url: '/system/notice',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除公告
-export function delNotice(noticeId) {
-  return request({
-    url: '/system/notice/' + noticeId,
-    method: 'delete'
-  })
-}

+ 45 - 0
src/api/system/notice/index.ts

@@ -0,0 +1,45 @@
+import request from '@/utils/request';
+import { NoticeForm, NoticeQuery, NoticeVO } from './types';
+import { AxiosPromise } from 'axios';
+// 查询公告列表
+export function listNotice(query: NoticeQuery): AxiosPromise<NoticeVO[]> {
+	return request({
+		url: '/system/notice/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 查询公告详细
+export function getNotice(noticeId: string | number): AxiosPromise<NoticeVO> {
+	return request({
+		url: '/system/notice/' + noticeId,
+		method: 'get'
+	});
+}
+
+// 新增公告
+export function addNotice(data: NoticeForm) {
+	return request({
+		url: '/system/notice',
+		method: 'post',
+		data: data
+	});
+}
+
+// 修改公告
+export function updateNotice(data: NoticeForm) {
+	return request({
+		url: '/system/notice',
+		method: 'put',
+		data: data
+	});
+}
+
+// 删除公告
+export function delNotice(noticeId: string | number | Array<string | number>) {
+	return request({
+		url: '/system/notice/' + noticeId,
+		method: 'delete'
+	});
+}

+ 26 - 0
src/api/system/notice/types.ts

@@ -0,0 +1,26 @@
+export interface NoticeVO extends BaseEntity {
+	noticeId: number;
+	noticeTitle: string;
+	noticeType: string;
+	noticeContent: string;
+	status: string;
+	remark: string;
+	createByName: string;
+}
+
+export interface NoticeQuery extends PageQuery {
+	noticeTitle: string;
+	createByName: string;
+	status: string;
+	noticeType: string;
+}
+
+export interface NoticeForm {
+	noticeId: number | string | undefined;
+	noticeTitle: string;
+	noticeType: string;
+	noticeContent: string;
+	status: string;
+	remark: string;
+	createByName: string;
+}

+ 0 - 27
src/api/system/oss.js

@@ -1,27 +0,0 @@
-import request from '@/utils/request'
-
-// 查询OSS对象存储列表
-export function listOss(query) {
-  return request({
-    url: '/system/oss/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询OSS对象基于id串
-export function listByIds(ossId) {
-  return request({
-    url: '/system/oss/listByIds/' + ossId,
-    method: 'get'
-  })
-}
-
-// 删除OSS对象存储
-export function delOss(ossId) {
-  return request({
-    url: '/system/oss/' + ossId,
-    method: 'delete'
-  })
-}
-

+ 28 - 0
src/api/system/oss/index.ts

@@ -0,0 +1,28 @@
+import request from '@/utils/request';
+import { OssQuery, OssVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询OSS对象存储列表
+export function listOss(query: OssQuery): AxiosPromise<OssVO[]> {
+	return request({
+		url: '/system/oss/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 查询OSS对象基于id串
+export function listByIds(ossId: string | number): AxiosPromise<OssVO[]> {
+	return request({
+		url: '/system/oss/listByIds/' + ossId,
+		method: 'get'
+	});
+}
+
+// 删除OSS对象存储
+export function delOss(ossId: string | number | Array<string | number>) {
+	return request({
+		url: '/system/oss/' + ossId,
+		method: 'delete'
+	});
+}

+ 22 - 0
src/api/system/oss/types.ts

@@ -0,0 +1,22 @@
+export interface OssVO extends BaseEntity {
+	ossId: string | number;
+	fileName: string;
+	originalName: string;
+	fileSuffix: string;
+	url: string;
+	createByName: string;
+	service: string;
+}
+
+export interface OssQuery extends PageQuery {
+	fileName: string;
+	originalName: string;
+	fileSuffix: string;
+	createTime: string;
+	service: string;
+	orderByColumn: string;
+	isAsc: string;
+}
+export interface OssForm {
+	file: undefined | string;
+}

+ 0 - 58
src/api/system/ossConfig.js

@@ -1,58 +0,0 @@
-import request from '@/utils/request'
-
-// 查询对象存储配置列表
-export function listOssConfig(query) {
-  return request({
-    url: '/system/oss/config/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询对象存储配置详细
-export function getOssConfig(ossConfigId) {
-  return request({
-    url: '/system/oss/config/' + ossConfigId,
-    method: 'get'
-  })
-}
-
-// 新增对象存储配置
-export function addOssConfig(data) {
-  return request({
-    url: '/system/oss/config',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改对象存储配置
-export function updateOssConfig(data) {
-  return request({
-    url: '/system/oss/config',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除对象存储配置
-export function delOssConfig(ossConfigId) {
-  return request({
-    url: '/system/oss/config/' + ossConfigId,
-    method: 'delete'
-  })
-}
-
-// 对象存储状态修改
-export function changeOssConfigStatus(ossConfigId, status, configKey) {
-  const data = {
-    ossConfigId,
-    status,
-    configKey
-  }
-  return request({
-    url: '/system/oss/config/changeStatus',
-    method: 'put',
-    data: data
-  })
-}

+ 60 - 0
src/api/system/ossConfig/index.ts

@@ -0,0 +1,60 @@
+import request from '@/utils/request';
+import { OssConfigForm, OssConfigQuery, OssConfigVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询对象存储配置列表
+export function listOssConfig(query: OssConfigQuery): AxiosPromise<OssConfigVO[]> {
+	return request({
+		url: '/system/oss/config/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 查询对象存储配置详细
+export function getOssConfig(ossConfigId: string | number): AxiosPromise<OssConfigVO> {
+	return request({
+		url: '/system/oss/config/' + ossConfigId,
+		method: 'get'
+	});
+}
+
+// 新增对象存储配置
+export function addOssConfig(data: OssConfigForm) {
+	return request({
+		url: '/system/oss/config',
+		method: 'post',
+		data: data
+	});
+}
+
+// 修改对象存储配置
+export function updateOssConfig(data: OssConfigForm) {
+	return request({
+		url: '/system/oss/config',
+		method: 'put',
+		data: data
+	});
+}
+
+// 删除对象存储配置
+export function delOssConfig(ossConfigId: string | number | Array<string | number>) {
+	return request({
+		url: '/system/oss/config/' + ossConfigId,
+		method: 'delete'
+	});
+}
+
+// 对象存储状态修改
+export function changeOssConfigStatus(ossConfigId: string | number, status: string, configKey: string) {
+	const data = {
+		ossConfigId,
+		status,
+		configKey
+	};
+	return request({
+		url: '/system/oss/config/changeStatus',
+		method: 'put',
+		data: data
+	});
+}

+ 38 - 0
src/api/system/ossConfig/types.ts

@@ -0,0 +1,38 @@
+export interface OssConfigVO extends BaseEntity {
+	ossConfigId: number | string;
+	configKey: string;
+	accessKey: string;
+	secretKey: string;
+	bucketName: string;
+	prefix: string;
+	endpoint: string;
+	domain: string;
+	isHttps: string;
+	region: string;
+	status: string;
+	ext1: string;
+	remark: string;
+	accessPolicy: string;
+}
+
+export interface OssConfigQuery extends PageQuery {
+	configKey: string;
+	bucketName: string;
+	status: string;
+}
+
+export interface OssConfigForm {
+	ossConfigId: string | number | undefined;
+	configKey: string;
+	accessKey: string;
+	secretKey: string;
+	bucketName: string;
+	prefix: string;
+	endpoint: string;
+	domain: string;
+	isHttps: string;
+	accessPolicy: string;
+	region: string;
+	status: string;
+	remark: string;
+}

+ 0 - 44
src/api/system/post.js

@@ -1,44 +0,0 @@
-import request from '@/utils/request'
-
-// 查询岗位列表
-export function listPost(query) {
-  return request({
-    url: '/system/post/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询岗位详细
-export function getPost(postId) {
-  return request({
-    url: '/system/post/' + postId,
-    method: 'get'
-  })
-}
-
-// 新增岗位
-export function addPost(data) {
-  return request({
-    url: '/system/post',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改岗位
-export function updatePost(data) {
-  return request({
-    url: '/system/post',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除岗位
-export function delPost(postId) {
-  return request({
-    url: '/system/post/' + postId,
-    method: 'delete'
-  })
-}

+ 46 - 0
src/api/system/post/index.ts

@@ -0,0 +1,46 @@
+import request from '@/utils/request';
+import { PostForm, PostQuery, PostVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询岗位列表
+export function listPost(query: PostQuery): AxiosPromise<PostVO[]> {
+	return request({
+		url: '/system/post/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 查询岗位详细
+export function getPost(postId: string | number): AxiosPromise<PostVO> {
+	return request({
+		url: '/system/post/' + postId,
+		method: 'get'
+	});
+}
+
+// 新增岗位
+export function addPost(data: PostForm) {
+	return request({
+		url: '/system/post',
+		method: 'post',
+		data: data
+	});
+}
+
+// 修改岗位
+export function updatePost(data: PostForm) {
+	return request({
+		url: '/system/post',
+		method: 'put',
+		data: data
+	});
+}
+
+// 删除岗位
+export function delPost(postId: string | number | (string | number)[]) {
+	return request({
+		url: '/system/post/' + postId,
+		method: 'delete'
+	});
+}

+ 23 - 0
src/api/system/post/types.ts

@@ -0,0 +1,23 @@
+export interface PostVO extends BaseEntity {
+	postId: number | string;
+	postCode: string;
+	postName: string;
+	postSort: number;
+	status: string;
+	remark: string;
+}
+
+export interface PostForm {
+	postId: number | string | undefined;
+	postCode: string;
+	postName: string;
+	postSort: number;
+	status: string;
+	remark: string;
+}
+
+export interface PostQuery extends PageQuery {
+	postCode: string;
+	postName: string;
+	status: string;
+}

+ 0 - 119
src/api/system/role.js

@@ -1,119 +0,0 @@
-import request from '@/utils/request'
-
-// 查询角色列表
-export function listRole(query) {
-  return request({
-    url: '/system/role/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询角色详细
-export function getRole(roleId) {
-  return request({
-    url: '/system/role/' + roleId,
-    method: 'get'
-  })
-}
-
-// 新增角色
-export function addRole(data) {
-  return request({
-    url: '/system/role',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改角色
-export function updateRole(data) {
-  return request({
-    url: '/system/role',
-    method: 'put',
-    data: data
-  })
-}
-
-// 角色数据权限
-export function dataScope(data) {
-  return request({
-    url: '/system/role/dataScope',
-    method: 'put',
-    data: data
-  })
-}
-
-// 角色状态修改
-export function changeRoleStatus(roleId, status) {
-  const data = {
-    roleId,
-    status
-  }
-  return request({
-    url: '/system/role/changeStatus',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除角色
-export function delRole(roleId) {
-  return request({
-    url: '/system/role/' + roleId,
-    method: 'delete'
-  })
-}
-
-// 查询角色已授权用户列表
-export function allocatedUserList(query) {
-  return request({
-    url: '/system/role/authUser/allocatedList',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询角色未授权用户列表
-export function unallocatedUserList(query) {
-  return request({
-    url: '/system/role/authUser/unallocatedList',
-    method: 'get',
-    params: query
-  })
-}
-
-// 取消用户授权角色
-export function authUserCancel(data) {
-  return request({
-    url: '/system/role/authUser/cancel',
-    method: 'put',
-    data: data
-  })
-}
-
-// 批量取消用户授权角色
-export function authUserCancelAll(data) {
-  return request({
-    url: '/system/role/authUser/cancelAll',
-    method: 'put',
-    params: data
-  })
-}
-
-// 授权用户选择
-export function authUserSelectAll(data) {
-  return request({
-    url: '/system/role/authUser/selectAll',
-    method: 'put',
-    params: data
-  })
-}
-
-// 根据角色ID查询部门树结构
-export function deptTreeSelect(roleId) {
-  return request({
-    url: '/system/role/deptTree/' + roleId,
-    method: 'get'
-  })
-}

+ 144 - 0
src/api/system/role/index.ts

@@ -0,0 +1,144 @@
+import { UserVO } from '@/api/system/user/types';
+import { UserQuery } from '@/api/system/user/types';
+import { AxiosPromise } from 'axios';
+import { RoleQuery, RoleVO, RoleDeptTree } from './types';
+import request from '@/utils/request';
+
+export const listRole = (query: RoleQuery): AxiosPromise<RoleVO[]> => {
+	return request({
+		url: '/system/role/list',
+		method: 'get',
+		params: query
+	});
+};
+
+/**
+ * 查询角色详细
+ */
+export const getRole = (roleId: string | number): AxiosPromise<RoleVO> => {
+	return request({
+		url: '/system/role/' + roleId,
+		method: 'get'
+	});
+};
+
+/**
+ * 新增角色
+ */
+export const addRole = (data: any) => {
+	return request({
+		url: '/system/role',
+		method: 'post',
+		data: data
+	});
+};
+
+/**
+ * 修改角色
+ * @param data
+ */
+export const updateRole = (data: any) => {
+	return request({
+		url: '/system/role',
+		method: 'put',
+		data: data
+	});
+};
+
+/**
+ * 角色数据权限
+ */
+export const dataScope = (data: any) => {
+	return request({
+		url: '/system/role/dataScope',
+		method: 'put',
+		data: data
+	});
+};
+
+/**
+ * 角色状态修改
+ */
+export const changeRoleStatus = (roleId: string | number, status: string) => {
+	const data = {
+		roleId,
+		status
+	};
+	return request({
+		url: '/system/role/changeStatus',
+		method: 'put',
+		data: data
+	});
+};
+
+/**
+ * 删除角色
+ */
+export const delRole = (roleId: Array<string | number> | string | number) => {
+	return request({
+		url: '/system/role/' + roleId,
+		method: 'delete'
+	});
+};
+
+/**
+ * 查询角色已授权用户列表
+ */
+export const allocatedUserList = (query: UserQuery): AxiosPromise<UserVO[]> => {
+	return request({
+		url: '/system/role/authUser/allocatedList',
+		method: 'get',
+		params: query
+	});
+};
+
+/**
+ * 查询角色未授权用户列表
+ */
+export const unallocatedUserList = (query: UserQuery): AxiosPromise<UserVO[]> => {
+	return request({
+		url: '/system/role/authUser/unallocatedList',
+		method: 'get',
+		params: query
+	});
+};
+
+/**
+ * 取消用户授权角色
+ */
+export const authUserCancel = (data: any) => {
+	return request({
+		url: '/system/role/authUser/cancel',
+		method: 'put',
+		data: data
+	});
+};
+
+/**
+ * 批量取消用户授权角色
+ */
+export const authUserCancelAll = (data: any) => {
+	return request({
+		url: '/system/role/authUser/cancelAll',
+		method: 'put',
+		params: data
+	});
+};
+
+/**
+ * 授权用户选择
+ */
+export const authUserSelectAll = (data: any) => {
+	return request({
+		url: '/system/role/authUser/selectAll',
+		method: 'put',
+		params: data
+	});
+};
+// 根据角色ID查询部门树结构
+export const deptTreeSelect = (roleId: string | number): AxiosPromise<RoleDeptTree> => {
+	return request({
+		url: '/system/role/deptTree/' + roleId,
+		method: 'get'
+	});
+};

+ 52 - 0
src/api/system/role/types.ts

@@ -0,0 +1,52 @@
+/**
+ * 菜单树形结构类型
+ */
+export interface DeptTreeOption {
+	id: string;
+	label: string;
+	parentId: string;
+	weight: number;
+	children?: DeptTreeOption[];
+}
+
+export interface RoleDeptTree {
+	checkedKeys: string[];
+	depts: DeptTreeOption[];
+}
+
+export interface RoleVO extends BaseEntity {
+	roleId: string | number;
+	roleName: string;
+	roleKey: string;
+	roleSort: number;
+	dataScope: string;
+	menuCheckStrictly: boolean;
+	deptCheckStrictly: boolean;
+	status: string;
+	delFlag: string;
+	remark?: any;
+	flag: boolean;
+	menuIds?: Array<string | number>;
+	deptIds?: Array<string | number>;
+	admin: boolean;
+}
+
+export interface RoleQuery extends PageQuery {
+	roleName: string;
+	roleKey: string;
+	status: string;
+}
+
+export interface RoleForm {
+	roleName: string;
+	roleKey: string;
+	roleSort: number;
+	status: string;
+	menuCheckStrictly: boolean;
+	deptCheckStrictly: boolean;
+	remark: string;
+	dataScope?: number;
+	roleId: string | undefined;
+	menuIds: Array<string | number>;
+	deptIds: Array<string | number>;
+}

+ 0 - 88
src/api/system/tenant.js

@@ -1,88 +0,0 @@
-import request from '@/utils/request'
-
-// 查询租户列表
-export function listTenant(query) {
-  return request({
-    url: '/system/tenant/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询租户详细
-export function getTenant(id) {
-  return request({
-    url: '/system/tenant/' + id,
-    method: 'get'
-  })
-}
-
-// 新增租户
-export function addTenant(data) {
-  return request({
-    url: '/system/tenant',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改租户
-export function updateTenant(data) {
-  return request({
-    url: '/system/tenant',
-    method: 'put',
-    data: data
-  })
-}
-
-// 租户状态修改
-export function changeTenantStatus(id, tenantId, status) {
-  const data = {
-    id,
-    tenantId,
-    status
-  }
-  return request({
-    url: '/system/tenant/changeStatus',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除租户
-export function delTenant(id) {
-  return request({
-    url: '/system/tenant/' + id,
-    method: 'delete'
-  })
-}
-
-// 动态切换租户
-export function dynamicTenant(tenantId) {
-  return request({
-    url: '/system/tenant/dynamic/' + tenantId,
-    method: 'get'
-  })
-}
-
-// 清除动态租户
-export function dynamicClear() {
-  return request({
-    url: '/system/tenant/dynamic/clear',
-    method: 'get'
-  })
-}
-
-// 同步租户套餐
-export function syncTenantPackage(tenantId, packageId) {
-  const data = {
-    tenantId,
-    packageId
-  }
-  return request({
-    url: '/system/tenant/syncTenantPackage',
-    method: 'get',
-    params: data
-  })
-}
-

+ 89 - 0
src/api/system/tenant/index.ts

@@ -0,0 +1,89 @@
+import request from '@/utils/request';
+import { TenantForm, TenantQuery, TenantVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询租户列表
+export function listTenant(query: TenantQuery): AxiosPromise<TenantVO[]> {
+	return request({
+		url: '/system/tenant/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 查询租户详细
+export function getTenant(id: string | number): AxiosPromise<TenantVO> {
+	return request({
+		url: '/system/tenant/' + id,
+		method: 'get'
+	});
+}
+
+// 新增租户
+export function addTenant(data: TenantForm) {
+	return request({
+		url: '/system/tenant',
+		method: 'post',
+		data: data
+	});
+}
+
+// 修改租户
+export function updateTenant(data: TenantForm) {
+	return request({
+		url: '/system/tenant',
+		method: 'put',
+		data: data
+	});
+}
+
+// 租户状态修改
+export function changeTenantStatus(id: string | number, tenantId: string | number, status: string) {
+	const data = {
+		id,
+		tenantId,
+		status
+	};
+	return request({
+		url: '/system/tenant/changeStatus',
+		method: 'put',
+		data: data
+	});
+}
+
+// 删除租户
+export function delTenant(id: string | number | Array<string | number>) {
+	return request({
+		url: '/system/tenant/' + id,
+		method: 'delete'
+	});
+}
+
+// 动态切换租户
+export function dynamicTenant(tenantId: string | number) {
+	return request({
+		url: '/system/tenant/dynamic/' + tenantId,
+		method: 'get'
+	});
+}
+
+// 清除动态租户
+export function dynamicClear() {
+	return request({
+		url: '/system/tenant/dynamic/clear',
+		method: 'get'
+	});
+}
+
+// 同步租户套餐
+export function syncTenantPackage(tenantId: string | number, packageId: string | number) {
+	const data = {
+		tenantId,
+		packageId
+	};
+	return request({
+		url: '/system/tenant/syncTenantPackage',
+		method: 'get',
+		params: data
+	});
+}

+ 46 - 0
src/api/system/tenant/types.ts

@@ -0,0 +1,46 @@
+export interface TenantVO extends BaseEntity {
+	id: number | string;
+	tenantId: number | string;
+	username: string;
+	contactUserName: string;
+	contactPhone: string;
+	companyName: string;
+	licenseNumber: string;
+	address: string;
+	domain: string;
+	intro: string;
+	remark: string;
+	packageId: string | number;
+	expireTime: string;
+	accountCount: number;
+	status: string;
+}
+
+export interface TenantQuery extends PageQuery {
+	tenantId: string | number;
+
+	contactUserName: string;
+
+	contactPhone: string;
+
+	companyName: string;
+}
+
+export interface TenantForm {
+	id: number | string | undefined;
+	tenantId: number | string | undefined;
+	username: string;
+	password: string;
+	contactUserName: string;
+	contactPhone: string;
+	companyName: string;
+	licenseNumber: string;
+	domain: string;
+	address: string;
+	intro: string;
+	remark: string;
+	packageId: string | number;
+	expireTime: string;
+	accountCount: number;
+	status: string;
+}

+ 0 - 58
src/api/system/tenantPackage.js

@@ -1,58 +0,0 @@
-import request from '@/utils/request'
-
-// 查询租户套餐列表
-export function listTenantPackage(query) {
-  return request({
-    url: '/system/tenant/package/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询租户套餐详细
-export function getTenantPackage(packageId) {
-  return request({
-    url: '/system/tenant/package/' + packageId,
-    method: 'get'
-  })
-}
-
-// 新增租户套餐
-export function addTenantPackage(data) {
-  return request({
-    url: '/system/tenant/package',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改租户套餐
-export function updateTenantPackage(data) {
-  return request({
-    url: '/system/tenant/package',
-    method: 'put',
-    data: data
-  })
-}
-
-// 租户套餐状态修改
-export function changePackageStatus(packageId, status) {
-  const data = {
-    packageId,
-    status
-  }
-  return request({
-    url: '/system/tenant/package/changeStatus',
-    method: 'put',
-    data: data
-  })
-}
-
-
-// 删除租户套餐
-export function delTenantPackage(packageId) {
-  return request({
-    url: '/system/tenant/package/' + packageId,
-    method: 'delete'
-  })
-}

+ 59 - 0
src/api/system/tenantPackage/index.ts

@@ -0,0 +1,59 @@
+import request from '@/utils/request';
+import { TenantPkgForm, TenantPkgQuery, TenantPkgVO } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询租户套餐列表
+export function listTenantPackage(query?: TenantPkgQuery): AxiosPromise<TenantPkgVO[]> {
+	return request({
+		url: '/system/tenant/package/list',
+		method: 'get',
+		params: query
+	});
+}
+
+// 查询租户套餐详细
+export function getTenantPackage(packageId: string | number): AxiosPromise<TenantPkgVO> {
+	return request({
+		url: '/system/tenant/package/' + packageId,
+		method: 'get'
+	});
+}
+
+// 新增租户套餐
+export function addTenantPackage(data: TenantPkgForm) {
+	return request({
+		url: '/system/tenant/package',
+		method: 'post',
+		data: data
+	});
+}
+
+// 修改租户套餐
+export function updateTenantPackage(data: TenantPkgForm) {
+	return request({
+		url: '/system/tenant/package',
+		method: 'put',
+		data: data
+	});
+}
+
+// 租户套餐状态修改
+export function changePackageStatus(packageId: number | string, status: string) {
+	const data = {
+		packageId,
+		status
+	};
+	return request({
+		url: '/system/tenant/package/changeStatus',
+		method: 'put',
+		data: data
+	});
+}
+
+// 删除租户套餐
+export function delTenantPackage(packageId: string | number | Array<string | number>) {
+	return request({
+		url: '/system/tenant/package/' + packageId,
+		method: 'delete'
+	});
+}

+ 22 - 0
src/api/system/tenantPackage/types.ts

@@ -0,0 +1,22 @@
+export interface TenantPkgVO extends BaseEntity {
+	packageId: string | number;
+	packageName: string;
+	menuIds: string;
+	remark: string;
+	menuCheckStrictly: boolean;
+	status: string;
+}
+
+export interface TenantPkgQuery extends PageQuery {
+	packageName: string;
+	status: string;
+}
+
+export interface TenantPkgForm {
+	packageId: string | number | undefined;
+	packageName: string;
+	menuIds: string;
+	remark: string;
+	menuCheckStrictly: boolean;
+	status: string;
+}

+ 0 - 135
src/api/system/user.js

@@ -1,135 +0,0 @@
-import request from '@/utils/request'
-import { parseStrEmpty } from "@/utils/ruoyi";
-
-// 查询用户列表
-export function listUser(query) {
-  return request({
-    url: '/system/user/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询用户详细
-export function getUser(userId) {
-  return request({
-    url: '/system/user/' + parseStrEmpty(userId),
-    method: 'get'
-  })
-}
-
-// 新增用户
-export function addUser(data) {
-  return request({
-    url: '/system/user',
-    method: 'post',
-    data: data
-  })
-}
-
-// 修改用户
-export function updateUser(data) {
-  return request({
-    url: '/system/user',
-    method: 'put',
-    data: data
-  })
-}
-
-// 删除用户
-export function delUser(userId) {
-  return request({
-    url: '/system/user/' + userId,
-    method: 'delete'
-  })
-}
-
-// 用户密码重置
-export function resetUserPwd(userId, password) {
-  const data = {
-    userId,
-    password
-  }
-  return request({
-    url: '/system/user/resetPwd',
-    method: 'put',
-    data: data
-  })
-}
-
-// 用户状态修改
-export function changeUserStatus(userId, status) {
-  const data = {
-    userId,
-    status
-  }
-  return request({
-    url: '/system/user/changeStatus',
-    method: 'put',
-    data: data
-  })
-}
-
-// 查询用户个人信息
-export function getUserProfile() {
-  return request({
-    url: '/system/user/profile',
-    method: 'get'
-  })
-}
-
-// 修改用户个人信息
-export function updateUserProfile(data) {
-  return request({
-    url: '/system/user/profile',
-    method: 'put',
-    data: data
-  })
-}
-
-// 用户密码重置
-export function updateUserPwd(oldPassword, newPassword) {
-  const data = {
-    oldPassword,
-    newPassword
-  }
-  return request({
-    url: '/system/user/profile/updatePwd',
-    method: 'put',
-    params: data
-  })
-}
-
-// 用户头像上传
-export function uploadAvatar(data) {
-  return request({
-    url: '/system/user/profile/avatar',
-    method: 'post',
-    data: data
-  })
-}
-
-// 查询授权角色
-export function getAuthRole(userId) {
-  return request({
-    url: '/system/user/authRole/' + userId,
-    method: 'get'
-  })
-}
-
-// 保存授权角色
-export function updateAuthRole(data) {
-  return request({
-    url: '/system/user/authRole',
-    method: 'put',
-    params: data
-  })
-}
-
-// 查询部门下拉树结构
-export function deptTreeSelect() {
-  return request({
-    url: '/system/user/deptTree',
-    method: 'get'
-  })
-}

+ 180 - 0
src/api/system/user/index.ts

@@ -0,0 +1,180 @@
+import { DeptVO } from './../dept/types';
+import { RoleVO } from '@/api/system/role/types';
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { UserForm, UserQuery, UserVO, UserInfoVO } from './types';
+import { parseStrEmpty } from '@/utils/ruoyi';
+
+/**
+ * 查询用户列表
+ * @param query
+ */
+export function listUser(query: UserQuery): AxiosPromise<UserVO[]> {
+	return request({
+		url: '/system/user/list',
+		method: 'get',
+		params: query
+	});
+}
+
+/**
+ * 获取用户详情
+ * @param userId
+ */
+export function getUser(userId?: string | number): AxiosPromise<UserInfoVO> {
+	return request({
+		url: '/system/user/' + parseStrEmpty(userId),
+		method: 'get'
+	});
+}
+
+/**
+ * 新增用户
+ */
+export function addUser(data: UserForm) {
+	return request({
+		url: '/system/user',
+		method: 'post',
+		data: data
+	});
+}
+
+/**
+ * 修改用户
+ */
+export function updateUser(data: UserForm) {
+	return request({
+		url: '/system/user',
+		method: 'put',
+		data: data
+	});
+}
+
+/**
+ * 删除用户
+ * @param userId 用户ID
+ */
+export function delUser(userId: Array<string | number> | string | number) {
+	return request({
+		url: '/system/user/' + userId,
+		method: 'delete'
+	});
+}
+
+/**
+ * 用户密码重置
+ * @param userId 用户ID
+ * @param password 密码
+ */
+export function resetUserPwd(userId: string | number, password: string) {
+	const data = {
+		userId,
+		password
+	};
+	return request({
+		url: '/system/user/resetPwd',
+		method: 'put',
+		data: data
+	});
+}
+
+/**
+ * 用户状态修改
+ * @param userId 用户ID
+ * @param status 用户状态
+ */
+export function changeUserStatus(userId: number | string, status: string) {
+	const data = {
+		userId,
+		status
+	};
+	return request({
+		url: '/system/user/changeStatus',
+		method: 'put',
+		data: data
+	});
+}
+
+/**
+ * 查询用户个人信息
+ */
+export function getUserProfile(): AxiosPromise<UserInfoVO> {
+	return request({
+		url: '/system/user/profile',
+		method: 'get'
+	});
+}
+
+/**
+ * 修改用户个人信息
+ * @param data 用户信息
+ */
+export function updateUserProfile(data: UserForm) {
+	return request({
+		url: '/system/user/profile',
+		method: 'put',
+		data: data
+	});
+}
+
+/**
+ * 用户密码重置
+ * @param oldPassword 旧密码
+ * @param newPassword 新密码
+ */
+export function updateUserPwd(oldPassword: string, newPassword: string) {
+	const data = {
+		oldPassword,
+		newPassword
+	};
+	return request({
+		url: '/system/user/profile/updatePwd',
+		method: 'put',
+		params: data
+	});
+}
+
+/**
+ * 用户头像上传
+ * @param data 头像文件
+ */
+export function uploadAvatar(data: FormData) {
+	return request({
+		url: '/system/user/profile/avatar',
+		method: 'post',
+		data: data
+	});
+}
+
+/**
+ * 查询授权角色
+ * @param userId 用户ID
+ */
+export function getAuthRole(userId: string | number): AxiosPromise<{ user: UserVO; roles: RoleVO[] }> {
+	return request({
+		url: '/system/user/authRole/' + userId,
+		method: 'get'
+	});
+}
+
+/**
+ * 保存授权角色
+ * @param data 用户ID
+ */
+export function updateAuthRole(data: { userId: string; roleIds: string }) {
+	return request({
+		url: '/system/user/authRole',
+		method: 'put',
+		params: data
+	});
+}
+
+/**
+ * 查询部门下拉树结构
+ */
+export function deptTreeSelect(): AxiosPromise<DeptVO[]> {
+	return request({
+		url: '/system/user/deptTree',
+		method: 'get'
+	});
+}

+ 84 - 0
src/api/system/user/types.ts

@@ -0,0 +1,84 @@
+import { DeptVO } from './../dept/types';
+import { RoleVO } from '@/api/system/role/types';
+import { PostVO } from '@/api/system/post/types';
+
+/**
+ * 用户信息
+ */
+export interface UserInfo {
+	user: UserVO;
+	roles: string[];
+	permissions: string[];
+}
+
+/**
+ * 用户查询对象类型
+ */
+export interface UserQuery extends PageQuery {
+	userName?: string;
+	phonenumber?: string;
+	status?: string;
+	deptId?: string | number;
+	roleId?: string | number;
+}
+
+/**
+ * 用户返回对象
+ */
+export interface UserVO extends BaseEntity {
+	userId: string | number;
+	deptId: number;
+	userName: string;
+	nickName: string;
+	userType: string;
+	email: string;
+	phonenumber: string;
+	sex: string;
+	avatar: string;
+	status: string;
+	delFlag: string;
+	loginIp: string;
+	loginDate: string;
+	remark: string;
+	dept: DeptVO;
+	roles: RoleVO[];
+	roleIds: any;
+	postIds: any;
+	roleId: any;
+	admin: boolean;
+}
+
+/**
+ * 用户表单类型
+ */
+export interface UserForm {
+	id?: string;
+	userId?: string;
+	deptId?: number;
+	userName: string;
+	nickName?: string;
+	password: string;
+	phonenumber?: string;
+	email?: string;
+	sex?: string;
+	status: string;
+	remark?: string;
+	postIds: string[];
+	roleIds: string[];
+}
+
+export interface UserInfoVO {
+	user: UserVO;
+	roles: RoleVO[];
+	roleIds: string[];
+	posts: PostVO[];
+	postIds: string[];
+	roleGroup: string;
+	postGroup: string;
+}
+
+export interface ResetPwdForm {
+	oldPassword: string;
+	newPassword: string;
+	confirmPassword: string;
+}

+ 0 - 85
src/api/tool/gen.js

@@ -1,85 +0,0 @@
-import request from '@/utils/request'
-
-// 查询生成表数据
-export function listTable(query) {
-  return request({
-    headers: { 'datasource': localStorage.getItem("dataName") },
-    url: '/tool/gen/list',
-    method: 'get',
-    params: query
-  })
-}
-// 查询db数据库列表
-export function listDbTable(query) {
-  return request({
-    headers: { 'datasource': localStorage.getItem("dataName") },
-    url: '/tool/gen/db/list',
-    method: 'get',
-    params: query
-  })
-}
-
-// 查询表详细信息
-export function getGenTable(tableId) {
-  return request({
-    headers: { 'datasource': localStorage.getItem("dataName") },
-    url: '/tool/gen/' + tableId,
-    method: 'get'
-  })
-}
-
-// 修改代码生成信息
-export function updateGenTable(data) {
-  return request({
-    headers: { 'datasource': localStorage.getItem("dataName") },
-    url: '/tool/gen',
-    method: 'put',
-    data: data
-  })
-}
-
-// 导入表
-export function importTable(data) {
-  return request({
-    headers: { 'datasource': localStorage.getItem("dataName") },
-    url: '/tool/gen/importTable',
-    method: 'post',
-    params: data
-  })
-}
-
-// 预览生成代码
-export function previewTable(tableId) {
-  return request({
-    headers: { 'datasource': localStorage.getItem("dataName") },
-    url: '/tool/gen/preview/' + tableId,
-    method: 'get'
-  })
-}
-
-// 删除表数据
-export function delTable(tableId) {
-  return request({
-    headers: { 'datasource': localStorage.getItem("dataName") },
-    url: '/tool/gen/' + tableId,
-    method: 'delete'
-  })
-}
-
-// 生成代码(自定义路径)
-export function genCode(tableName) {
-  return request({
-    headers: { 'datasource': localStorage.getItem("dataName") },
-    url: '/tool/gen/genCode/' + tableName,
-    method: 'get'
-  })
-}
-
-// 同步数据库
-export function synchDb(tableName) {
-  return request({
-    headers: { 'datasource': localStorage.getItem("dataName") },
-    url: '/tool/gen/synchDb/' + tableName,
-    method: 'get'
-  })
-}

+ 87 - 0
src/api/tool/gen/index.ts

@@ -0,0 +1,87 @@
+import request from '@/utils/request';
+import { DbTableQuery, DbTableVO, TableQuery, TableVO, GenTableVO, DbTableForm } from './types';
+import { AxiosPromise } from 'axios';
+
+// 查询生成表数据
+export const listTable = (query: TableQuery): AxiosPromise<TableVO[]> => {
+	return request({
+		headers: { datasource: localStorage.getItem('dataName') },
+		url: '/tool/gen/list',
+		method: 'get',
+		params: query
+	});
+};
+// 查询db数据库列表
+export const listDbTable = (query: DbTableQuery): AxiosPromise<DbTableVO[]> => {
+	return request({
+		headers: { datasource: localStorage.getItem('dataName') },
+		url: '/tool/gen/db/list',
+		method: 'get',
+		params: query
+	});
+};
+
+// 查询表详细信息
+export const getGenTable = (tableId: string | number): AxiosPromise<GenTableVO> => {
+	return request({
+		headers: { datasource: localStorage.getItem('dataName') },
+		url: '/tool/gen/' + tableId,
+		method: 'get'
+	});
+};
+
+// 修改代码生成信息
+export const updateGenTable = (data: DbTableForm) => {
+	return request({
+		headers: { datasource: localStorage.getItem('dataName') },
+		url: '/tool/gen',
+		method: 'put',
+		data: data
+	});
+};
+
+// 导入表
+export const importTable = (data: { tables: string }) => {
+	return request({
+		headers: { datasource: localStorage.getItem('dataName') },
+		url: '/tool/gen/importTable',
+		method: 'post',
+		params: data
+	});
+};
+
+// 预览生成代码
+export const previewTable = (tableId: string | number) => {
+	return request({
+		headers: { datasource: localStorage.getItem('dataName') },
+		url: '/tool/gen/preview/' + tableId,
+		method: 'get'
+	});
+};
+
+// 删除表数据
+export const delTable = (tableId: string | number | Array<string | number>) => {
+	return request({
+		headers: { datasource: localStorage.getItem('dataName') },
+		url: '/tool/gen/' + tableId,
+		method: 'delete'
+	});
+};
+
+// 生成代码(自定义路径)
+export const genCode = (tableName: string) => {
+	return request({
+		headers: { datasource: localStorage.getItem('dataName') },
+		url: '/tool/gen/genCode/' + tableName,
+		method: 'get'
+	});
+};
+
+// 同步数据库
+export const synchDb = (tableName: string) => {
+	return request({
+		headers: { datasource: localStorage.getItem('dataName') },
+		url: '/tool/gen/synchDb/' + tableName,
+		method: 'get'
+	});
+};

+ 178 - 0
src/api/tool/gen/types.ts

@@ -0,0 +1,178 @@
+export interface TableVO extends BaseEntity {
+	createDept: number | string;
+	tableId: string | number;
+	tableName: string;
+	tableComment: string;
+	subTableName?: any;
+	subTableFkName?: any;
+	className: string;
+	tplCategory: string;
+	packageName: string;
+	moduleName: string;
+	businessName: string;
+	functionName: string;
+	functionAuthor: string;
+	genType: string;
+	genPath: string;
+	pkColumn?: any;
+	columns?: any;
+	options?: any;
+	remark?: any;
+	treeCode?: any;
+	treeParentCode?: any;
+	treeName?: any;
+	menuIds?: any;
+	parentMenuId?: any;
+	parentMenuName?: any;
+	tree: boolean;
+	crud: boolean;
+}
+
+export interface TableQuery extends PageQuery {
+	tableName: string;
+	tableComment: string;
+	dataName: string;
+}
+
+export interface DbColumnVO extends BaseEntity {
+	createDept?: any;
+	columnId?: any;
+	tableId?: any;
+	columnName?: any;
+	columnComment?: any;
+	columnType?: any;
+	javaType?: any;
+	javaField?: any;
+	isPk?: any;
+	isIncrement?: any;
+	isRequired?: any;
+	isInsert?: any;
+	isEdit?: any;
+	isList?: any;
+	isQuery?: any;
+	queryType?: any;
+	htmlType?: any;
+	dictType?: any;
+	sort?: any;
+	increment: boolean;
+	capJavaField?: any;
+	usableColumn: boolean;
+	superColumn: boolean;
+	list: boolean;
+	pk: boolean;
+	insert: boolean;
+	edit: boolean;
+	query: boolean;
+	required: boolean;
+}
+
+export interface DbTableVO {
+	createDept?: any;
+	tableId?: any;
+	tableName: string;
+	tableComment: string;
+	subTableName?: any;
+	subTableFkName?: any;
+	className?: any;
+	tplCategory?: any;
+	packageName?: any;
+	moduleName?: any;
+	businessName?: any;
+	functionName?: any;
+	functionAuthor?: any;
+	genType?: any;
+	genPath?: any;
+	pkColumn?: any;
+	columns: DbColumnVO[];
+	options?: any;
+	remark?: any;
+	treeCode?: any;
+	treeParentCode?: any;
+	treeName?: any;
+	menuIds?: any;
+	parentMenuId?: any;
+	parentMenuName?: any;
+	tree: boolean;
+	crud: boolean;
+}
+
+export interface DbTableQuery extends PageQuery {
+	tableName: string;
+	tableComment: string;
+}
+
+export interface GenTableVO {
+	info: DbTableVO;
+	rows: DbColumnVO[];
+	tables: DbTableVO[];
+}
+
+export interface DbColumnForm extends BaseEntity {
+	createDept: number;
+	columnId: string;
+	tableId: string;
+	columnName: string;
+	columnComment: string;
+	columnType: string;
+	javaType: string;
+	javaField: string;
+	isPk: string;
+	isIncrement: string;
+	isRequired: string;
+	isInsert?: any;
+	isEdit: string;
+	isList: string;
+	isQuery?: any;
+	queryType: string;
+	htmlType: string;
+	dictType: string;
+	sort: number;
+	increment: boolean;
+	capJavaField: string;
+	usableColumn: boolean;
+	superColumn: boolean;
+	list: boolean;
+	pk: boolean;
+	insert: boolean;
+	edit: boolean;
+	query: boolean;
+	required: boolean;
+}
+
+export interface DbParamForm {
+	treeCode?: any;
+	treeName?: any;
+	treeParentCode?: any;
+	parentMenuId: string;
+}
+
+export interface DbTableForm extends BaseEntity {
+	createDept?: any;
+	tableId: string | string;
+	tableName: string;
+	tableComment: string;
+	subTableName?: any;
+	subTableFkName?: any;
+	className: string;
+	tplCategory: string;
+	packageName: string;
+	moduleName: string;
+	businessName: string;
+	functionName: string;
+	functionAuthor: string;
+	genType: string;
+	genPath: string;
+	pkColumn?: any;
+	columns: DbColumnForm[];
+	options: string;
+	remark?: any;
+	treeCode?: any;
+	treeParentCode?: any;
+	treeName?: any;
+	menuIds?: any;
+	parentMenuId: string;
+	parentMenuName?: any;
+	tree: boolean;
+	crud: boolean;
+	params: DbParamForm;
+}

+ 54 - 0
src/api/types.ts

@@ -0,0 +1,54 @@
+/**
+ * 注册
+ */
+export type RegisterForm = {
+	tenantId: string;
+	username: string;
+	password: string;
+	confirmPassword?: string;
+	code?: string;
+	uuid?: string;
+	userType?: string;
+};
+
+/**
+ * 登录请求
+ */
+export interface LoginData {
+	tenantId: string;
+	username: string;
+	password: string;
+	rememberMe?: boolean;
+	code?: string;
+	uuid?: string;
+}
+
+/**
+ * 登录响应
+ */
+export interface LoginResult {
+	token: string;
+}
+
+/**
+ * 验证码返回
+ */
+export interface VerifyCodeResult {
+	captchaEnabled: boolean;
+	uuid?: string;
+	img?: string;
+}
+
+/**
+ * 租户
+ */
+export interface TenantVO {
+	companyName: string;
+	domain: any;
+	tenantId: string;
+}
+
+export interface TenantInfo {
+	tenantEnabled: boolean;
+	voList: TenantVO[];
+}

BIN
src/assets/images/login-background.jpg


BIN
src/assets/images/profile.jpg


BIN
src/assets/logo/logo.png


+ 66 - 66
src/assets/styles/btn.scss

@@ -1,99 +1,99 @@
 @import './variables.module.scss';
 
 @mixin colorBtn($color) {
-  background: $color;
+	background: $color;
 
-  &:hover {
-    color: $color;
+	&:hover {
+		color: $color;
 
-    &:before,
-    &:after {
-      background: $color;
-    }
-  }
+		&:before,
+		&:after {
+			background: $color;
+		}
+	}
 }
 
 .blue-btn {
-  @include colorBtn($blue)
+	@include colorBtn($blue);
 }
 
 .light-blue-btn {
-  @include colorBtn($light-blue)
+	@include colorBtn($light-blue);
 }
 
 .red-btn {
-  @include colorBtn($red)
+	@include colorBtn($red);
 }
 
 .pink-btn {
-  @include colorBtn($pink)
+	@include colorBtn($pink);
 }
 
 .green-btn {
-  @include colorBtn($green)
+	@include colorBtn($green);
 }
 
 .tiffany-btn {
-  @include colorBtn($tiffany)
+	@include colorBtn($tiffany);
 }
 
 .yellow-btn {
-  @include colorBtn($yellow)
+	@include colorBtn($yellow);
 }
 
 .pan-btn {
-  font-size: 14px;
-  color: #fff;
-  padding: 14px 36px;
-  border-radius: 8px;
-  border: none;
-  outline: none;
-  transition: 600ms ease all;
-  position: relative;
-  display: inline-block;
-
-  &:hover {
-    background: #fff;
-
-    &:before,
-    &:after {
-      width: 100%;
-      transition: 600ms ease all;
-    }
-  }
-
-  &:before,
-  &:after {
-    content: '';
-    position: absolute;
-    top: 0;
-    right: 0;
-    height: 2px;
-    width: 0;
-    transition: 400ms ease all;
-  }
-
-  &::after {
-    right: inherit;
-    top: inherit;
-    left: 0;
-    bottom: 0;
-  }
+	font-size: 14px;
+	color: #fff;
+	padding: 14px 36px;
+	border-radius: 8px;
+	border: none;
+	outline: none;
+	transition: 600ms ease all;
+	position: relative;
+	display: inline-block;
+
+	&:hover {
+		background: #fff;
+
+		&:before,
+		&:after {
+			width: 100%;
+			transition: 600ms ease all;
+		}
+	}
+
+	&:before,
+	&:after {
+		content: '';
+		position: absolute;
+		top: 0;
+		right: 0;
+		height: 2px;
+		width: 0;
+		transition: 400ms ease all;
+	}
+
+	&::after {
+		right: inherit;
+		top: inherit;
+		left: 0;
+		bottom: 0;
+	}
 }
 
 .custom-button {
-  display: inline-block;
-  line-height: 1;
-  white-space: nowrap;
-  cursor: pointer;
-  background: #fff;
-  color: #fff;
-  -webkit-appearance: none;
-  text-align: center;
-  box-sizing: border-box;
-  outline: 0;
-  margin: 0;
-  padding: 10px 15px;
-  font-size: 14px;
-  border-radius: 4px;
+	display: inline-block;
+	line-height: 1;
+	white-space: nowrap;
+	cursor: pointer;
+	background: #fff;
+	color: #fff;
+	-webkit-appearance: none;
+	text-align: center;
+	box-sizing: border-box;
+	outline: 0;
+	margin: 0;
+	padding: 10px 15px;
+	font-size: 14px;
+	border-radius: 4px;
 }

+ 55 - 50
src/assets/styles/element-ui.scss

@@ -1,96 +1,101 @@
 // cover some element-ui styles
 
+.el-divider--horizontal {
+	margin-bottom: 10px;
+	margin-top: 10px;
+}
+
 .el-breadcrumb__inner,
 .el-breadcrumb__inner a {
-  font-weight: 400 !important;
+	font-weight: 400 !important;
 }
 
 .el-upload {
-  input[type="file"] {
-    display: none !important;
-  }
+	input[type='file'] {
+		display: none !important;
+	}
 }
 
 .el-upload__input {
-  display: none;
+	display: none;
 }
 
 .cell {
-  .el-tag {
-    margin-right: 0px;
-  }
+	.el-tag {
+		margin-right: 0px;
+	}
 }
 
 .small-padding {
-  .cell {
-    padding-left: 5px;
-    padding-right: 5px;
-  }
+	.cell {
+		padding-left: 5px;
+		padding-right: 5px;
+	}
 }
 
 .fixed-width {
-  .el-button--mini {
-    padding: 7px 10px;
-    width: 60px;
-  }
+	.el-button--mini {
+		padding: 7px 10px;
+		width: 60px;
+	}
 }
 
 .status-col {
-  .cell {
-    padding: 0 10px;
-    text-align: center;
-
-    .el-tag {
-      margin-right: 0px;
-    }
-  }
+	.cell {
+		padding: 0 10px;
+		text-align: center;
+
+		.el-tag {
+			margin-right: 0px;
+		}
+	}
 }
 
 // to fixed https://github.com/ElemeFE/element/issues/2461
 .el-dialog {
-  transform: none;
-  left: 0;
-  position: relative;
-  margin: 0 auto;
+	transform: none;
+	left: 0;
+	position: relative;
+	margin: 0 auto;
 }
 
 // refine element ui upload
 .upload-container {
-  .el-upload {
-    width: 100%;
-
-    .el-upload-dragger {
-      width: 100%;
-      height: 200px;
-    }
-  }
+	.el-upload {
+		width: 100%;
+
+		.el-upload-dragger {
+			width: 100%;
+			height: 200px;
+		}
+	}
 }
 
 // dropdown
 .el-dropdown-menu {
-  a {
-    display: block
-  }
+	a {
+		display: block;
+	}
 }
 
 // fix date-picker ui bug in filter-item
 .el-range-editor.el-input__inner {
-  display: inline-flex !important;
+	display: inline-flex !important;
 }
 
 // to fix el-date-picker css style
 .el-range-separator {
-  box-sizing: content-box;
+	box-sizing: content-box;
 }
 
-.el-menu--collapse
-  > div
-  > .el-submenu
-  > .el-submenu__title
-  .el-submenu__icon-arrow {
-  display: none;
+.el-menu--collapse > div > .el-submenu > .el-submenu__title .el-submenu__icon-arrow {
+	display: none;
 }
 
-.el-dropdown .el-dropdown-link{
-  color: var(--el-color-primary) !important;
-}
+.el-dropdown .el-dropdown-link {
+	color: var(--el-color-primary) !important;
+}
+
+.el-dialog {
+	border-radius: 3% !important;
+}

+ 104 - 90
src/assets/styles/index.scss

@@ -5,189 +5,203 @@
 @import './sidebar.scss';
 @import './btn.scss';
 @import './ruoyi.scss';
-
+@import 'animate.css';
+//@import 'element-plus/dist/index.css';
 body {
-  height: 100%;
-  margin: 0;
-  -moz-osx-font-smoothing: grayscale;
-  -webkit-font-smoothing: antialiased;
-  text-rendering: optimizeLegibility;
-  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
+	height: 100%;
+	margin: 0;
+	-moz-osx-font-smoothing: grayscale;
+	-webkit-font-smoothing: antialiased;
+	text-rendering: optimizeLegibility;
+	font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
 }
 
 label {
-  font-weight: 700;
+	font-weight: 700;
 }
 
 html {
-  height: 100%;
-  box-sizing: border-box;
+	height: 100%;
+	box-sizing: border-box;
 }
 
 #app {
-  height: 100%;
+	height: 100%;
 }
 
 *,
 *:before,
 *:after {
-  box-sizing: inherit;
+	box-sizing: inherit;
 }
 
 .no-padding {
-  padding: 0px !important;
+	padding: 0px !important;
 }
 
 .padding-content {
-  padding: 4px 0;
+	padding: 4px 0;
 }
 
 a:focus,
 a:active {
-  outline: none;
+	outline: none;
 }
 
 a,
 a:focus,
 a:hover {
-  cursor: pointer;
-  color: inherit;
-  text-decoration: none;
+	cursor: pointer;
+	color: inherit;
+	text-decoration: none;
 }
 
 div:focus {
-  outline: none;
+	outline: none;
 }
 
 .fr {
-  float: right;
+	float: right;
 }
 
 .fl {
-  float: left;
+	float: left;
 }
 
 .pr-5 {
-  padding-right: 5px;
+	padding-right: 5px;
 }
 
 .pl-5 {
-  padding-left: 5px;
+	padding-left: 5px;
 }
 
 .block {
-  display: block;
+	display: block;
 }
 
 .pointer {
-  cursor: pointer;
+	cursor: pointer;
 }
 
 .inlineBlock {
-  display: block;
+	display: block;
 }
 
 .clearfix {
-  &:after {
-    visibility: hidden;
-    display: block;
-    font-size: 0;
-    content: " ";
-    clear: both;
-    height: 0;
-  }
+	&:after {
+		visibility: hidden;
+		display: block;
+		font-size: 0;
+		content: ' ';
+		clear: both;
+		height: 0;
+	}
 }
 
 aside {
-  background: #eef1f6;
-  padding: 8px 24px;
-  margin-bottom: 20px;
-  border-radius: 2px;
-  display: block;
-  line-height: 32px;
-  font-size: 16px;
-  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
-  color: #2c3e50;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-
-  a {
-    color: #337ab7;
-    cursor: pointer;
-
-    &:hover {
-      color: rgb(32, 160, 255);
-    }
-  }
+	background: #eef1f6;
+	padding: 8px 24px;
+	margin-bottom: 20px;
+	border-radius: 2px;
+	display: block;
+	line-height: 32px;
+	font-size: 16px;
+	font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+		sans-serif;
+	color: #2c3e50;
+	-webkit-font-smoothing: antialiased;
+	-moz-osx-font-smoothing: grayscale;
+
+	a {
+		color: #337ab7;
+		cursor: pointer;
+
+		&:hover {
+			color: rgb(32, 160, 255);
+		}
+	}
 }
 
 //main-container全局样式
 .app-container {
-  padding: 20px;
+	padding: 20px;
+}
+// search面板样式
+.panel,
+.search {
+	margin-bottom: 0.75rem;
+	border-radius: 0.25rem;
+	border: 1px solid var(--el-border-color-light);
+	background-color: var(--el-bg-color-overlay);
+	padding: 0.75rem;
+	--tw-shadow: var(--el-box-shadow-light);
+	--tw-shadow-colored: var(--el-box-shadow-light);
+	box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
 }
 
 .components-container {
-  margin: 30px 50px;
-  position: relative;
+	margin: 30px 50px;
+	position: relative;
 }
 
 .pagination-container {
-  margin-top: 30px;
+	margin-top: 30px;
 }
 
 .text-center {
-  text-align: center
+	text-align: center;
 }
 
 .sub-navbar {
-  height: 50px;
-  line-height: 50px;
-  position: relative;
-  width: 100%;
-  text-align: right;
-  padding-right: 20px;
-  transition: 600ms ease position;
-  background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
+	height: 50px;
+	line-height: 50px;
+	position: relative;
+	width: 100%;
+	text-align: right;
+	padding-right: 20px;
+	transition: 600ms ease position;
+	background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
 
-  .subtitle {
-    font-size: 20px;
-    color: #fff;
-  }
+	.subtitle {
+		font-size: 20px;
+		color: #fff;
+	}
 
-  &.draft {
-    background: #d0d0d0;
-  }
+	&.draft {
+		background: #d0d0d0;
+	}
 
-  &.deleted {
-    background: #d0d0d0;
-  }
+	&.deleted {
+		background: #d0d0d0;
+	}
 }
 
 .link-type,
 .link-type:focus {
-  color: #337ab7;
-  cursor: pointer;
+	color: #337ab7;
+	cursor: pointer;
 
-  &:hover {
-    color: rgb(32, 160, 255);
-  }
+	&:hover {
+		color: rgb(32, 160, 255);
+	}
 }
 
 .filter-container {
-  padding-bottom: 10px;
+	padding-bottom: 10px;
 
-  .filter-item {
-    display: inline-block;
-    vertical-align: middle;
-    margin-bottom: 10px;
-  }
+	.filter-item {
+		display: inline-block;
+		vertical-align: middle;
+		margin-bottom: 10px;
+	}
 }
 
 //refine vue-multiselect plugin
 .multiselect {
-  line-height: 16px;
+	line-height: 16px;
 }
 
 .multiselect--active {
-  z-index: 1000 !important;
+	z-index: 1000 !important;
 }

+ 46 - 52
src/assets/styles/mixin.scss

@@ -1,66 +1,60 @@
 @mixin clearfix {
-  &:after {
-    content: "";
-    display: table;
-    clear: both;
-  }
+	&:after {
+		content: '';
+		display: table;
+		clear: both;
+	}
 }
 
 @mixin scrollBar {
-  &::-webkit-scrollbar-track-piece {
-    background: #d3dce6;
-  }
-
-  &::-webkit-scrollbar {
-    width: 6px;
-  }
-
-  &::-webkit-scrollbar-thumb {
-    background: #99a9bf;
-    border-radius: 20px;
-  }
+	&::-webkit-scrollbar-track-piece {
+		background: #d3dce6;
+	}
+
+	&::-webkit-scrollbar {
+		width: 6px;
+	}
+
+	&::-webkit-scrollbar-thumb {
+		background: #99a9bf;
+		border-radius: 20px;
+	}
 }
 
 @mixin relative {
-  position: relative;
-  width: 100%;
-  height: 100%;
+	position: relative;
+	width: 100%;
+	height: 100%;
 }
 
 @mixin pct($pct) {
-  width: #{$pct};
-  position: relative;
-  margin: 0 auto;
+	width: #{$pct};
+	position: relative;
+	margin: 0 auto;
 }
 
 @mixin triangle($width, $height, $color, $direction) {
-  $width: $width/2;
-  $color-border-style: $height solid $color;
-  $transparent-border-style: $width solid transparent;
-  height: 0;
-  width: 0;
-
-  @if $direction==up {
-    border-bottom: $color-border-style;
-    border-left: $transparent-border-style;
-    border-right: $transparent-border-style;
-  }
-
-  @else if $direction==right {
-    border-left: $color-border-style;
-    border-top: $transparent-border-style;
-    border-bottom: $transparent-border-style;
-  }
-
-  @else if $direction==down {
-    border-top: $color-border-style;
-    border-left: $transparent-border-style;
-    border-right: $transparent-border-style;
-  }
-
-  @else if $direction==left {
-    border-right: $color-border-style;
-    border-top: $transparent-border-style;
-    border-bottom: $transparent-border-style;
-  }
+	$width: $width/2;
+	$color-border-style: $height solid $color;
+	$transparent-border-style: $width solid transparent;
+	height: 0;
+	width: 0;
+
+	@if $direction==up {
+		border-bottom: $color-border-style;
+		border-left: $transparent-border-style;
+		border-right: $transparent-border-style;
+	} @else if $direction==right {
+		border-left: $color-border-style;
+		border-top: $transparent-border-style;
+		border-bottom: $transparent-border-style;
+	} @else if $direction==down {
+		border-top: $color-border-style;
+		border-left: $transparent-border-style;
+		border-right: $transparent-border-style;
+	} @else if $direction==left {
+		border-right: $color-border-style;
+		border-top: $transparent-border-style;
+		border-bottom: $transparent-border-style;
+	}
 }

+ 52 - 39
src/assets/styles/ruoyi.scss

@@ -1,9 +1,9 @@
- /**
+/**
  * 通用css样式布局处理
  * Copyright (c) 2019 ruoyi
  */
 
- /** 基础通用 **/
+/** 基础通用 **/
 .pt5 {
 	padding-top: 5px;
 }
@@ -53,7 +53,18 @@
 	margin-left: 20px;
 }
 
-.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
 	font-family: inherit;
 	font-weight: 500;
 	line-height: 1.1;
@@ -75,7 +86,8 @@
 }
 
 .el-table {
-	.el-table__header-wrapper, .el-table__fixed-header-wrapper {
+	.el-table__header-wrapper,
+	.el-table__fixed-header-wrapper {
 		th {
 			word-break: break-word;
 			background-color: #f8f8f9 !important;
@@ -85,7 +97,7 @@
 		}
 	}
 	.el-table__body-wrapper {
-		.el-button [class*="el-icon-"] + span {
+		.el-button [class*='el-icon-'] + span {
 			margin-left: 1px;
 		}
 	}
@@ -93,11 +105,11 @@
 
 /** 表单布局 **/
 .form-header {
-    font-size:15px;
-	color:#6379bb;
-	border-bottom:1px solid #ddd;
-	margin:8px 10px 25px 10px;
-	padding-bottom:5px
+	font-size: 15px;
+	color: #6379bb;
+	border-bottom: 1px solid #ddd;
+	margin: 8px 10px 25px 10px;
+	padding-bottom: 5px;
 }
 
 /** 表格布局 **/
@@ -111,25 +123,25 @@
 
 /* tree border */
 .tree-border {
-    margin-top: 5px;
-    border: 1px solid #e5e6e7;
-    background: #FFFFFF none;
-    border-radius:4px;
-    width: 100%;
+	margin-top: 5px;
+	border: 1px solid #e5e6e7;
+	background: #ffffff none;
+	border-radius: 4px;
+	width: 100%;
 }
 
 .pagination-container .el-pagination {
-	right: 0;
-	position: absolute;
+	//right: 0;
+	//position: absolute;
 }
 
-@media ( max-width : 768px) {
-  .pagination-container .el-pagination > .el-pagination__jump {
-    display: none !important;
-  }
-  .pagination-container .el-pagination > .el-pagination__sizes {
-    display: none !important;
-  }
+@media (max-width: 768px) {
+	.pagination-container .el-pagination > .el-pagination__jump {
+		display: none !important;
+	}
+	.pagination-container .el-pagination > .el-pagination__sizes {
+		display: none !important;
+	}
 }
 
 .el-table .fixed-width .el-button--small {
@@ -141,11 +153,12 @@
 /** 表格更多操作下拉样式 */
 .el-table .el-dropdown-link {
 	cursor: pointer;
-	color: #409EFF;
+	color: #409eff;
 	margin-left: 10px;
 }
 
-.el-table .el-dropdown, .el-icon-arrow-down {
+.el-table .el-dropdown,
+.el-icon-arrow-down {
 	font-size: 12px;
 }
 
@@ -196,22 +209,22 @@
 /* button color */
 .el-button--cyan.is-active,
 .el-button--cyan:active {
-  background: #20B2AA;
-  border-color: #20B2AA;
-  color: #FFFFFF;
+	background: #20b2aa;
+	border-color: #20b2aa;
+	color: #ffffff;
 }
 
 .el-button--cyan:focus,
 .el-button--cyan:hover {
-  background: #48D1CC;
-  border-color: #48D1CC;
-  color: #FFFFFF;
+	background: #48d1cc;
+	border-color: #48d1cc;
+	color: #ffffff;
 }
 
 .el-button--cyan {
-  background-color: #20B2AA;
-  border-color: #20B2AA;
-  color: #FFFFFF;
+	background-color: #20b2aa;
+	border-color: #20b2aa;
+	color: #ffffff;
 }
 
 /* text color */
@@ -265,10 +278,10 @@
 }
 
 /* 拖拽列样式 */
-.sortable-ghost{
-	opacity: .8;
-	color: #fff!important;
-	background: #42b983!important;
+.sortable-ghost {
+	opacity: 0.8;
+	color: #fff !important;
+	background: #42b983 !important;
 }
 
 /* 表格右侧工具栏样式 */

+ 230 - 232
src/assets/styles/sidebar.scss

@@ -1,238 +1,236 @@
 #app {
-
-  .main-container {
-    min-height: 100%;
-    transition: margin-left .28s;
-    margin-left: $base-sidebar-width;
-    position: relative;
-  }
-
-  .sidebarHide {
-    margin-left: 0!important;
-  }
-
-  .sidebar-container {
-    -webkit-transition: width .28s;
-    transition: width 0.28s;
-    width: $base-sidebar-width !important;
-    background-color: $base-menu-background;
-    height: 100%;
-    position: fixed;
-    font-size: 0px;
-    top: 0;
-    bottom: 0;
-    left: 0;
-    z-index: 1001;
-    overflow: hidden;
-    -webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
-    box-shadow: 2px 0 6px rgba(0,21,41,.35);
-
-    // reset element-ui css
-    .horizontal-collapse-transition {
-      transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
-    }
-
-    .scrollbar-wrapper {
-      overflow-x: hidden !important;
-    }
-
-    .el-scrollbar__bar.is-vertical {
-      right: 0px;
-    }
-
-    .el-scrollbar {
-      height: 100%;
-    }
-
-    &.has-logo {
-      .el-scrollbar {
-        height: calc(100% - 50px);
-      }
-    }
-
-    .is-horizontal {
-      display: none;
-    }
-
-    a {
-      display: inline-block;
-      width: 100%;
-      overflow: hidden;
-    }
-
-    .svg-icon {
-      margin-right: 16px;
-    }
-
-    .el-menu {
-      border: none;
-      height: 100%;
-      width: 100% !important;
-    }
-
-    .el-menu-item, .menu-title {
-      overflow: hidden !important;
-      text-overflow: ellipsis !important;
-      white-space: nowrap !important;
-    }
-
-    .el-menu-item .el-menu-tooltip__trigger {
-      display: inline-block !important;
-    }
-
-    // menu hover
-    .sub-menu-title-noDropdown,
-    .el-sub-menu__title {
-      &:hover {
-        background-color: rgba(0, 0, 0, 0.06) !important;
-      }
-    }
-
-    & .theme-dark .is-active > .el-sub-menu__title {
-      color: $base-menu-color-active !important;
-    }
-
-    & .nest-menu .el-sub-menu>.el-sub-menu__title,
-    & .el-sub-menu .el-menu-item {
-      min-width: $base-sidebar-width !important;
-
-      &:hover {
-        background-color: rgba(0, 0, 0, 0.06) !important;
-      }
-    }
-
-    & .theme-dark .nest-menu .el-sub-menu>.el-sub-menu__title,
-    & .theme-dark .el-sub-menu .el-menu-item {
-      background-color: $base-sub-menu-background !important;
-
-      &:hover {
-        background-color: $base-sub-menu-hover !important;
-      }
-    }
-  }
-
-  .hideSidebar {
-    .sidebar-container {
-      width: 54px !important;
-    }
-
-    .main-container {
-      margin-left: 54px;
-    }
-
-    .sub-menu-title-noDropdown {
-      padding: 0 !important;
-      position: relative;
-
-      .el-tooltip {
-        padding: 0 !important;
-
-        .svg-icon {
-          margin-left: 20px;
-        }
-      }
-    }
-
-    .el-sub-menu {
-      overflow: hidden;
-
-      &>.el-sub-menu__title {
-        padding: 0 !important;
-
-        .svg-icon {
-          margin-left: 20px;
-        }
-
-      }
-    }
-
-    .el-menu--collapse {
-      .el-sub-menu {
-        &>.el-sub-menu__title {
-          &>span {
-            height: 0;
-            width: 0;
-            overflow: hidden;
-            visibility: hidden;
-            display: inline-block;
-          }
-          &>i {
-            height: 0;
-            width: 0;
-            overflow: hidden;
-            visibility: hidden;
-            display: inline-block;
-          }
-        }
-      }
-    }
-  }
-
-  .el-menu--collapse .el-menu .el-sub-menu {
-    min-width: $base-sidebar-width !important;
-  }
-
-  // mobile responsive
-  .mobile {
-    .main-container {
-      margin-left: 0px;
-    }
-
-    .sidebar-container {
-      transition: transform .28s;
-      width: $base-sidebar-width !important;
-    }
-
-    &.hideSidebar {
-      .sidebar-container {
-        pointer-events: none;
-        transition-duration: 0.3s;
-        transform: translate3d(-$base-sidebar-width, 0, 0);
-      }
-    }
-  }
-
-  .withoutAnimation {
-
-    .main-container,
-    .sidebar-container {
-      transition: none;
-    }
-  }
+	.main-container {
+		min-height: 100%;
+		transition: margin-left 0.28s;
+		margin-left: $base-sidebar-width;
+		position: relative;
+	}
+
+	.sidebarHide {
+		margin-left: 0 !important;
+	}
+
+	.sidebar-container {
+		-webkit-transition: width 0.28s;
+		transition: width 0.28s;
+		width: $base-sidebar-width !important;
+		background-color: $base-menu-background;
+		height: 100%;
+		position: fixed;
+		font-size: 0px;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		z-index: 1001;
+		overflow: hidden;
+		-webkit-box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35);
+		box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35);
+
+		// reset element-ui css
+		.horizontal-collapse-transition {
+			transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
+		}
+
+		.scrollbar-wrapper {
+			overflow-x: hidden !important;
+		}
+
+		.el-scrollbar__bar.is-vertical {
+			right: 0px;
+		}
+
+		.el-scrollbar {
+			height: 100%;
+		}
+
+		&.has-logo {
+			.el-scrollbar {
+				height: calc(100% - 50px);
+			}
+		}
+
+		.is-horizontal {
+			display: none;
+		}
+
+		a {
+			display: inline-block;
+			width: 100%;
+			overflow: hidden;
+		}
+
+		.svg-icon {
+			margin-right: 16px;
+		}
+
+		.el-menu {
+			border: none;
+			height: 100%;
+			width: 100% !important;
+		}
+
+		.el-menu-item,
+		.menu-title {
+			overflow: hidden !important;
+			text-overflow: ellipsis !important;
+			white-space: nowrap !important;
+		}
+
+		.el-menu-item .el-menu-tooltip__trigger {
+			display: inline-block !important;
+		}
+
+		// menu hover
+		.sub-menu-title-noDropdown,
+		.el-sub-menu__title {
+			&:hover {
+				background-color: rgba(0, 0, 0, 0.06) !important;
+			}
+		}
+
+		& .theme-dark .is-active > .el-sub-menu__title {
+			color: $base-menu-color-active !important;
+		}
+
+		& .nest-menu .el-sub-menu > .el-sub-menu__title,
+		& .el-sub-menu .el-menu-item {
+			min-width: $base-sidebar-width !important;
+
+			&:hover {
+				background-color: rgba(0, 0, 0, 0.06) !important;
+			}
+		}
+
+		& .theme-dark .nest-menu .el-sub-menu > .el-sub-menu__title,
+		& .theme-dark .el-sub-menu .el-menu-item {
+			background-color: $base-sub-menu-background !important;
+
+			&:hover {
+				background-color: $base-sub-menu-hover !important;
+			}
+		}
+	}
+
+	.hideSidebar {
+		.sidebar-container {
+			width: 54px !important;
+		}
+
+		.main-container {
+			margin-left: 54px;
+		}
+
+		.sub-menu-title-noDropdown {
+			padding: 0 !important;
+			position: relative;
+
+			.el-tooltip {
+				padding: 0 !important;
+
+				.svg-icon {
+					margin-left: 20px;
+				}
+			}
+		}
+
+		.el-sub-menu {
+			overflow: hidden;
+
+			& > .el-sub-menu__title {
+				padding: 0 !important;
+
+				.svg-icon {
+					margin-left: 20px;
+				}
+			}
+		}
+
+		.el-menu--collapse {
+			.el-sub-menu {
+				& > .el-sub-menu__title {
+					& > span {
+						height: 0;
+						width: 0;
+						overflow: hidden;
+						visibility: hidden;
+						display: inline-block;
+					}
+					& > i {
+						height: 0;
+						width: 0;
+						overflow: hidden;
+						visibility: hidden;
+						display: inline-block;
+					}
+				}
+			}
+		}
+	}
+
+	.el-menu--collapse .el-menu .el-sub-menu {
+		min-width: $base-sidebar-width !important;
+	}
+
+	// mobile responsive
+	.mobile {
+		.main-container {
+			margin-left: 0px;
+		}
+
+		.sidebar-container {
+			transition: transform 0.28s;
+			width: $base-sidebar-width !important;
+		}
+
+		&.hideSidebar {
+			.sidebar-container {
+				pointer-events: none;
+				transition-duration: 0.3s;
+				transform: translate3d(-$base-sidebar-width, 0, 0);
+			}
+		}
+	}
+
+	.withoutAnimation {
+		.main-container,
+		.sidebar-container {
+			transition: none;
+		}
+	}
 }
 
 // when menu collapsed
 .el-menu--vertical {
-  &>.el-menu {
-    .svg-icon {
-      margin-right: 16px;
-    }
-  }
-
-  .nest-menu .el-sub-menu>.el-sub-menu__title,
-  .el-menu-item {
-    &:hover {
-      // you can use $sub-menuHover
-      background-color: rgba(0, 0, 0, 0.06) !important;
-    }
-  }
-
-  // the scroll bar appears when the sub-menu is too long
-  >.el-menu--popup {
-    max-height: 100vh;
-    overflow-y: auto;
-
-    &::-webkit-scrollbar-track-piece {
-      background: #d3dce6;
-    }
-
-    &::-webkit-scrollbar {
-      width: 6px;
-    }
-
-    &::-webkit-scrollbar-thumb {
-      background: #99a9bf;
-      border-radius: 20px;
-    }
-  }
+	& > .el-menu {
+		.svg-icon {
+			margin-right: 16px;
+		}
+	}
+
+	.nest-menu .el-sub-menu > .el-sub-menu__title,
+	.el-menu-item {
+		&:hover {
+			// you can use $sub-menuHover
+			background-color: rgba(0, 0, 0, 0.06) !important;
+		}
+	}
+
+	// the scroll bar appears when the sub-menu is too long
+	> .el-menu--popup {
+		max-height: 100vh;
+		overflow-y: auto;
+
+		&::-webkit-scrollbar-track-piece {
+			background: #d3dce6;
+		}
+
+		&::-webkit-scrollbar {
+			width: 6px;
+		}
+
+		&::-webkit-scrollbar-thumb {
+			background: #99a9bf;
+			border-radius: 20px;
+		}
+	}
 }

+ 13 - 13
src/assets/styles/transition.scss

@@ -3,51 +3,51 @@
 /* fade */
 .fade-enter-active,
 .fade-leave-active {
-  transition: opacity 0.28s;
+	transition: opacity 0.28s;
 }
 
 .fade-enter,
 .fade-leave-active {
-  opacity: 0;
+	opacity: 0;
 }
 
 /* fade-transform */
 .fade-transform--move,
 .fade-transform-leave-active,
 .fade-transform-enter-active {
-  transition: all .5s;
+	transition: all 0.5s;
 }
 
 .fade-transform-leave-active {
-  position: absolute;
+	position: absolute;
 }
 
 .fade-transform-enter {
-  opacity: 0;
-  transform: translateX(-30px);
+	opacity: 0;
+	transform: translateX(-30px);
 }
 
 .fade-transform-leave-to {
-  opacity: 0;
-  transform: translateX(30px);
+	opacity: 0;
+	transform: translateX(30px);
 }
 
 /* breadcrumb transition */
 .breadcrumb-enter-active,
 .breadcrumb-leave-active {
-  transition: all .5s;
+	transition: all 0.5s;
 }
 
 .breadcrumb-enter,
 .breadcrumb-leave-active {
-  opacity: 0;
-  transform: translateX(20px);
+	opacity: 0;
+	transform: translateX(20px);
 }
 
 .breadcrumb-move {
-  transition: all .5s;
+	transition: all 0.5s;
 }
 
 .breadcrumb-leave-active {
-  position: absolute;
+	position: absolute;
 }

+ 26 - 26
src/assets/styles/variables.module.scss

@@ -1,12 +1,12 @@
 // base color
 $blue: #324157;
-$light-blue: #3A71A8;
-$red: #C03639;
-$pink: #E65D6E;
-$green: #30B08F;
-$tiffany: #4AB7BD;
-$yellow: #FEC171;
-$panGreen: #30B08F;
+$light-blue: #3a71a8;
+$red: #c03639;
+$pink: #e65d6e;
+$green: #30b08f;
+$tiffany: #4ab7bd;
+$yellow: #fec171;
+$panGreen: #30b08f;
 
 // 默认菜单主题风格
 $base-menu-color: #bfcbd9;
@@ -36,10 +36,10 @@ $base-sub-menu-background:#000c17;
 $base-sub-menu-hover:#001528;
 */
 
-$--color-primary: #409EFF;
-$--color-success: #67C23A;
-$--color-warning: #E6A23C;
-$--color-danger: #F56C6C;
+$--color-primary: #409eff;
+$--color-success: #67c23a;
+$--color-warning: #e6a23c;
+$--color-danger: #f56c6c;
 $--color-info: #909399;
 
 $base-sidebar-width: 200px;
@@ -47,19 +47,19 @@ $base-sidebar-width: 200px;
 // the :export directive is the magic sauce for webpack
 // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
 :export {
-  menuColor: $base-menu-color;
-  menuLightColor: $base-menu-light-color;
-  menuColorActive: $base-menu-color-active;
-  menuBackground: $base-menu-background;
-  menuLightBackground: $base-menu-light-background;
-  subMenuBackground: $base-sub-menu-background;
-  subMenuHover: $base-sub-menu-hover;
-  sideBarWidth: $base-sidebar-width;
-  logoTitleColor: $base-logo-title-color;
-  logoLightTitleColor: $base-logo-light-title-color;
-  primaryColor: $--color-primary;
-  successColor: $--color-success;
-  dangerColor: $--color-danger;
-  infoColor: $--color-info;
-  warningColor: $--color-warning;
+	menuColor: $base-menu-color;
+	menuLightColor: $base-menu-light-color;
+	menuColorActive: $base-menu-color-active;
+	menuBackground: $base-menu-background;
+	menuLightBackground: $base-menu-light-background;
+	subMenuBackground: $base-sub-menu-background;
+	subMenuHover: $base-sub-menu-hover;
+	sideBarWidth: $base-sidebar-width;
+	logoTitleColor: $base-logo-title-color;
+	logoLightTitleColor: $base-logo-light-title-color;
+	primaryColor: $--color-primary;
+	successColor: $--color-success;
+	dangerColor: $--color-danger;
+	infoColor: $--color-info;
+	warningColor: $--color-warning;
 }

+ 27 - 29
src/components/Breadcrumb/index.vue

@@ -1,57 +1,55 @@
-<template>
-  <el-breadcrumb class="app-breadcrumb" separator="/">
-    <transition-group name="breadcrumb">
-      <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
-        <span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span>
-        <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
-      </el-breadcrumb-item>
-    </transition-group>
-  </el-breadcrumb>
-</template>
+<script setup lang="ts">
+import { RouteLocationMatched } from 'vue-router'
 
-<script setup>
 const route = useRoute();
 const router = useRouter();
-const levelList = ref([])
+const levelList = ref<RouteLocationMatched[]>([])
 
-function getBreadcrumb() {
+const getBreadcrumb = () => {
   // only show routes with meta.title
   let matched = route.matched.filter(item => item.meta && item.meta.title);
   const first = matched[0]
   // 判断是否为首页
   if (!isDashboard(first)) {
-    matched = [{ path: '/index', meta: { title: '首页' } }].concat(matched)
+    matched = ([{ path: '/index', meta: { title: '首页' } }] as any).concat(matched)
   }
-
   levelList.value = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
 }
-function isDashboard(route) {
-  const name = route && route.name
+const isDashboard = (route: RouteLocationMatched) => {
+  const name = route && route.name as string
   if (!name) {
     return false
   }
   return name.trim() === 'Index'
 }
-function handleLink(item) {
+const handleLink = (item: RouteLocationMatched) => {
   const { redirect, path } = item
-  if (redirect) {
-    router.push(redirect)
-    return
-  }
-  router.push(path)
+  redirect ? router.push(redirect as string) : router.push(path)
 }
 
 watchEffect(() => {
   // if you go to the redirect page, do not update the breadcrumbs
-  if (route.path.startsWith('/redirect/')) {
-    return
-  }
+  if (route.path.startsWith('/redirect/')) return
   getBreadcrumb()
 })
-getBreadcrumb();
+onMounted(() => {
+  getBreadcrumb();
+})
 </script>
 
-<style lang='scss' scoped>
+<template>
+	<el-breadcrumb class="app-breadcrumb" separator="/">
+		<transition-group name="breadcrumb">
+			<el-breadcrumb-item v-for="(item, index) in levelList" :key="item.path">
+				<span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{
+          item.meta?.title }}</span>
+				<a v-else @click.prevent="handleLink(item)">{{ item.meta?.title }}</a>
+			</el-breadcrumb-item>
+		</transition-group>
+	</el-breadcrumb>
+</template>
+
+<style lang="scss" scoped>
 .app-breadcrumb.el-breadcrumb {
   display: inline-block;
   font-size: 14px;
@@ -63,4 +61,4 @@ getBreadcrumb();
     cursor: text;
   }
 }
-</style>
+</style>

+ 34 - 31
src/components/DictTag/index.vue

@@ -1,31 +1,10 @@
-<template>
-  <div>
-    <template v-for="(item, index) in options">
-      <template v-if="values.includes(item.value)">
-        <span
-          v-if="item.elTagType == 'default' || item.elTagType == ''"
-          :key="item.value"
-          :index="index"
-          :class="item.elTagClass"
-        >{{ item.label }}</span>
-        <el-tag
-          v-else
-          :disable-transitions="true"
-          :key="item.value + ''"
-          :index="index"
-          :type="item.elTagType === 'primary' ? '' : item.elTagType"
-          :class="item.elTagClass"
-        >{{ item.label }}</el-tag>
-      </template>
-    </template>
-  </div>
-</template>
+<script setup lang="ts">
+import { PropType } from 'vue';
 
-<script setup>
 const props = defineProps({
   // 数据
   options: {
-    type: Array,
+    type: Array as PropType<DictDataOption[]>,
     default: null,
   },
   // 当前的值
@@ -33,17 +12,41 @@ const props = defineProps({
 })
 
 const values = computed(() => {
-  if (props.value !== null && typeof props.value !== 'undefined') {
-    return Array.isArray(props.value) ? props.value : [String(props.value)];
-  } else {
-    return [];
-  }
+	if (props.value !== null && typeof props.value !== 'undefined') {
+		return Array.isArray(props.value) ? props.value : [String(props.value)];
+	} else {
+		return [];
+	}
 })
-
 </script>
 
+<template>
+	<div>
+		<template v-for="(item, index) in options">
+			<template v-if="values.includes(item.value)">
+				<span
+					v-if="item.elTagType == 'default' || item.elTagType == ''"
+					:key="item.value"
+					:index="index"
+					:class="item.elTagClass"
+					>{{ item.label }}</span
+				>
+				<el-tag
+					v-else
+					:disable-transitions="true"
+					:key="item.value + ''"
+					:index="index"
+					:type="item.elTagType === 'primary' ? '' : item.elTagType"
+					:class="item.elTagClass"
+					>{{ item.label }}</el-tag
+				>
+			</template>
+		</template>
+	</div>
+</template>
+
 <style scoped>
 .el-tag + .el-tag {
   margin-left: 10px;
 }
-</style>
+</style>

+ 53 - 51
src/components/Editor/index.vue

@@ -1,36 +1,8 @@
-<template>
-  <div>
-    <el-upload
-        :action="uploadUrl"
-        :before-upload="handleBeforeUpload"
-        :on-success="handleUploadSuccess"
-        :on-error="handleUploadError"
-        class="editor-img-uploader"
-        name="file"
-        :show-file-list="false"
-        :headers="headers"
-        style="display: none"
-        ref="uploadRef"
-        v-if="type == 'url'"
-    >
-    </el-upload>
-    <div class="editor">
-      <quill-editor
-          ref="myQuillEditor"
-          v-model:content="content"
-          contentType="html"
-          @textChange="(e) => $emit('update:modelValue', content)"
-          :options="options"
-          :style="styles"
-      />
-    </div>
-  </div>
-</template>
-
-<script setup>
+<script setup lang="ts">
 import { QuillEditor, Quill } from '@vueup/vue-quill';
 import '@vueup/vue-quill/dist/vue-quill.snow.css';
 import { getToken } from "@/utils/auth";
+import { ComponentInternalInstance } from "vue";
 
 const props = defineProps({
   /* 编辑器的内容 */
@@ -64,10 +36,12 @@ const props = defineProps({
   }
 });
 
-const { proxy } = getCurrentInstance();
-// 上传的图片服务器地址
-const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/system/oss/upload");
-const headers = ref({ Authorization: "Bearer " + getToken() });
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+
+const upload = reactive<UploadOption>({
+  headers: { Authorization: "Bearer " + getToken() },
+  url: import.meta.env.VITE_APP_BASE_API + '/system/oss/upload'
+})
 const myQuillEditor = ref();
 
 const options = ref({
@@ -90,10 +64,10 @@ const options = ref({
         ["link", "image", "video"]                       // 链接、图片、视频
       ],
       handlers: {
-        image: function (value) {
+        image: function (value: any) {
           if (value) {
             // 调用element图片上传
-            document.querySelector(".editor-img-uploader>.el-upload").click();
+            (document.querySelector(".editor-img-uploader>.el-upload") as HTMLDivElement)?.click();
           } else {
             Quill.format("image", true);
           }
@@ -106,7 +80,7 @@ const options = ref({
 });
 
 const styles = computed(() => {
-  let style = {};
+  let style: any = {};
   if (props.minHeight) {
     style.minHeight = `${props.minHeight}px`;
   }
@@ -118,51 +92,79 @@ const styles = computed(() => {
 
 const content = ref("");
 watch(() => props.modelValue, (v) => {
-  if (v !== content) {
+  if (v !== content.value) {
     content.value = v === undefined ? "<p></p>" : v;
   }
 }, { immediate: true });
 
 // 图片上传成功返回图片地址
-function handleUploadSuccess(res, file) {
+const handleUploadSuccess = (res: any) => {
   // 获取富文本实例
   let quill = toRaw(myQuillEditor.value).getQuill();
   // 如果上传成功
-  if (res.code == 200) {
+  if (res.code === 200) {
     // 获取光标位置
     let length = quill.selection.savedRange.index;
     // 插入图片,res为服务器返回的图片链接地址
     quill.insertEmbed(length, "image", res.data.url);
     // 调整光标到最后
     quill.setSelection(length + 1);
-    proxy.$modal.closeLoading();
+    proxy?.$modal.closeLoading();
   } else {
-    proxy.$modal.loading(res.msg);
-    proxy.$modal.closeLoading();
+    proxy?.$modal.loading(res.msg);
+    proxy?.$modal.closeLoading();
   }
 }
 
 // 图片上传前拦截
-function handleBeforeUpload(file) {
+const handleBeforeUpload = (file: any) => {
   // 校检文件大小
   if (props.fileSize) {
     const isLt = file.size / 1024 / 1024 < props.fileSize;
     if (!isLt) {
-      proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
+      proxy?.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
       return false;
     }
   }
-  proxy.$modal.loading("正在上传文件,请稍候...");
+  proxy?.$modal.loading('正在上传文件,请稍候...');
   return true;
 }
 
 // 图片失败拦截
-function handleUploadError(err) {
-  proxy.$modal.msgError("上传文件失败");
+const handleUploadError = (err: any) => {
+  console.error(err);
+  proxy?.$modal.msgError('上传文件失败');
 }
-
 </script>
 
+<template>
+	<div>
+		<el-upload
+			:action="upload.url"
+			:before-upload="handleBeforeUpload"
+			:on-success="handleUploadSuccess"
+			:on-error="handleUploadError"
+			class="editor-img-uploader"
+			name="file"
+			:show-file-list="false"
+			:headers="upload.headers"
+			style="display: none"
+			v-if="type === 'url'"
+		>
+		</el-upload>
+		<div class="editor">
+			<quill-editor
+				ref="myQuillEditor"
+				v-model:content="content"
+				contentType="html"
+				@textChange="(e: any) => $emit('update:modelValue', content)"
+				:options="options"
+				:style="styles"
+			/>
+		</div>
+	</div>
+</template>
+
 <style>
 .editor, .ql-toolbar {
   white-space: pre-wrap !important;
@@ -175,9 +177,9 @@ function handleUploadError(err) {
   content: "请输入链接地址:";
 }
 .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
-  border-right: 0px;
+  border-right: 0;
   content: "保存";
-  padding-right: 0px;
+  padding-right: 0;
 }
 
 .ql-snow .ql-tooltip[data-mode="video"]::before {

+ 82 - 73
src/components/FileUpload/index.vue

@@ -1,46 +1,8 @@
-<template>
-  <div class="upload-file">
-    <el-upload
-      multiple
-      :action="uploadFileUrl"
-      :before-upload="handleBeforeUpload"
-      :file-list="fileList"
-      :limit="limit"
-      :on-error="handleUploadError"
-      :on-exceed="handleExceed"
-      :on-success="handleUploadSuccess"
-      :show-file-list="false"
-      :headers="headers"
-      class="upload-file-uploader"
-      ref="fileUpload"
-    >
-      <!-- 上传按钮 -->
-      <el-button type="primary">选取文件</el-button>
-    </el-upload>
-    <!-- 上传提示 -->
-    <div class="el-upload__tip" v-if="showTip">
-      请上传
-      <template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
-      <template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
-      的文件
-    </div>
-    <!-- 文件列表 -->
-    <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
-      <li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
-        <el-link :href="`${file.url}`" :underline="false" target="_blank">
-          <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
-        </el-link>
-        <div class="ele-upload-list__item-content-action">
-          <el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
-        </div>
-      </li>
-    </transition-group>
-  </div>
-</template>
-
-<script setup>
+<script setup lang="ts">
 import { getToken } from "@/utils/auth";
 import { listByIds, delOss } from "@/api/system/oss";
+import { ComponentInternalInstance } from "vue";
+import { ElUpload, UploadFile } from "element-plus";
 
 const props = defineProps({
   modelValue: [String, Object, Array],
@@ -66,32 +28,35 @@ const props = defineProps({
   }
 });
 
-const { proxy } = getCurrentInstance();
-const emit = defineEmits();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const emit = defineEmits(['update:modelValue']);
 const number = ref(0);
-const uploadList = ref([]);
+const uploadList = ref<any[]>([]);
+
 const baseUrl = import.meta.env.VITE_APP_BASE_API;
 const uploadFileUrl = ref(baseUrl + "/system/oss/upload"); // 上传文件服务器地址
 const headers = ref({ Authorization: "Bearer " + getToken() });
-const fileList = ref([]);
+
+const fileList = ref<any[]>([]);
 const showTip = computed(
   () => props.isShowTip && (props.fileType || props.fileSize)
 );
 
+const fileUploadRef = ref(ElUpload);
+
 watch(() => props.modelValue, async val => {
   if (val) {
     let temp = 1;
     // 首先将值转为数组
-    let list;
+    let list = [];
     if (Array.isArray(val)) {
       list = val;
     } else {
-      await listByIds(val).then(res => {
-        list = res.data.map(oss => {
-          oss = { name: oss.originalName, url: oss.url, ossId: oss.ossId };
-          return oss;
+      const res =  await listByIds(val as string)
+      list = res.data.map((oss) => {
+          const data = { name: oss.originalName, url: oss.url, ossId: oss.ossId };
+          return data;
         });
-      })
     }
     // 然后将数组转为对象数组
     fileList.value = list.map(item => {
@@ -106,14 +71,14 @@ watch(() => props.modelValue, async val => {
 },{ deep: true, immediate: true });
 
 // 上传前校检格式和大小
-function handleBeforeUpload(file) {
+const handleBeforeUpload = (file: any) => {
   // 校检文件类型
   if (props.fileType.length) {
     const fileName = file.name.split('.');
     const fileExt = fileName[fileName.length - 1];
     const isTypeOk = props.fileType.indexOf(fileExt) >= 0;
     if (!isTypeOk) {
-      proxy.$modal.msgError(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`);
+      proxy?.$modal.msgError(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`);
       return false;
     }
   }
@@ -121,41 +86,41 @@ function handleBeforeUpload(file) {
   if (props.fileSize) {
     const isLt = file.size / 1024 / 1024 < props.fileSize;
     if (!isLt) {
-      proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
+      proxy?.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
       return false;
     }
   }
-  proxy.$modal.loading("正在上传文件,请稍候...");
+  proxy?.$modal.loading("正在上传文件,请稍候...");
   number.value++;
   return true;
 }
 
 // 文件个数超出
-function handleExceed() {
-  proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
+const handleExceed = () => {
+  proxy?.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
 }
 
 // 上传失败
-function handleUploadError(err) {
-  proxy.$modal.msgError("上传文件失败");
+const handleUploadError = () => {
+  proxy?.$modal.msgError("上传文件失败");
 }
 
 // 上传成功回调
-function handleUploadSuccess(res, file) {
+const handleUploadSuccess = (res:any, file: UploadFile) => {
   if (res.code === 200) {
     uploadList.value.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId });
     uploadedSuccessfully();
   } else {
     number.value--;
-    proxy.$modal.closeLoading();
-    proxy.$modal.msgError(res.msg);
-    proxy.$refs.fileUpload.handleRemove(file);
+    proxy?.$modal.closeLoading();
+    proxy?.$modal.msgError(res.msg);
+    fileUploadRef.value.handleRemove(file);
     uploadedSuccessfully();
   }
 }
 
 // 删除文件
-function handleDelete(index) {
+const handleDelete = (index: number) => {
   let ossId = fileList.value[index].ossId;
   delOss(ossId);
   fileList.value.splice(index, 1);
@@ -163,18 +128,18 @@ function handleDelete(index) {
 }
 
 // 上传结束处理
-function uploadedSuccessfully() {
+const uploadedSuccessfully =() => {
   if (number.value > 0 && uploadList.value.length === number.value) {
     fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value);
     uploadList.value = [];
     number.value = 0;
     emit("update:modelValue", listToString(fileList.value));
-    proxy.$modal.closeLoading();
+    proxy?.$modal.closeLoading();
   }
 }
 
 // 获取文件名称
-function getFileName(name) {
+const getFileName = (name: string) => {
   // 如果是url那么取最后的名字 如果不是直接返回
   if (name.lastIndexOf("/") > -1) {
     return name.slice(name.lastIndexOf("/") + 1);
@@ -184,18 +149,62 @@ function getFileName(name) {
 }
 
 // 对象转成指定字符串分隔
-function listToString(list, separator) {
+const listToString = (list: any[], separator?: string) => {
   let strs = "";
   separator = separator || ",";
-  for (let i in list) {
-    if(list[i].ossId) {
-      strs += list[i].ossId + separator;
+  list.forEach(item => {
+    if (item.ossId) {
+      strs += item.ossId + separator;
     }
-  }
-  return strs != "" ? strs.substr(0, strs.length - 1) : "";
+  })
+  return strs != "" ? strs.substring(0, strs.length - 1) : "";
 }
 </script>
 
+<template>
+	<div class="upload-file">
+		<el-upload
+			multiple
+			:action="uploadFileUrl"
+			:before-upload="handleBeforeUpload"
+			:file-list="fileList"
+			:limit="limit"
+			:on-error="handleUploadError"
+			:on-exceed="handleExceed"
+			:on-success="handleUploadSuccess"
+			:show-file-list="false"
+			:headers="headers"
+			class="upload-file-uploader"
+			ref="fileUploadRef"
+		>
+			<!-- 上传按钮 -->
+			<el-button type="primary">选取文件</el-button>
+		</el-upload>
+		<!-- 上传提示 -->
+		<div class="el-upload__tip" v-if="showTip">
+			请上传
+			<template v-if="fileSize">
+				大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
+			</template>
+			<template v-if="fileType">
+				格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
+			</template>
+			的文件
+		</div>
+		<!-- 文件列表 -->
+		<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
+			<li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList">
+				<el-link :href="`${file.url}`" :underline="false" target="_blank">
+					<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
+				</el-link>
+				<div class="ele-upload-list__item-content-action">
+					<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
+				</div>
+			</li>
+		</transition-group>
+	</div>
+</template>
+
 <style scoped lang="scss">
 .upload-file-uploader {
   margin-bottom: 5px;

Some files were not shown because too many files changed in this diff