guojianzhe 2 lat temu
commit
7c1365f9e6
100 zmienionych plików z 7598 dodań i 0 usunięć
  1. 26 0
      .editorconfig
  2. 7 0
      .env.development
  3. 11 0
      .env.production
  4. 11 0
      .env.staging
  5. 17 0
      .eslintignore
  6. 276 0
      .eslintrc.js
  7. 30 0
      .eslintrc.json
  8. 27 0
      .gitignore
  9. 37 0
      .prettierrc
  10. 50 0
      README.md
  11. 5 0
      auto-imports.d.ts
  12. 12 0
      components.d.ts
  13. 213 0
      index.html
  14. 1 0
      legacy.d.ts
  15. 82 0
      package.json
  16. 1 0
      public/vite.svg
  17. 3 0
      src/App.vue
  18. 15 0
      src/Icons/index.ts
  19. 0 0
      src/Icons/svg/button.svg
  20. 0 0
      src/Icons/svg/cascader.svg
  21. 1 0
      src/Icons/svg/checkbox.svg
  22. 0 0
      src/Icons/svg/color.svg
  23. 0 0
      src/Icons/svg/component.svg
  24. 0 0
      src/Icons/svg/date-range.svg
  25. 0 0
      src/Icons/svg/date.svg
  26. 1 0
      src/Icons/svg/input.svg
  27. 0 0
      src/Icons/svg/number.svg
  28. 1 0
      src/Icons/svg/password.svg
  29. 1 0
      src/Icons/svg/radio.svg
  30. 1 0
      src/Icons/svg/rate.svg
  31. 0 0
      src/Icons/svg/rich-text.svg
  32. 1 0
      src/Icons/svg/row.svg
  33. 1 0
      src/Icons/svg/select.svg
  34. 1 0
      src/Icons/svg/slider.svg
  35. 1 0
      src/Icons/svg/switch.svg
  36. 1 0
      src/Icons/svg/table.svg
  37. 1 0
      src/Icons/svg/textarea.svg
  38. 0 0
      src/Icons/svg/time-range.svg
  39. 1 0
      src/Icons/svg/time.svg
  40. 1 0
      src/Icons/svg/upload.svg
  41. 140 0
      src/api/flowable/definition.ts
  42. 54 0
      src/api/flowable/demo/wzhbgnew.ts
  43. 44 0
      src/api/flowable/expression.ts
  44. 79 0
      src/api/flowable/finished.ts
  45. 68 0
      src/api/flowable/form.ts
  46. 44 0
      src/api/flowable/listener.ts
  47. 105 0
      src/api/flowable/process.ts
  48. 132 0
      src/api/flowable/todo.ts
  49. 63 0
      src/api/login.ts
  50. 13 0
      src/api/menu.ts
  51. 108 0
      src/api/request/login.ts
  52. 5 0
      src/api/request/module/Form.ts
  53. 25 0
      src/api/request/module/MenuForm.ts
  54. 7 0
      src/api/request/module/RouterList.ts
  55. 7 0
      src/api/request/module/loginForm.ts
  56. 41 0
      src/api/request/module/profile.ts
  57. 80 0
      src/api/request/monitor/cache/index.ts
  58. 113 0
      src/api/request/monitor/cache/list.ts
  59. 330 0
      src/api/request/monitor/job/index.ts
  60. 160 0
      src/api/request/monitor/job/jobLog.ts
  61. 161 0
      src/api/request/monitor/log/loginLog.ts
  62. 172 0
      src/api/request/monitor/log/operaLog.ts
  63. 72 0
      src/api/request/monitor/online/index.ts
  64. 24 0
      src/api/request/monitor/server/index.ts
  65. 210 0
      src/api/request/system/config/index.ts
  66. 284 0
      src/api/request/system/dept/index.ts
  67. 230 0
      src/api/request/system/dict/data.ts
  68. 242 0
      src/api/request/system/dict/index.ts
  69. 319 0
      src/api/request/system/menu/index.ts
  70. 225 0
      src/api/request/system/notice/notice.ts
  71. 217 0
      src/api/request/system/post/post.ts
  72. 462 0
      src/api/request/system/role/role.ts
  73. 113 0
      src/api/request/system/tool/gen/editTable.ts
  74. 103 0
      src/api/request/system/tool/gen/importTable.ts
  75. 272 0
      src/api/request/system/tool/gen/index.ts
  76. 464 0
      src/api/request/system/user/index.ts
  77. 57 0
      src/api/system/cache.ts
  78. 108 0
      src/api/system/config.ts
  79. 136 0
      src/api/system/dept.ts
  80. 61 0
      src/api/system/dict/data.ts
  81. 83 0
      src/api/system/dict/type.ts
  82. 87 0
      src/api/system/job.ts
  83. 54 0
      src/api/system/jobLog.ts
  84. 66 0
      src/api/system/logininfor.ts
  85. 133 0
      src/api/system/menu.ts
  86. 69 0
      src/api/system/notice.ts
  87. 28 0
      src/api/system/online.ts
  88. 54 0
      src/api/system/operlog.ts
  89. 83 0
      src/api/system/post.ts
  90. 179 0
      src/api/system/role.ts
  91. 13 0
      src/api/system/server.ts
  92. 207 0
      src/api/system/user.ts
  93. 137 0
      src/api/tool/gen.ts
  94. 15 0
      src/api/ym/equipment.ts
  95. BIN
      src/assets/401_images/401.gif
  96. BIN
      src/assets/404_images/404.png
  97. BIN
      src/assets/404_images/404_cloud.png
  98. 1 0
      src/assets/icons/svg/404.svg
  99. 1 0
      src/assets/icons/svg/bug.svg
  100. 1 0
      src/assets/icons/svg/build.svg

+ 26 - 0
.editorconfig

@@ -0,0 +1,26 @@
+
+# EditorConfig 有助于为不同IDE编辑器上处理同一项目的多个开发人员维护一致的编码风格
+# 告诉EditorConfig插件,这是根文件,不用继续往上查找
+root = true
+
+# 匹配全部文件
+[*]
+# 设置字符集
+charset = utf-8
+# 缩进风格,可选space、tab
+indent_style = tab
+# 缩进的空格数
+indent_size = 4
+# 结尾换行符,可选lf、cr、crlf
+end_of_line = lf
+# 在文件结尾插入新行
+insert_final_newline = true
+# 去除行首的任意空白字符
+trim_trailing_whitespace = true 
+# 删除一行中的前后空格
+trim_trailing_whitespace = true
+
+# 匹配md结尾的文件
+[*.md]
+insert_final_newline = false
+trim_trailing_whitespace = false

+ 7 - 0
.env.development

@@ -0,0 +1,7 @@
+# 页面标题
+VITE_APP_TITLE = "后台管理系统"
+
+# 开发环境配置
+VITE_APP_ENV = "development"
+
+VITE_APP_BASE_API = "/dev-api"

+ 11 - 0
.env.production

@@ -0,0 +1,11 @@
+# 页面标题
+VITE_APP_TITLE = "后台管理系统"
+
+# 生产环境配置
+VITE_APP_ENV = "production"
+
+# 若依管理系统/生产环境
+VITE_APP_BASE_API = "//localhost:8080"
+
+# 是否在打包时开启压缩,支持 gzip 和 brotli
+VITE_BUILD_COMPRESS = "gzip"

+ 11 - 0
.env.staging

@@ -0,0 +1,11 @@
+# 页面标题
+VITE_APP_TITLE = 后台管理系统
+
+# 生产环境配置
+VITE_APP_ENV = 'staging'
+
+# 若依管理系统/生产环境
+VITE_APP_BASE_API = '/stage-api'
+
+# 是否在打包时开启压缩,支持 gzip 和 brotli
+VITE_BUILD_COMPRESS = gzip

+ 17 - 0
.eslintignore

@@ -0,0 +1,17 @@
+# 忽略build目录下类型为js的文件的语法检查
+build/*.js
+# 忽略src/assets目录下文件的语法检查
+src/assets
+# 忽略public目录下文件的语法检查
+public
+# 忽略当前目录下为js的文件的语法检查
+*.js
+# 忽略当前目录下为vue的文件的语法检查
+*.vue
+node_modules
+*.sh
+*.md
+*.woff
+*.ttf
+.vscode
+.idea

+ 276 - 0
.eslintrc.js

@@ -0,0 +1,276 @@
+// ESlint 检查配置
+module.exports = {
+	root: true,
+	parserOptions: {
+		parser: "babel-eslint",
+		sourceType: "module",
+	},
+	env: {
+		browser: true,
+		node: true,
+		es6: true,
+	},
+	extends: ["plugin:vue/recommended", "eslint:recommended"],
+
+	// add your custom rules here
+	//it is base on https://github.com/vuejs/eslint-config-vue
+	rules: {
+		"vue/max-attributes-per-line": [
+			2,
+			{
+				singleline: 10,
+				multiline: {
+					max: 1,
+					allowFirstLine: false,
+				},
+			},
+		],
+		"vue/singleline-html-element-content-newline": "off",
+		"vue/multiline-html-element-content-newline": "off",
+		"vue/name-property-casing": ["error", "PascalCase"],
+		"vue/no-v-html": "off",
+		"accessor-pairs": 2,
+		"arrow-spacing": [
+			2,
+			{
+				before: true,
+				after: true,
+			},
+		],
+		"block-spacing": [2, "always"],
+		"brace-style": [
+			2,
+			"1tbs",
+			{
+				allowSingleLine: true,
+			},
+		],
+		camelcase: [
+			0,
+			{
+				properties: "always",
+			},
+		],
+		"comma-dangle": [2, "never"],
+		"comma-spacing": [
+			2,
+			{
+				before: false,
+				after: true,
+			},
+		],
+		"comma-style": [2, "last"],
+		"constructor-super": 2,
+		curly: [2, "multi-line"],
+		"dot-location": [2, "property"],
+		"eol-last": 2,
+		eqeqeq: ["error", "always", { null: "ignore" }],
+		"generator-star-spacing": [
+			2,
+			{
+				before: true,
+				after: true,
+			},
+		],
+		"handle-callback-err": [2, "^(err|error)$"],
+		indent: [
+			2,
+			2,
+			{
+				SwitchCase: 1,
+			},
+		],
+		"jsx-quotes": [2, "prefer-single"],
+		"key-spacing": [
+			2,
+			{
+				beforeColon: false,
+				afterColon: true,
+			},
+		],
+		"keyword-spacing": [
+			2,
+			{
+				before: true,
+				after: true,
+			},
+		],
+		"new-cap": [
+			2,
+			{
+				newIsCap: true,
+				capIsNew: false,
+			},
+		],
+		"new-parens": 2,
+		"no-array-constructor": 2,
+		"no-caller": 2,
+		"no-console": "off",
+		"no-class-assign": 2,
+		"no-cond-assign": 2,
+		"no-const-assign": 2,
+		"no-control-regex": 0,
+		"no-delete-var": 2,
+		"no-dupe-args": 2,
+		"no-dupe-class-members": 2,
+		"no-dupe-keys": 2,
+		"no-duplicate-case": 2,
+		"no-empty-character-class": 2,
+		"no-empty-pattern": 2,
+		"no-eval": 2,
+		"no-ex-assign": 2,
+		"no-extend-native": 2,
+		"no-extra-bind": 2,
+		"no-extra-boolean-cast": 2,
+		"no-extra-parens": [2, "functions"],
+		"no-fallthrough": 2,
+		"no-floating-decimal": 2,
+		"no-func-assign": 2,
+		"no-implied-eval": 2,
+		"no-inner-declarations": [2, "functions"],
+		"no-invalid-regexp": 2,
+		"no-irregular-whitespace": 2,
+		"no-iterator": 2,
+		"no-label-var": 2,
+		"no-labels": [
+			2,
+			{
+				allowLoop: false,
+				allowSwitch: false,
+			},
+		],
+		"no-lone-blocks": 2,
+		"no-mixed-spaces-and-tabs": 2,
+		"no-multi-spaces": 2,
+		"no-multi-str": 2,
+		"no-multiple-empty-lines": [
+			2,
+			{
+				max: 1,
+			},
+		],
+		"no-native-reassign": 2,
+		"no-negated-in-lhs": 2,
+		"no-new-object": 2,
+		"no-new-require": 2,
+		"no-new-symbol": 2,
+		"no-new-wrappers": 2,
+		"no-obj-calls": 2,
+		"no-octal": 2,
+		"no-octal-escape": 2,
+		"no-path-concat": 2,
+		"no-proto": 2,
+		"no-redeclare": 2,
+		"no-regex-spaces": 2,
+		"no-return-assign": [2, "except-parens"],
+		"no-self-assign": 2,
+		"no-self-compare": 2,
+		"no-sequences": 2,
+		"no-shadow-restricted-names": 2,
+		"no-spaced-func": 2,
+		"no-sparse-arrays": 2,
+		"no-this-before-super": 2,
+		"no-throw-literal": 2,
+		"no-trailing-spaces": 2,
+		"no-undef": 2,
+		"no-undef-init": 2,
+		"no-unexpected-multiline": 2,
+		"no-unmodified-loop-condition": 2,
+		"no-unneeded-ternary": [
+			2,
+			{
+				defaultAssignment: false,
+			},
+		],
+		"no-unreachable": 2,
+		"no-unsafe-finally": 2,
+		"no-unused-vars": [
+			2,
+			{
+				vars: "all",
+				args: "none",
+			},
+		],
+		"no-useless-call": 2,
+		"no-useless-computed-key": 2,
+		"no-useless-constructor": 2,
+		"no-useless-escape": 0,
+		"no-whitespace-before-property": 2,
+		"no-with": 2,
+		"one-var": [
+			2,
+			{
+				initialized: "never",
+			},
+		],
+		"operator-linebreak": [
+			2,
+			"after",
+			{
+				overrides: {
+					"?": "before",
+					":": "before",
+				},
+			},
+		],
+		"padded-blocks": [2, "never"],
+		quotes: [
+			2,
+			"single",
+			{
+				avoidEscape: true,
+				allowTemplateLiterals: true,
+			},
+		],
+		semi: [2, "never"],
+		"semi-spacing": [
+			2,
+			{
+				before: false,
+				after: true,
+			},
+		],
+		"space-before-blocks": [2, "always"],
+		"space-before-function-paren": [2, "never"],
+		"space-in-parens": [2, "never"],
+		"space-infix-ops": 2,
+		"space-unary-ops": [
+			2,
+			{
+				words: true,
+				nonwords: false,
+			},
+		],
+		"spaced-comment": [
+			2,
+			"always",
+			{
+				markers: [
+					"global",
+					"globals",
+					"eslint",
+					"eslint-disable",
+					"*package",
+					"!",
+					",",
+				],
+			},
+		],
+		"template-curly-spacing": [2, "never"],
+		"use-isnan": 2,
+		"valid-typeof": 2,
+		"wrap-iife": [2, "any"],
+		"yield-star-spacing": [2, "both"],
+		yoda: [2, "never"],
+		"prefer-const": 2,
+		"no-debugger": process.env.NODE_ENV === "production" ? 2 : 0,
+		"object-curly-spacing": [
+			2,
+			"always",
+			{
+				objectsInObjects: false,
+			},
+		],
+		"array-bracket-spacing": [2, "never"],
+	},
+};

+ 30 - 0
.eslintrc.json

@@ -0,0 +1,30 @@
+// https://eslint.org/docs/user-guide/configuring
+
+{
+    "extends": [
+      "eslint:recommended",
+      "plugin:vue/vue3-recommended",
+      "prettier"
+    ],
+    // required to lint *.vue files
+    "plugins": [
+      "vue"
+    ],
+    // add your custom rules here
+    "rules": {
+      // allow async-await
+      "generator-star-spacing": "off",
+      // allow debugger during development
+    //   "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
+      "no-labels": ["warn", {"allowLoop": true}],
+      "no-unused-vars": "off",
+      "vue/no-mutating-props": "off",
+      "vue/require-default-prop": "off",
+      "vue/no-unused-vars": "off",
+      "vue/prop-name-casing": "off",
+      "vue/attribute-hyphenation": "off",
+      "vue/no-template-shadow": "off",
+      "vue/component-definition-name-casing": "off"
+    }
+  }
+  

+ 27 - 0
.gitignore

@@ -0,0 +1,27 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+package-lock.json
+yarn.lock

+ 37 - 0
.prettierrc

@@ -0,0 +1,37 @@
+{
+    "bracketSameLine": false,
+    // 大括号内的首尾需要空格
+    "bracketSpacing": true,
+    // 一行最多 100 字符
+    "printWidth": 200,
+    // 使用 2 个空格缩进
+    "tabWidth": 4,
+    // 不使用缩进符,而使用空格
+    "useTabs": false,
+    // 行尾需要有分号
+    "semi": true,
+    // 使用单引号
+    "singleQuote": false,
+    // 对象的 key 仅在必要时用引号
+    "quoteProps": "as-needed",
+    // jsx 不使用单引号,而使用双引号
+    "jsxSingleQuote": false,
+    // 末尾不需要逗号
+    "trailingComma": "es5",
+    // jsx 标签的反尖括号需要换行
+    "jsxBracketSameLine": false,
+    // 箭头函数,只有一个参数的时候,也需要括号
+    "arrowParens": "avoid",
+    // 不需要写文件开头的 @prettier
+    "requirePragma": false,
+    // 不需要自动在文件开头插入 @prettier
+    "insertPragma": false,
+    // 当超出print width(上面有这个参数)时就折行
+    "proseWrap": "preserve",
+    // 根据显示样式决定 html 要不要折行
+    "htmlWhitespaceSensitivity": "css",
+    // 换行符使用 lf
+    "endOfLine": "lf",
+    // 在VUE文件中不要缩进脚本和样式标记
+    "vueIndentScriptAndStyle": false
+}

+ 50 - 0
README.md

@@ -0,0 +1,50 @@
+<p align="center">
+	<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
+</p>
+<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.3</h1>
+<h4 align="center">基于SpringBoot+Vue3前后端分离的Java快速开发框架</h4>
+<p align="center">
+	<a href="https://gitee.com/y_project/RuoYi-Vue/stargazers" target="_blank"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"/></a>
+	<a href="https://gitee.com/y_project/RuoYi-Vue" target="_blank"><img src="https://img.shields.io/badge/RuoYi-v3.8.3-brightgreen.svg"/></a>
+	<a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE" target="_blank"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"/></a>
+</p>
+
+## 平台简介
+
+* 本仓库为前端技术栈 <a href="https://v3.cn.vuejs.org" target="_blank">Vue3</a> + <a href="https://element-plus.org/zh-CN" target="_blank">Element Plus</a> + <a href="https://cn.vitejs.dev" target="_blank">Vite</a> 版本。
+* 配套后端代码仓库地址[RuoYi-Vue](https://gitee.com/lyforvue/ruoyi_vue3_ts) 中的ruoyi目录。
+* 前端技术栈【<a href="https://cn.vuejs.org" target="_blank">Vue2</a> + <a href="https://element.eleme.cn/#/zh-CN" target="_blank">ElementUI</a> + <a href="https://cli.vuejs.org/zh" target="_blank">Vue CLI</a>】,请移步:<a href="https://gitee.com/y_project/RuoYi-Vue/tree/master/ruoyi-ui" target="_blank">RuoYi-Vue</a>。
+* 阿里云折扣场:<a href="http://aly.ruoyi.vip" target="_blank">点我进入</a>,腾讯云秒杀场:<a href="http://txy.ruoyi.vip" target="_blank">点我进入</a>
+* 阿里云优惠券:<a href="https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link" target="_blank">点我领取</a>,腾讯云优惠券:<a href="https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console" target="_blank">点我领取</a>
+
+## 前端运行
+
+```bash
+# 克隆项目
+git clone https://gitee.com/lyforvue/ruoyi_vue3_ts.git
+
+# 进入项目目录
+cd ruoyi_vue3_ts
+
+# 安装依赖
+npm install
+
+# 不建议使用cnpm安装依赖,可能会出现莫名其妙的问题,npm依赖安装比较慢使用如下方式
+npm install --registry=https://registry.npmmirror.com
+
+# 启动服务
+npm run dev
+
+# 需要修改端口请自行改动vite.config.ts中server中的port的值
+```
+浏览器访问 <a href="http://localhost:7000" target="_blank">http://localhost:7000</a>
+
+## 发布
+
+```bash
+# 构建测试环境
+npm run build:stage
+
+# 构建生产环境
+npm run build:prod
+```

+ 5 - 0
auto-imports.d.ts

@@ -0,0 +1,5 @@
+// Generated by 'unplugin-auto-import'
+export {}
+declare global {
+
+}

+ 12 - 0
components.d.ts

@@ -0,0 +1,12 @@
+// generated by unplugin-vue-components
+// We suggest you to commit this file into source control
+// Read more: https://github.com/vuejs/core/pull/3399
+import '@vue/runtime-core'
+
+export {}
+
+declare module '@vue/runtime-core' {
+  export interface GlobalComponents {
+    
+  }
+}

+ 213 - 0
index.html

@@ -0,0 +1,213 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <!-- <title>Vite + Vue + TS</title> -->
+    <title>若依管理系统</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>

+ 1 - 0
legacy.d.ts

@@ -0,0 +1 @@
+declare module 'vue3-treeselect';

+ 82 - 0
package.json

@@ -0,0 +1,82 @@
+{
+  "name": "ruoyi_ui_ts",
+  "private": true,
+  "version": "0.0.0",
+  "type": "module",
+  "scripts": {
+    "dev": "vite --host",
+    "build": "vue-tsc --noEmit && vite build ",
+    "build:prod": "vite build --mode production",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "@element-plus/icons-vue": "^2.0.5",
+    "@typescript-eslint/eslint-plugin": "^5.19.0",
+    "@typescript-eslint/parser": "^5.19.0",
+    "bpmn-js": "^13.2.0",
+    "bpmn-js-bpmnlint": "^0.20.1",
+    "bpmnlint": "^8.2.0",
+    "bpmnlint-loader": "^0.1.6",
+    "diagram-js": "^12.2.0",
+    "file-drops": "^0.5.0",
+    "pinia-plugin-persist": "^1.0.0",
+    "vkbeautify": "^0.99.3",
+    "vue": "^3.2.35",
+    "vue3-treeselect": "^0.1.10",
+    "xcrud": "^0.4.19"
+  },
+  "devDependencies": {
+    "@highlightjs/vue-plugin": "^2.1.0",
+    "@types/file-saver": "^2.0.5",
+    "@types/inherits": "^0.0.30",
+    "@types/js-cookie": "^3.0.2",
+    "@types/node": "^17.0.21",
+    "@types/nprogress": "^0.2.0",
+    "@vitejs/plugin-vue": "^2.2.0",
+    "@vitejs/plugin-vue-jsx": "^1.3.7",
+    "@vue/compiler-sfc": "^3.2.36",
+    "@vueuse/core": "^8.5.0",
+    "axios": "^0.27.2",
+    "consola": "^2.15.3",
+    "core-js": "^3.23.5",
+    "cron-validator": "^1.3.1",
+    "echarts": "^5.3.3",
+    "element-plus": "^2.2.5",
+    "eslint": "^8.14.0",
+    "eslint-plugin-vue": "^8.6.0",
+    "fast-glob": "^3.2.11",
+    "file-saver": "^2.0.5",
+    "fuse.js": "^6.6.2",
+    "js-cookie": "^3.0.1",
+    "jsencrypt": "^3.2.1",
+    "nanoid": "^4.0.0",
+    "nprogress": "^0.2.0",
+    "pinia": "^2.0.16",
+    "quill": "^1.3.7",
+    "sass": "^1.52.1",
+    "screenfull": "^6.0.2",
+    "sortablejs": "^1.14.0",
+    "typescript": "^4.6.4",
+    "unplugin-auto-import": "^0.9.3",
+    "unplugin-vue-components": "^0.21.1",
+    "vite": "^2.9.9",
+    "vite-plugin-compression": "^0.5.1",
+    "vite-plugin-style-import": "^2.0.0",
+    "vite-plugin-svg-icons": "^2.0.1",
+    "vite-plugin-vue-setup-extend": "^0.4.0",
+    "vite-svg-loader": "^3.4.0",
+    "vue-clipboard3": "^2.0.0",
+    "vue-cropper": "^1.0.5",
+    "vue-router": "^4.1.2",
+    "vue-tsc": "^0.38.4",
+    "vue3-highlightjs": "^1.0.5"
+  },
+  "browserslist": [
+    "> 1%",
+    "not ie 11",
+    "not op_mini all"
+  ],
+  "engines": {
+    "node": ">= 14"
+  }
+}

+ 1 - 0
public/vite.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

+ 3 - 0
src/App.vue

@@ -0,0 +1,3 @@
+<template>
+    <router-view />
+</template>

+ 15 - 0
src/Icons/index.ts

@@ -0,0 +1,15 @@
+import { defineComponent } from "vue";
+import SvgIcon from "@/components/SvgIcon.vue"; // svg component
+
+// export default defineComponent({
+// 	components: {
+// 		"svg-icon": SvgIcon,
+// 	},
+// 	mounted() {
+// 		const req = require.context("./svg", false, /.svg$/);
+// 		const requireAll = (
+// 			requireContext: __WebpackModuleApi.RequireContext
+// 		) => requireContext.keys().map(requireContext);
+// 		requireAll(req);
+// 	},
+// });

Plik diff jest za duży
+ 0 - 0
src/Icons/svg/button.svg


Plik diff jest za duży
+ 0 - 0
src/Icons/svg/cascader.svg


+ 1 - 0
src/Icons/svg/checkbox.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575982282951" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="902" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M828.40625 90.125H195.59375C137.375 90.125 90.125 137.375 90.125 195.59375v632.8125c0 58.21875 47.25 105.46875 105.46875 105.46875h632.8125c58.21875 0 105.46875-47.25 105.46875-105.46875V195.59375c0-58.21875-47.25-105.46875-105.46875-105.46875z m52.734375 738.28125c0 29.16-23.57015625 52.734375-52.734375 52.734375H195.59375c-29.109375 0-52.734375-23.574375-52.734375-52.734375V195.59375c0-29.109375 23.625-52.734375 52.734375-52.734375h632.8125c29.16 0 52.734375 23.625 52.734375 52.734375v632.8125z" p-id="903"></path><path d="M421.52890625 709.55984375a36.28125 36.28125 0 0 1-27.55265625-12.66890625L205.17453125 476.613125a36.28546875 36.28546875 0 0 1 55.10109375-47.22890625l164.986875 192.4846875 342.16171875-298.48078125a36.2896875 36.2896875 0 0 1 47.70984375 54.68765625L445.3859375 700.6203125a36.3234375 36.3234375 0 0 1-23.85703125 8.93953125z" p-id="904"></path></svg>

Plik diff jest za duży
+ 0 - 0
src/Icons/svg/color.svg


Plik diff jest za duży
+ 0 - 0
src/Icons/svg/component.svg


Plik diff jest za duży
+ 0 - 0
src/Icons/svg/date-range.svg


Plik diff jest za duży
+ 0 - 0
src/Icons/svg/date.svg


+ 1 - 0
src/Icons/svg/input.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575802859706" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3102" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896 224H128c-35.2 0-64 28.8-64 64v448c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V288c0-35.2-28.8-64-64-64z m0 480c0 19.2-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V320c0-19.2 12.8-32 32-32h704c19.2 0 32 12.8 32 32v384z" p-id="3103"></path><path d="M224 352c-19.2 0-32 12.8-32 32v256c0 16 12.8 32 32 32s32-12.8 32-32V384c0-16-12.8-32-32-32z" p-id="3104"></path></svg>

Plik diff jest za duży
+ 0 - 0
src/Icons/svg/number.svg


+ 1 - 0
src/Icons/svg/password.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575802846045" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2750" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M868.593046 403.832442c-30.081109-28.844955-70.037123-44.753273-112.624057-44.753273L265.949606 359.079168c-42.554188 0-82.510202 15.908318-112.469538 44.690852-30.236652 28.782533-46.857191 67.222007-46.857191 108.198258l0 294.079782c0 40.977273 16.619516 79.414701 46.702672 108.136859 29.959336 28.844955 70.069869 44.814672 112.624057 44.814672l490.019383 0c42.585911 0 82.696444-15.969717 112.624057-44.814672 30.082132-28.844955 46.579875-67.222007 46.579875-108.136859L915.172921 511.968278C915.171897 471.053426 898.675178 432.677397 868.593046 403.832442zM841.821309 806.049083c0 22.098297-8.882298 42.772152-25.099654 58.306964-16.154935 15.661701-37.81935 24.203238-60.752666 24.203238L265.949606 888.559285c-22.934339 0-44.567032-8.54256-60.877509-24.264637-16.186657-15.474436-25.067932-36.148291-25.067932-58.246589L180.004165 511.968278c0-22.035876 8.881274-42.772152 25.192775-58.307987 16.186657-15.536858 37.81935-24.139793 60.753689-24.139793l490.019383 0c22.933315 0 44.597731 8.602935 60.752666 24.139793 16.21838 15.535835 25.099654 36.272112 25.099654 58.307987L841.822332 806.049083zM510.974136 135.440715c114.914216 0 208.318536 89.75214 208.318536 200.055338l73.350588 0c0-149.113109-126.366036-270.496667-281.669124-270.496667-155.333788 0-281.699824 121.383558-281.699824 270.496667l73.350588 0C302.623877 225.193879 396.059919 135.440715 510.974136 135.440715zM474.299865 747.244792l73.350588 0L547.650453 629.576859l-73.350588 0L474.299865 747.244792z" p-id="2751"></path></svg>

+ 1 - 0
src/Icons/svg/radio.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575966775973" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="879" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M507.39346659 71.84873358c241.53533667 0 437.39770766 195.85422109 437.39770767 437.37442191 0 241.53766571-195.86237099 437.38955776-437.39770767 437.38955776-241.50040803 0-437.34997219-195.85189205-437.34997219-437.38955776C70.0434944 267.70295467 265.89189347 71.84873358 507.39346659 71.84873358L507.39346659 71.84873358zM507.39346659 282.81899805c-125.00686734 0-226.37039389 101.38914133-226.37039388 226.41813048 0 125.01268821 101.36352768 226.39717262 226.37039388 226.39717262 125.04295993 0 226.42395136-101.38448441 226.42395136-226.39717262C733.81625401 384.20813938 632.43642653 282.81899805 507.39346659 282.81899805L507.39346659 282.81899805zM507.39346659 120.78172615c-214.46664192 0-388.42047261 173.95150279-388.4204726 388.44026539 0 214.51204949 173.95499463 388.46122325 388.4204726 388.46122325 214.52369237 0 388.46005817-173.94800981 388.46005818-388.46122325C895.85236082 294.73322894 721.91715897 120.78172615 507.39346659 120.78172615z" p-id="880"></path></svg>

+ 1 - 0
src/Icons/svg/rate.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577246781606" class="icon" viewBox="0 0 1069 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1098" xmlns:xlink="http://www.w3.org/1999/xlink" width="84.5595703125" height="81"><defs><style type="text/css"></style></defs><path d="M633.72929961 378.02038203l9.49872568 18.68789795 20.78025469 2.79745225 206.61592412 27.33248408a11.46496817 11.46496817 0 0 1 6.6095543 19.47324902l-147.2675168 147.35350284-14.89299345 14.89299345 3.8006376 20.68280244 37.84585956 204.89044571a11.46496817 11.46496817 0 0 1-16.4808914 12.2961788L554.68980898 751.84713388l-18.68789794-9.49299345-18.48726123 9.99171915-183.23885392 99.34968163a11.46496817 11.46496817 0 0 1-16.78471347-11.8662416l32.5433127-205.79617881 3.29617793-20.78598692-15.19108243-14.49172002-151.03375839-143.48407587a11.46496817 11.46496817 0 0 1 6.09936328-19.63949062l205.79617881-32.63503185 20.78598691-3.2961788L428.87898125 380.72038203 518.59235674 192.64331182a11.46496817 11.46496817 0 0 1 20.56815264-0.26369385l94.56879023 185.63503183zM496.64840732 85.52038203l-121.75796162 254.98089229L95.76433145 384.76178369A34.3949045 34.3949045 0 0 0 77.46050938 443.66879023l204.87324901 194.66369385-44.16879023 279.1146498a34.3949045 34.3949045 0 0 0 50.36560489 35.61592325l248.4-134.67898038 251.84522285 128.27579591a34.3949045 34.3949045 0 0 0 49.43694287-36.89426777l-51.30573223-277.85350284 199.73120977-199.90891758a34.3949045 34.3949045 0 0 0-19.82866201-58.40827998l-280.11783428-37.03184736L558.32993633 84.71210205a34.3949045 34.3949045 0 0 0-61.68152901 0.80254775z" p-id="1099"></path></svg>

Plik diff jest za duży
+ 0 - 0
src/Icons/svg/rich-text.svg


+ 1 - 0
src/Icons/svg/row.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1579339929870" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1182" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M152 854.856875h325.7146875V237.715625H134.856875v600q0 6.99375 5.0746875 12.0684375T152 854.856875z m737.143125-17.1421875v-600H546.284375v617.1421875H872q6.99375 0 12.0684375-5.07375t5.0746875-12.0684375z m68.5715625-651.429375V837.715625q0 35.3821875-25.16625 60.5484375T872 923.4284375H152q-35.383125 0-60.5484375-25.1653125T66.284375 837.7146875V186.284375q0-35.3821875 25.16625-60.5484375T152 100.5715625h720q35.383125 0 60.5484375 25.1653125t25.16625 60.5484375z" p-id="1183"></path></svg>

+ 1 - 0
src/Icons/svg/select.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575803481213" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="804" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M62 511.97954521C62 263.86590869 263.90681826 62 511.97954521 62s449.97954521 201.825 449.97954521 449.97954521c0 248.19545479-201.90681826 449.97954521-449.97954521 449.97954521C263.90681826 962 62 760.175 62 511.97954521M901.98636348 511.97954521c0-215.24318174-175.00909131-390.41590869-390.00681827-390.41590869-215.03863652 0-389.96590869 175.17272695-389.96590868 390.41590869 0 215.28409131 175.00909131 390.45681826 389.96590868 390.45681826C727.01818174 902.47727305 901.98636348 727.30454521 901.98636348 511.97954521M264.17272695 430.28409131c0-5.76818174 2.12727305-11.51590869 6.64772696-15.87272696 8.71363652-8.75454521 22.88863652-8.75454521 31.725 0l209.4340913 208.22727305L721.45454521 414.53409131c8.75454521-8.71363652 22.97045479-8.71363652 31.90909132 0 8.71363652 8.75454521 8.71363652 22.88863652 0 31.60227304L511.97954521 685.74090869 270.71818174 446.01363653C266.27954521 441.77954521 264.17272695 436.05227305 264.17272695 430.28409131" p-id="805"></path></svg>

+ 1 - 0
src/Icons/svg/slider.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577185310368" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1238" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M951.453125 476.84375H523.671875a131.8359375 131.8359375 0 0 0-254.1796875 0H72.546875v70.3125h196.9453125a131.8359375 131.8359375 0 0 0 254.1796875 0H951.453125z" p-id="1239"></path></svg>

+ 1 - 0
src/Icons/svg/switch.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1576042673958" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1110" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M692 792H332c-150 0-270-120-270-270s120-270 270-270h360c150 0 270 120 270 270 0 147-120 270-270 270zM332 312c-117 0-210 93-210 210s93 210 210 210h360c117 0 210-93 210-210s-93-210-210-210H332z" p-id="1111"></path><path d="M341 522m-150 0a150 150 0 1 0 300 0 150 150 0 1 0-300 0Z" p-id="1112"></path></svg>

+ 1 - 0
src/Icons/svg/table.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1595774196464" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4269" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M856.187 65.711H167.215c-56.054 0-101.554 45.5-101.554 101.554v688.972c0 56.054 45.5 101.554 101.554 101.554h688.972c56.054 0 101.554-45.5 101.554-101.554V167.265c0-56.054-45.5-101.554-101.554-101.554z m-677.024 51.773H844.24c34.05 0 61.729 27.678 61.729 61.728v183.594H117.434V179.212c0-34.05 27.678-61.728 61.729-61.728z m217.046 297.094H634.66v219.934H396.209V414.578z m-51.773 219.834H117.434V414.578h227.002v219.834z m341.997-219.834H905.97v219.934H686.433V414.578z m157.807 491.44H179.163c-34.05 0-61.73-27.678-61.73-61.728V686.185h227.003v219.833h51.773V686.185H634.66v219.833h51.772V686.185H905.97V844.29c0 34.05-27.679 61.728-61.729 61.728z" p-id="4270"></path></svg>

+ 1 - 0
src/Icons/svg/textarea.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575802855098" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2984" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896 160H128c-35.2 0-64 28.8-64 64v576c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V224c0-35.2-28.8-64-64-64z m0 608c0 16-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V256c0-16 12.8-32 32-32h704c19.2 0 32 12.8 32 32v512z" p-id="2985"></path><path d="M224 288c-19.2 0-32 12.8-32 32v256c0 16 12.8 32 32 32s32-12.8 32-32V320c0-16-12.8-32-32-32z m608 480c19.2 0 32-12.8 32-32V608L704 768h128z" p-id="2986"></path></svg>

Plik diff jest za duży
+ 0 - 0
src/Icons/svg/time-range.svg


+ 1 - 0
src/Icons/svg/time.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577099827399" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1008" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M520 559h204c17.673 0 32 14.327 32 32 0 17.673-14.327 32-32 32H488c-17.673 0-32-14.327-32-32 0-0.167 0.001-0.334 0.004-0.5a32.65 32.65 0 0 1-0.004-0.5V277c0-17.673 14.327-32 32-32 17.673 0 32 14.327 32 32v282z m-8 401C264.576 960 64 759.424 64 512S264.576 64 512 64s448 200.576 448 448-200.576 448-448 448z m0-64c212.077 0 384-171.923 384-384S724.077 128 512 128 128 299.923 128 512s171.923 384 384 384z" p-id="1009"></path></svg>

+ 1 - 0
src/Icons/svg/upload.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577540289643" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7922" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M530.944 458.24l4.8 3.456 122.176 106.816a32 32 0 0 1-37.44 51.584l-4.672-3.392L546.56 556.16v280.704a32 32 0 0 1-26.24 31.488l-5.76 0.512a32 32 0 0 1-31.424-26.24l-0.512-5.76-0.064-280.704-69.12 60.48a32 32 0 0 1-40.96 0.896l-4.16-3.968a32 32 0 0 1-0.96-40.96l4.032-4.16 122.176-106.816a32 32 0 0 1 37.312-3.456zM497.92 128c128.128 0 239.168 82.304 275.52 199.04 123.968 11.264 221.312 113.088 221.312 237.44 0 128.128-103.68 232.96-234.88 238.272h-5.888l-35.52 0.192a32 32 0 0 1-0.192-64l35.264-0.128 4.672-0.064c96.384-3.84 172.544-80.896 172.544-174.272 0-96.128-80.512-174.464-179.584-174.464h-1.984a32 32 0 0 1-32-25.28C695.872 264.96 604.736 192 497.92 192 381.824 192 285.44 277.76 274.816 388.48a32 32 0 0 1-28.352 28.8c-83.968 9.152-147.84 78.208-147.84 159.552l0.192 7.936c3.84 85.76 77.056 154.112 166.592 154.112h45.632a32 32 0 0 1 0 64h-45.632C142.016 802.944 40.32 708.032 34.88 586.88l-0.192-9.28c0-106.88 76.352-197.184 179.968-219.904C239.488 226.112 357.76 128 497.856 128z" p-id="7923"></path></svg>

+ 140 - 0
src/api/flowable/definition.ts

@@ -0,0 +1,140 @@
+import request from "@/utils/request";
+
+// 查询流程定义列表
+export const listDefinition = async (query: any) => {
+  return await request({
+    url: '/flowable/definition/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 部署流程实例
+export const definitionStart = async (procDefId: string, data: any) => {
+  return await request({
+    url: '/flowable/definition/start/' + procDefId,
+    method: 'post',
+    data: data
+  })
+}
+
+// 获取流程变量
+export const getProcessVariables = async (taskId: string) => {
+	return await request({
+		url: "/flowable/task/processVariables/" + taskId,
+		method: "get",
+	});
+};
+
+// 激活/挂起流程
+export const updateState = async (params: any) => {
+  return await request({
+    url: '/flowable/definition/updateState',
+    method: 'put',
+    params: params
+  })
+}
+
+// 指定流程办理人员列表
+export const userList = async (query: any) => {
+  return await request({
+		url: "/flowable/definition/userList",
+		method: "get",
+		params: query,
+  });
+}
+
+// 指定流程办理组列表
+export const roleList = async (query: any) => {
+	return await request({
+		url: "/flowable/definition/roleList",
+		method: "get",
+		params: query,
+	});
+};
+
+// 指定流程表达式
+export const expList = async (query: any) => {
+	return await request({
+		url: "/flowable/definition/expList",
+		method: "get",
+		params: query,
+	});
+};
+
+// 读取xml文件
+export const readXml = async (deployId: string) => {
+	return await request({
+		url: "/flowable/definition/readXml/" + deployId,
+		method: "get",
+	});
+};
+
+// 读取image文件
+export const readImage = async (deployId: string) => {
+	return await request({
+		url: "/flowable/definition/readImage/" + deployId,
+		method: "get",
+	});
+};
+
+// 获取流程执行节点
+export const getFlowViewer = async (procInsId: string, executionId: string) => {
+	return await request({
+		url: "/flowable/task/flowViewer/" + procInsId + "/" + executionId,
+		method: "get",
+	});
+};
+
+// 流程节点数据
+export const flowXmlAndNode = async (query: any) => {
+	return await request({
+		url: "/flowable/task/flowXmlAndNode",
+		method: "get",
+		params: query,
+	});
+};
+
+// 读取xml文件
+export const saveXml = async (data: any) => {
+	return await request({
+		url: "/flowable/definition/save",
+		method: "post",
+		data: data,
+	});
+};
+
+// 新增流程定义
+export const addDeployment = async (data: any) => {
+	return await request({
+		url: "/system/deployment",
+		method: "post",
+		data: data,
+	});
+};
+
+// 修改流程定义
+export const updateDeployment = async (data: any) => {
+	return await request({
+		url: "/system/deployment",
+		method: "put",
+		data: data,
+	});
+};
+
+// 删除流程定义
+export const delDeployment = async (deployId: string) => {
+	return await request({
+		url: "/flowable/definition/" + deployId,
+		method: "delete",
+	});
+};
+
+// 导出流程定义
+export const exportDeployment = async (query: any) => {
+	return await request({
+		url: "/system/deployment/export",
+		method: "get",
+		params: query,
+	});
+};

+ 54 - 0
src/api/flowable/demo/wzhbgnew.ts

@@ -0,0 +1,54 @@
+import request from "@/utils/request";
+
+// 查询无纸化办公(申请)列表
+export const listApply = async (query: any) => {
+	return await request({
+		url: "/demo/apply/list",
+		method: "get",
+		params: query,
+	});
+};
+
+// 查询无纸化办公(申请)详细
+export const getApply = async (query: any) => {
+	return await request({
+		url: "/demo/apply/getinfo",
+		method: "get",
+		params: query,
+	});
+};
+
+// 新增无纸化办公(申请)
+export const addApply = async (data: any) => {
+	return await request({
+		url: "/demo/apply/add",
+		method: "post",
+		data: data,
+	});
+};
+
+// 修改无纸化办公(申请)
+export const updateApply = async (data: any) => {
+	return await request({
+		url: "/demo/apply/edit",
+		method: "put",
+		data: data,
+	});
+};
+
+// 删除无纸化办公(申请)
+export const delApply = async (id: string) => {
+	return await request({
+		url: "/demo/apply/" + id,
+		method: "delete",
+	});
+};
+
+// 查询无纸化办公(申请)详细
+export const getApplyByTask = async (query: any) => {
+	return await request({
+		url: "/demo/apply/getInfoByTask",
+		method: "get",
+		params: query,
+	});
+};

+ 44 - 0
src/api/flowable/expression.ts

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询流程达式列表
+export const listExpression = async (query: any) => {
+  return await request({
+    url: '/flowable/expression/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询流程达式详细
+export const getExpression = async (id: string) => {
+	return await request({
+		url: "/flowable/expression/" + id,
+		method: "get",
+	});
+};
+
+// 新增流程达式
+export const addExpression = async (data: any) => {
+	return await request({
+		url: "/flowable/expression",
+		method: "post",
+		data: data,
+	});
+};
+
+// 修改流程达式
+export const updateExpression = async (data: any) => {
+	return await request({
+		url: "/flowable/expression",
+		method: "put",
+		data: data,
+	});
+};
+
+// 删除流程达式
+export const delExpression = async (id: string) => {
+	return await request({
+		url: "/flowable/expression/" + id,
+		method: "delete",
+	});
+};

+ 79 - 0
src/api/flowable/finished.ts

@@ -0,0 +1,79 @@
+import request from '@/utils/request'
+
+// 查询已办任务列表
+export const finishedList = async (query: any) => {
+  return await request({
+    url: '/flowable/task/finishedList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 任务流转记录
+export const flowRecord = async (query: any) => {
+	return await request({
+		url: "/flowable/task/flowRecord",
+		method: "get",
+		params: query,
+	});
+};
+
+// 撤回任务
+export const revokeProcess = async (data: any) => {
+	return await request({
+		url: "/flowable/task/revokeProcess",
+		method: "post",
+		data: data,
+	});
+};
+
+// 部署流程实例
+export const deployStart = async (deployId: string) => {
+	return await request({
+		url: "/flowable/process/startFlow/" + deployId,
+		method: "get",
+	});
+};
+
+// 查询流程定义详细
+export const getDeployment = async (id: string) => {
+	return await request({
+		url: "/system/deployment/" + id,
+		method: "get",
+	});
+};
+
+// 新增流程定义
+export const addDeployment = async (data: any) => {
+	return await request({
+		url: "/system/deployment",
+		method: "post",
+		data: data,
+	});
+};
+
+// 修改流程定义
+export const updateDeployment = async (data: any) => {
+	return await request({
+		url: "/system/deployment",
+		method: "put",
+		data: data,
+	});
+};
+
+// 删除流程定义
+export const delDeployment = async (id: string) => {
+	return await request({
+		url: "/flowable/instance/delete/" + id,
+		method: "delete",
+	});
+};
+
+// 导出流程定义
+export const exportDeployment = async (query: any) => {
+	return await request({
+		url: "/system/deployment/export",
+		method: "get",
+		params: query,
+	});
+};

+ 68 - 0
src/api/flowable/form.ts

@@ -0,0 +1,68 @@
+import request from '@/utils/request'
+
+// 查询流程表单列表
+export const listForm = async (query: any) => {
+  return await request({
+    url: '/flowable/form/list',
+    method: 'get',
+    params: query
+  })
+}
+export const listAllForm = async (query: any) => {
+	return await request({
+		url: "/flowable/form/formList",
+		method: "get",
+		params: query,
+	});
+};
+
+// 查询流程表单详细
+export const getForm = async (formId: string) => {
+	return await request({
+		url: "/flowable/form/" + formId,
+		method: "get",
+	});
+}
+
+// 新增流程表单
+export const addForm = async (data: any) => {
+	return await request({
+		url: "/flowable/form",
+		method: "post",
+		data: data,
+	});
+}
+
+// 修改流程表单
+export const updateForm = async (data: any) => {
+	return await request({
+		url: "/flowable/form",
+		method: "put",
+		data: data,
+	});
+}
+// 挂载表单
+export const addDeployForm = async (data: any) => {
+	return await request({
+		url: "/flowable/form/addDeployForm",
+		method: "post",
+		data: data,
+	});
+}
+
+// 删除流程表单
+export const delForm = async (formId: string) => {
+	return await request({
+		url: "/flowable/form/" + formId,
+		method: "delete",
+	});
+}
+
+// 导出流程表单
+export const exportForm = async (query: any) => {
+	return await request({
+		url: "/flowable/form/export",
+		method: "get",
+		params: query,
+	});
+};

+ 44 - 0
src/api/flowable/listener.ts

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询流程监听列表
+export const listListener = async (query: any) => {
+  return await request({
+    url: '/flowable/listener/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询流程监听详细
+export const getListener = async (id: string) => {
+	return await request({
+		url: "/flowable/listener/" + id,
+		method: "get",
+	});
+}
+
+// 新增流程监听
+export const addListener = async (data: any) => {
+	return await request({
+		url: "/flowable/listener",
+		method: "post",
+		data: data,
+	});
+}
+
+// 修改流程监听
+export const updateListener = async (data: any) => {
+	return await request({
+		url: "/flowable/listener",
+		method: "put",
+		data: data,
+	});
+}
+
+// 删除流程监听
+export const delListener = async (id: string) => {
+	return await request({
+		url: "/flowable/listener/" + id,
+		method: "delete",
+	});
+};

+ 105 - 0
src/api/flowable/process.ts

@@ -0,0 +1,105 @@
+import request from '@/utils/request'
+
+// 我的发起的流程
+export const myProcessList = async (query: any) => {
+	return await request({
+		url: "/flowable/task/myProcess",
+		method: "get",
+		params: query,
+	});
+}
+
+export const flowFormData = async (query: any) => {
+	return await request({
+		url: "/flowable/task/flowFormData",
+		method: "get",
+		params: query,
+	});
+};
+
+// 完成任务
+export const complete = async (data: any) => {
+	return request({
+		url: "/flowable/task/complete",
+		method: "post",
+		data: data,
+	});
+}
+
+// 取消申请
+export const stopProcess = async (data: any) => {
+	return request({
+		url: "/flowable/task/stopProcess",
+		method: "post",
+		data: data,
+	});
+}
+
+// 驳回任务
+export const rejectTask = async (data: any) => {
+	return request({
+		url: "/flowable/task/reject",
+		method: "post",
+		data: data,
+	});
+}
+
+// 可退回任务列表
+export const returnList = async (data: any) => {
+	return request({
+		url: "/flowable/task/returnList",
+		method: "post",
+		data: data,
+	});
+}
+
+// 部署流程实例
+export const deployStart = async (deployId: string) => {
+	return request({
+		url: "/flowable/process/startFlow/" + deployId,
+		method: "get",
+	});
+}
+
+// 查询流程定义详细
+export const getDeployment = async (id: string) => {
+	return request({
+		url: "/system/deployment/" + id,
+		method: "get",
+	});
+}
+
+// 新增流程定义
+export const addDeployment = async (data: any) => {
+	return request({
+		url: "/system/deployment",
+		method: "post",
+		data: data,
+	});
+}
+
+// 修改流程定义
+export const updateDeployment = async (data: any) => {
+	return request({
+		url: "/system/deployment",
+		method: "put",
+		data: data,
+	});
+}
+
+// 删除流程定义
+export const delDeployment = async (id: string) => {
+	return request({
+		url: "/system/deployment/" + id,
+		method: "delete",
+	});
+}
+
+// 导出流程定义
+export const exportDeployment = async (query: any) => {
+	return request({
+		url: "/system/deployment/export",
+		method: "get",
+		params: query,
+	});
+};

+ 132 - 0
src/api/flowable/todo.ts

@@ -0,0 +1,132 @@
+import request from '@/utils/request'
+
+// 查询待办任务列表
+export const todoList = async (query: any) => {
+  return await request({
+    url: '/flowable/task/todoList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 完成任务
+export const complete = async (data: any) => {
+	return await request({
+		url: "/flowable/task/complete",
+		method: "post",
+		data: data,
+	});
+}
+
+// 委派任务
+export const delegate = async (data: any) => {
+	return await request({
+		url: "/flowable/task/delegate",
+		method: "post",
+		data: data,
+	});
+}
+
+// 退回任务
+export const returnTask = async (data: any) => {
+	return await request({
+		url: "/flowable/task/return",
+		method: "post",
+		data: data,
+	});
+}
+
+// 驳回任务
+export const rejectTask = async (data: any) => {
+	return await request({
+		url: "/flowable/task/reject",
+		method: "post",
+		data: data,
+	});
+}
+
+// 可退回任务列表
+export const returnList = async (data: any) => {
+	return await request({
+		url: "/flowable/task/returnList",
+		method: "post",
+		data: data,
+	});
+}
+
+// 下一节点
+export const getNextFlowNode = async (data: any) => {
+	return await request({
+		url: "/flowable/task/nextFlowNode",
+		method: "post",
+		data: data,
+	});
+}
+
+// 下一节点
+export const getNextFlowNodeByStart = async (data: any) => {
+	return await request({
+		url: "/flowable/task/nextFlowNodeByStart",
+		method: "post",
+		data: data,
+	});
+}
+
+// 部署流程实例
+export const deployStart = async (deployId: string) => {
+	return await request({
+		url: "/flowable/process/startFlow/" + deployId,
+		method: "get",
+	});
+}
+
+// 查询流程定义详细
+export const getDeployment = async (id: string) => {
+	return await request({
+		url: "/system/deployment/" + id,
+		method: "get",
+	});
+}
+
+// 新增流程定义
+export const addDeployment = async (data: any) => {
+	return await request({
+		url: "/system/deployment",
+		method: "post",
+		data: data,
+	});
+}
+
+// 修改流程定义
+export const updateDeployment = async (data: any) => {
+	return await request({
+		url: "/system/deployment",
+		method: "put",
+		data: data,
+	});
+}
+
+// 删除流程定义
+export const delDeployment = async (id: string) => {
+	return await request({
+		url: "/system/deployment/" + id,
+		method: "delete",
+	});
+}
+
+// 导出流程定义
+export const exportDeployment = async (query: any) => {
+	return await request({
+		url: "/system/deployment/export",
+		method: "get",
+		params: query,
+	});
+}
+// 流程节点表单
+export const flowTaskForm = async (query: any) => {
+	return await request({
+		url: "/flowable/task/flowTaskForm",
+		method: "get",
+		params: query,
+	});
+};

+ 63 - 0
src/api/login.ts

@@ -0,0 +1,63 @@
+import request from "@/utils/request";
+
+/**
+ * 登录方法
+ *
+ * @param {object} loginParam 登录参数
+ * @returns
+ */
+export const login = async (loginParam: any) => {
+	return await request({
+		url: "/login",
+		method: "post",
+		data: loginParam,
+	});
+};
+
+/**
+ * 获取用户(角色与权限)详细信息
+ *
+ * @returns
+ */
+export const getInfo = async () => {
+	return await request({
+		url: "/getInfo",
+		method: "get",
+	});
+};
+
+/**
+ * 退出
+ *
+ * @returns
+ */
+export const logout = async () => {
+	return await request({
+		url: "/logout",
+		method: "post",
+	});
+};
+
+/**
+ * 获取验证码
+ *
+ * @returns
+ */
+export const getCodeImg = async () => {
+	return await request({
+		url: "/captchaImage",
+		method: "get",
+	});
+};
+
+// 注册方法
+export const register = async (data: any) => {
+	return await request({
+		url: "/register",
+		headers: {
+			isToken: false,
+		},
+		method: "post",
+		data: data,
+	});
+};

+ 13 - 0
src/api/menu.ts

@@ -0,0 +1,13 @@
+import request from "@/utils/request";
+
+/**
+ * 获取路由
+ *
+ * @returns
+ */
+export const getRouters = async () => {
+	return await request({
+		url: "/getRouters",
+		method: "get",
+	});
+};

+ 108 - 0
src/api/request/login.ts

@@ -0,0 +1,108 @@
+import useUserStore from "@/store/modules/user";
+import { useRouter } from "vue-router";
+import { getCodeImg } from "@/api/login";
+import Cookies from "js-cookie";
+import { encrypt, decrypt } from "@/utils/jsencrypt";
+import { ref } from "vue";
+import { ElForm } from "element-plus";
+import { lodashFunc } from "@/utils/ruoyi";
+//import { ILoginForm } from "./module/loginForm";
+
+export default () => {
+	const loginFormRef = ref<InstanceType<typeof ElForm>>();
+	const codeUrl = ref<string>("");
+	const loginForm = ref<any>({
+		username: "admin",
+		password: "admin123",
+		rememberMe: false,
+		code: "",
+		uuid: "",
+	});
+
+	const loginRules = {
+		username: [
+			{ required: true, trigger: "blur", message: "用户名不能为空" },
+		],
+		password: [
+			{ required: true, trigger: "blur", message: "密码不能为空" },
+		],
+		code: [
+			{ required: true, trigger: "change", message: "验证码不能为空" },
+		],
+	};
+
+	let loading = ref<boolean>(false);
+	const redirect = ref<any>(undefined);
+
+	const userStore = useUserStore();
+	const router = useRouter();
+
+	const getCodeBase64 = () => {
+		getCodeImg().then((res: any) => {
+			if (res.code === 200) {
+				// const data = res.data;
+				console.log(res.uuid);
+				loginForm.value.uuid = res.uuid;
+				const img = res.img;
+				if (img.indexOf("data:image") > -1) {
+					codeUrl.value = img;
+				} else {
+					codeUrl.value = "data:image/png;base64," + img;
+				}
+			}
+		});
+	};
+
+    // 验证码防抖,设置每700毫秒才能点击一次
+	const getCode = lodashFunc(getCodeBase64, 700);
+
+	const getCookie = () => {
+		const username = Cookies.get("username");
+		const password = Cookies.get("password");
+		const rememberMe = Cookies.get("rememberMe");
+		// prettier-ignore
+		loginForm.value.username = username === undefined ? loginForm.value.username : username;
+		// prettier-ignore
+		loginForm.value.password = password === undefined ? loginForm.value.password : decrypt(password) as string;
+		// prettier-ignore
+		loginForm.value.rememberMe = rememberMe === undefined ? false : Boolean(rememberMe);
+	};
+
+	const handleLogin = () => {
+		loginFormRef.value?.validate((valid: boolean) => {
+			if (valid) {
+				loading.value = true;
+				if (loginForm.value.rememberMe) {
+					// prettier-ignore
+					Cookies.set("username", loginForm.value.username, { expires: 30,});
+					// prettier-ignore
+					Cookies.set("password", encrypt(loginForm.value.password).toString(), {expires: 30, });
+					// prettier-ignore
+					Cookies.set("rememberMe", loginForm.value.rememberMe.toString(), { expires: 30, });
+				} else {
+					Cookies.remove("username");
+					Cookies.remove("password");
+					Cookies.remove("rememberMe");
+				}
+
+				// prettier-ignore
+				userStore.userLogin(loginForm.value)
+				.then(() => {
+					router.push({ path: redirect.value || "/" }).catch(() => {});
+				})
+				.catch((error) => {
+					console.log("登录失败", error);
+					loading.value = false;
+					getCode();
+				});
+			}
+		});
+	};
+
+	getCode();
+	getCookie();
+    // prettier-ignore
+	return { 
+        loginFormRef, loginForm, loginRules, codeUrl, loading, getCode, handleLogin, 
+    };
+};

+ 5 - 0
src/api/request/module/Form.ts

@@ -0,0 +1,5 @@
+export interface IForm {
+	deptid: string;
+	stopid: string;
+	status: string;
+}

+ 25 - 0
src/api/request/module/MenuForm.ts

@@ -0,0 +1,25 @@
+export interface IMenu {
+	children: [];
+	component: string;
+	createBy: string;
+	createTime: string;
+	icon: string | "system";
+	isCache: string;
+	isFrame: string;
+	menuId: 1;
+	menuName: string;
+	menuType: string | "M";
+	orderNum: number | 1;
+	params: any;
+	parentId: number | 0;
+	parentName: string;
+	path: string | "system";
+	perms: string | "";
+	query: string | "";
+	remark: string;
+	searchValue: string;
+	status: string | "0";
+	updateBy: string;
+	updateTime: string;
+	visible: string | "0";
+}

+ 7 - 0
src/api/request/module/RouterList.ts

@@ -0,0 +1,7 @@
+// 自定义路由接口
+export interface IRouterList {
+	name?: string;
+	path: string;
+	component: any;
+	[propname: string]: any;
+}

+ 7 - 0
src/api/request/module/loginForm.ts

@@ -0,0 +1,7 @@
+export interface ILoginForm {
+	username: string
+	password: string
+	rememberMe: boolean;
+	code: "";
+	uuid: "";
+}

+ 41 - 0
src/api/request/module/profile.ts

@@ -0,0 +1,41 @@
+export interface IDept {
+	ancestors?: string;
+	children?: [];
+	createBy?: string;
+	createTime?: string;
+	delFlag?: string;
+	deptId?: string;
+	deptName: string;
+	email?: string;
+	leader?: string;
+	orderNum?: string;
+}
+export interface IUser {
+  userId: string;
+	userName: string;
+	createTime: string;
+	phonenumber: string;
+	admin?: boolean;
+	avatar?: string;
+	createBy?: string;
+	delFlag?: string;
+	dept: IDept;
+	deptId?: string;
+	email: string;
+	loginDate?: string;
+	loginIp?: string;
+	nickName: string;
+	postIds?: string;
+	postNameArray?: string;
+	remark?: string;
+	roleIds?: undefined;
+	roleNameArray?: undefined;
+	roles?: [];
+	salt?: undefined;
+	searchValue?: undefined;
+	sex?: string;
+	status?: string;
+	updateBy?: undefined;
+	updateTime?: undefined;
+	
+}

+ 80 - 0
src/api/request/monitor/cache/index.ts

@@ -0,0 +1,80 @@
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { getCache } from "@/api/system/cache";
+import * as echarts from "echarts";
+
+export default () => {
+    const { proxy } = getCurrentInstance() as any;
+
+	const cache = ref<any>([]);
+	const commandstats = ref<any>(null);
+	const usedmemory = ref<any>(null);
+
+	const getList = () => {
+		proxy.$modal.loading("正在加载缓存监控数据,请稍候!");
+		getCache().then((response) => {
+			proxy.$modal.closeLoading();
+			cache.value = response.data;
+
+			const commandstatsIntance = echarts.init(
+				commandstats.value,
+				"macarons"
+			);
+			commandstatsIntance.setOption({
+				tooltip: {
+					trigger: "item",
+					formatter: "{a} <br/>{b} : {c} ({d}%)",
+				},
+				series: [
+					{
+						name: "命令",
+						type: "pie",
+						roseType: "radius",
+						radius: [15, 95],
+						center: ["50%", "38%"],
+						data: response.data.commandStats,
+						animationEasing: "cubicInOut",
+						animationDuration: 1000,
+					},
+				],
+			});
+
+			const usedmemoryInstance = echarts.init(
+				usedmemory.value,
+				"macarons"
+			);
+			usedmemoryInstance.setOption({
+				tooltip: {
+					formatter:
+						"{b} <br/>{a} : " + cache.value.info.used_memory_human,
+				},
+				series: [
+					{
+						name: "峰值",
+						type: "gauge",
+						min: 0,
+						max: 1000,
+						detail: {
+							formatter: cache.value.info.used_memory_human,
+						},
+						data: [
+							{
+								value: parseFloat(
+									cache.value.info.used_memory_human
+								),
+								name: "内存消耗",
+							},
+						],
+					},
+				],
+			});
+		});
+	};
+
+	onMounted(() => {
+		getList();
+	});
+
+    return {
+        cache, commandstats, usedmemory, getList
+    }
+};

+ 113 - 0
src/api/request/monitor/cache/list.ts

@@ -0,0 +1,113 @@
+import { getCurrentInstance, ref, onMounted } from "vue";
+// prettier-ignore
+import { listCacheName, listCacheKey, getCacheValue, clearCacheName, clearCacheKey, clearCacheAll } from "@/api/system/cache";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	const cacheNames = ref<any>([]);
+	const cacheKeys = ref<any>([]);
+	const cacheForm = ref<any>({});
+	const loading = ref<boolean>(true);
+	const subLoading = ref<boolean>(false);
+	const nowCacheName = ref<string>("");
+	const tableHeight = ref<number>(window.innerHeight - 200);
+
+	/** 查询缓存名称列表 */
+	const getCacheNames = () => {
+		loading.value = true;
+		listCacheName().then((response: any) => {
+			if (response.code === 200) {
+				cacheNames.value = response.data;
+				loading.value = false;
+			}
+		});
+	};
+
+	/** 刷新缓存名称列表 */
+	const refreshCacheNames = () => {
+		getCacheNames();
+		proxy.$modal.msgSuccess("刷新缓存列表成功");
+	};
+
+	/** 清理指定名称缓存 */
+	const handleClearCacheName = (row: any) => {
+		clearCacheName(row.cacheName).then((response: any) => {
+			if (response.code === 200) {
+				// prettier-ignore
+				proxy.$modal.msgSuccess("清理缓存名称[" + nowCacheName.value + "]成功");
+				getCacheKeys();
+			}
+		});
+	};
+
+	/** 查询缓存键名列表 */
+	const getCacheKeys = (row?: any) => {
+		const cacheName = row ? row.cacheName : nowCacheName.value;
+		if (cacheName === "") {
+			return;
+		}
+		subLoading.value = true;
+		listCacheKey(cacheName).then((response: any) => {
+			if (response.code === 200) {
+				cacheKeys.value = response.data;
+				subLoading.value = false;
+				nowCacheName.value = cacheName;
+			}
+		});
+	};
+
+	/** 刷新缓存键名列表 */
+	const refreshCacheKeys = () => {
+		getCacheKeys();
+		proxy.$modal.msgSuccess("刷新键名列表成功");
+	};
+
+	/** 清理指定键名缓存 */
+	const handleClearCacheKey = (cacheKey: any) => {
+		clearCacheKey(cacheKey).then((response: any) => {
+			if (response.code === 200) {
+				proxy.$modal.msgSuccess("清理缓存键名[" + cacheKey + "]成功");
+				getCacheKeys();
+			}
+		});
+	};
+
+	/** 列表前缀去除 */
+	const nameFormatter = (row: any) => {
+		return row.cacheName.replace(":", "");
+	};
+
+	/** 键名前缀去除 */
+	const keyFormatter = (cacheKey: any) => {
+		return cacheKey.replace(nowCacheName.value, "");
+	};
+
+	/** 查询缓存内容详细 */
+	const handleCacheValue = (cacheKey: any) => {
+		getCacheValue(nowCacheName.value, cacheKey).then((response: any) => {
+			if (response.code === 200) {
+				cacheForm.value = response.data;
+			}
+		});
+	};
+
+	/** 清理全部缓存 */
+	const handleClearCacheAll = () => {
+		clearCacheAll().then((response: any) => {
+			if (response.code === 200) {
+				proxy.$modal.msgSuccess("清理全部缓存成功");
+			}
+		});
+	};
+
+	onMounted(() => {
+		getCacheNames();
+	});
+
+    // prettier-ignore
+    return {
+        cacheNames, cacheKeys, cacheForm, loading, subLoading, tableHeight, refreshCacheNames, handleClearCacheName, getCacheKeys, refreshCacheKeys, 
+        handleClearCacheKey, nameFormatter, keyFormatter, handleCacheValue, handleClearCacheAll, 
+    };
+
+};

+ 330 - 0
src/api/request/monitor/job/index.ts

@@ -0,0 +1,330 @@
+import { ElForm, ElTable } from "element-plus";
+import { getCurrentInstance, onMounted, ref } from "vue";
+// prettier-ignore
+import { addJob, changeJobStatus, delJob, getJob, listJob, runJob, updateJob, } from "@/api/system/job";
+// coron 验证
+import { isValidCron } from "cron-validator";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	// 遮罩层
+	const loading = ref<boolean>(true);
+	// 选中数组
+	const ids = ref<any>();
+	// 非单个禁用
+	const single = ref<boolean>(true);
+	// 非多个禁用
+	const multiple = ref<boolean>(true);
+	// 显示搜索条件
+	const showSearch = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 定时任务表格数据
+	const jobList = ref<any>();
+	// 弹出层标题
+	const title = ref<string>("");
+	// 是否显示弹出层
+	const open = ref<boolean>(false);
+	// 是否显示详细弹出层
+	const openView = ref<boolean>(false);
+	// 任务组名字典
+	const jobGroupOptions = ref<any>();
+	// 状态字典
+	const statusOptions = ref<any>();
+	// 查询参数
+	const queryParams = ref<any>({
+		pageNum: 1,
+		pageSize: 10,
+		jobName: undefined,
+		jobGroup: undefined,
+		status: undefined,
+	});
+	const queryFormRef = ref<InstanceType<typeof ElForm>>();
+	const formRef = ref<InstanceType<typeof ElForm>>();
+	const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	// 表单参数
+	const formData = ref<any>();
+	// prettier-ignore
+	const checkCoreExpression = (rule: any, value: any, callback: any) => {
+        if (!value) {
+            return callback(new Error('cron表达式不能为空!'))
+        }
+        setTimeout(() => {
+            // 验证cron表达式
+            if (!isValidCron(value, {
+                alias: true,
+                seconds: true,
+                allowBlankDay: true,
+                allowSevenAsSunday: true,
+            } )) {
+                callback(new Error('cron表达式不正确!'))
+            } else {
+                callback();
+            }
+        }, 150);
+      }
+	// 表单校验
+	const rules = ref({
+		jobName: [
+			{
+				required: true,
+				message: "任务名称不能为空",
+				trigger: ["blur", "change"],
+			},
+		],
+		jobGroup: [
+			{
+				required: true,
+				message: "请选择分组",
+				trigger: "change",
+			},
+		],
+		invokeTarget: [
+			{
+				required: true,
+				message: "调用目标字符串不能为空",
+				trigger: ["blur", "change"],
+			},
+		],
+		cronExpression: [
+			{
+                required: true,
+				validator: checkCoreExpression,
+				trigger: ["blur", "change"],
+			},
+			/* {
+				required: true,
+				message: "cron执行表达式不能为空",
+				trigger: "blur",
+			}, */
+		],
+	});
+
+	const getList = async () => {
+		loading.value = true;
+		await listJob(queryParams.value).then((response: any) => {
+			jobList.value = response.rows;
+			total.value = parseInt(response.total);
+			loading.value = false;
+		});
+	};
+	// 任务组名字典翻译
+	const jobGroupFormat = (row: any) => {
+		return proxy.selectDictLabel(jobGroupOptions.value, row.jobGroup);
+	};
+	// 状态字典翻译
+	const statusFormat = (row: any) => {
+		return proxy.selectDictLabel(statusOptions.value, row.status);
+	};
+
+	const cleanSelect = () => {
+		proxy.cleanTableSelection(pageTableRef);
+		proxy.resetForm(formRef);
+	};
+
+	// 取消按钮
+	const cancel = () => {
+		open.value = false;
+		reset();
+		cleanSelect();
+	};
+	// 表单重置
+	const reset = () => {
+		formData.value = {
+			jobId: undefined,
+			jobName: undefined,
+			jobGroup: undefined,
+			invokeTarget: undefined,
+			cronExpression: undefined,
+			misfirePolicy: 1,
+			concurrent: 1,
+			status: "0",
+		};
+		proxy.resetForm(formRef);
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getList();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		proxy.resetForm(queryFormRef);
+		handleQuery();
+	};
+	// 多选框选中数据
+	const handleSelectionChange = (selection: any) => {
+		ids.value = selection.map((item: { jobId: any }) => item.jobId);
+		single.value = selection.length != 1;
+		multiple.value = !selection.length;
+	};
+	/* 立即执行一次 */
+	const handleRun = (row: any) => {
+		proxy.setTableRowSelected(pageTableRef, row, true);
+		// prettier-ignore
+		proxy.$modal.confirm('确认要立即执行一次"' + row.jobName + '"任务吗?')
+			.then(() => {
+				return runJob(row.jobId, row.jobGroup);
+			})
+			.then((response: any) => {
+				if (response.code === 200) {
+                    proxy.$modal.msgSuccess("执行成功");
+                    proxy.setTableRowSelected(pageTableRef, row, false);
+                }
+			})
+			.catch(() => {
+                proxy.setTableRowSelected(pageTableRef, row, false);
+				console.log("确定执行操作取消");
+			});
+	};
+	/** 任务详细信息 */
+	const handleView = (row: any) => {
+		getJob(row.jobId).then((response) => {
+			formData.value = response.data;
+			proxy.setTableRowSelected(pageTableRef, row, true);
+			openView.value = true;
+		});
+	};
+	/** 任务日志列表查询 */
+	const handleJobLog = (row: any) => {
+		//this.$router.push("/job/log");
+		const jobId = row.jobId || 0;
+		proxy.$router.push({
+			path: "/monitor/job-log/index",
+			query: { jobId: jobId },
+		});
+	};
+	// 更多操作触发
+	const handleCommand = (command: string, row: any) => {
+		switch (command) {
+			case "handleRun":
+				handleRun(row);
+				break;
+			case "handleView":
+				handleView(row);
+				break;
+			case "handleJobLog":
+				handleJobLog(row);
+				break;
+			default:
+				break;
+		}
+	};
+	// 任务状态修改
+	const handleStatusChange = (row: {
+		status: string;
+		jobName: string;
+		jobId: string;
+	}) => {
+		let text = row.status === "0" ? "启动" : "停止";
+		proxy.setTableRowSelected(pageTableRef, row, true);
+		// prettier-ignore
+		proxy.$modal.confirm('确认要' + text + '【' + row.jobName + '】任务吗?')
+			.then(function () {
+				return changeJobStatus(row.jobId, row.status);
+			})
+			.then((response:  any) => {
+				if (response.code === 200) {
+                    proxy.$modal.msgSuccess(text + "成功");
+                }
+			})
+			.catch(() => {
+				row.status = row.status === "0" ? "1" : "0";
+                proxy.setTableRowSelected(pageTableRef, row, false);
+			});
+	};
+
+	/** 新增按钮操作 */
+	const handleAdd = () => {
+		reset();
+		open.value = true;
+		title.value = "添加任务";
+	};
+	/** 修改按钮操作 */
+	const handleUpdate = (row: any) => {
+		reset();
+		const jobId = row.jobId || ids.value;
+		getJob(jobId).then((response) => {
+			formData.value = response.data;
+			title.value = "修改任务";
+			// 设置当前行被选中
+			proxy.setTableRowSelected(pageTableRef, row, true);
+			open.value = true;
+		});
+	};
+	/** 提交按钮 */
+	const submitForm = () => {
+		formRef.value?.validate((valid: boolean) => {
+			if (valid) {
+				if (formData.value.jobId !== undefined) {
+					updateJob(formData.value)
+						.then((response: any) => {
+							if (response.code === 200) {
+								proxy.$modal.msgSuccess("修改成功");
+							}
+						})
+						.finally(() => {
+							open.value = false;
+							getList();
+						});
+				} else {
+					addJob(formData.value)
+						.then((response: any) => {
+							if (response.code === 200) {
+								proxy.$modal.msgSuccess("新增成功");
+							}
+						})
+						.finally(() => {
+							open.value = false;
+							getList();
+						});
+				}
+			}
+		});
+	};
+	/** 删除按钮操作 */
+	const handleDelete = (row: any) => {
+		const jobIds = row.jobId || ids.value;
+		if (row) {
+			// 设置当前行被选中
+			proxy.setTableRowSelected(pageTableRef, row, true);
+		}
+		// prettier-ignore
+		proxy.$modal.confirm('是否确认删除定时任务编号为"' + jobIds + '"的数据项?')
+			.then(() => {
+				return delJob(jobIds);
+			})
+			.then((response: { code: number }) => {
+				if (response.code === 200) {
+					getList();
+					proxy.$modal.msgSuccess("删除成功");
+				}
+			})
+			.catch(() => {
+                cleanSelect();
+				console.log("取消了删除");
+			});
+	};
+	/** 导出按钮操作 */
+	const handleExport = () => {
+		// prettier-ignore
+		proxy.download('/monitor/job/exportByStream', {...queryParams}, `定时任务${new Date().getTime()}.xlsx`);
+	};
+
+	onMounted(() => {
+		getList();
+		proxy.getDicts("sys_job_group").then((response: any) => {
+			jobGroupOptions.value = response.data;
+		});
+		proxy.getDicts("sys_job_status").then((response: any) => {
+			statusOptions.value = response.data;
+		});
+	});
+
+	// prettier-ignore
+	return {
+        loading, single, multiple, showSearch, total, jobList, title, open, openView, jobGroupOptions, statusOptions, formRef, formData, rules, 
+        getList, jobGroupFormat, cancel, handleQuery, resetQuery, handleSelectionChange, handleCommand, handleStatusChange, cleanSelect,   
+        handleJobLog, handleAdd, handleUpdate, submitForm, handleDelete, handleExport, queryParams, queryFormRef, pageTableRef, 
+    }
+};

+ 160 - 0
src/api/request/monitor/job/jobLog.ts

@@ -0,0 +1,160 @@
+import { cleanJobLog, delJobLog, listJobLog } from "@/api/system/jobLog";
+import { ElTable } from "element-plus";
+import { getCurrentInstance, ref } from "vue";
+import { useRouter } from "vue-router";
+//import useTagsViewStore from "@/store/modules/tagsView";
+
+export default () => {
+	const router = useRouter();
+	const { proxy } = getCurrentInstance() as any;
+	// prettier-ignore
+	const { sys_job_group, sys_job_status } = proxy.useDict("sys_job_group","sys_job_status");
+	// 遮罩层
+	const loading = ref<boolean>(true);
+	// 导出遮罩层
+	const exportLoading = ref<boolean>(false);
+	// 选中数组
+	let ids: any = [];
+	// 非多个禁用
+	const multiple = ref<boolean>(false);
+	// 显示搜索条件
+	const showSearch = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 调度日志表格数据
+	const jobLogList = ref<any>([]);
+	// 是否显示弹出层
+	const open = ref<boolean>(false);
+	// 日期范围
+	const dateRange = ref<any>();
+	// 是否显示弹出层
+	// 表单参数
+	const formData = ref<any>({});
+	// 查询参数
+	const queryParams = ref({
+		pageNum: 1,
+		pageSize: 10,
+		jobName: undefined,
+		jobGroup: undefined,
+		status: undefined,
+	});
+    const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	const getList = () => {
+		loading.value = true;
+		// prettier-ignore
+		listJobLog(proxy.addDateRange(queryParams.value, dateRange.value)).then((response: any) => {
+            jobLogList.value = response.rows;
+            total.value = parseInt(response.total);
+            loading.value = false;
+        });
+	};
+	// 返回按钮
+	const handleClose = () => {
+		// useTagsViewStore().delView(proxy.$route);
+		proxy.$router.push({ path: "/monitor/job" });
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getList();
+	};
+    const cleanSelect = () => {
+        proxy.cleanTableSelection(pageTableRef);
+    };
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		dateRange.value = [];
+		proxy.resetForm("queryForm");
+		handleQuery();
+	};
+	// 多选框选中数据
+	const handleSelectionChange = (selection: any) => {
+		ids = selection.map((item: { jobLogId: any }) => item.jobLogId);
+		multiple.value = !selection.length;
+	};
+	/** 详细按钮操作 */
+	const handleView = (row: any) => {
+		open.value = true;
+		formData.value = row;
+        proxy.setTableRowSelected(pageTableRef, row, true);
+	};
+	/** 删除按钮操作 */
+	const handleDeleteOne = (row: any) => {
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		ids.push(row.jobId);
+		const jobLogIds = ids;
+        // 遮罩层
+		proxy.$modal.confirm('是否确认删除调度日志编号为"【' + row.jobId + '】"的数据项?')
+			.then(() => {
+				return delJobLog(jobLogIds);
+			})
+			.then((response: any) => {
+				if (response.code === 200) {
+					getList();
+					proxy.$modal.msgSuccess("删除成功");
+				}
+			})
+			.catch(() => {
+                cleanSelect();
+				console.log("取消了删除");
+			});
+	};
+	const handleDelete = () => {
+        // prettier-ignore
+		proxy.$modal.confirm('是否确认删除调度日志编号为"' + ids + '"的数据项?')
+			.then(() => {
+				return delJobLog(ids);
+			})
+			.then((response: any) => {
+				if (response.code === 200) {
+					getList();
+					proxy.$modal.msgSuccess("删除成功");
+				}
+			})
+			.catch(() => {
+                cleanSelect();
+				console.log("取消了删除");
+			});
+	};
+	/** 清空按钮操作 */
+	const handleClean = () => {
+		// prettier-ignore
+		proxy.$modal.confirm("是否确认清空所有调度日志数据项?", "警告")
+        .then(() => {
+            return cleanJobLog();
+        })
+        .then((response: any) => {
+            if (response.code === 200) {
+                getList();
+                proxy.$modal.msgSuccess("清空成功");
+            }
+        })
+        .catch(() => {
+            console.log("清空日志操作取消");
+        });
+	};
+	/** 导出按钮操作 */
+	const handleExport = () => {
+		// prettier-ignore
+		proxy.download('/monitor/jobLog/exportByStream', {...queryParams}, `调度日志导出${new Date().getTime()}.xlsx`);
+	};
+
+	// const jobId = proxy.$route.query.jobId;
+	// if (jobId !== undefined && jobId != 0) {
+	// 	getJob(jobId).then((response: any) => {
+	// 		queryParams.value.jobName = response.data.jobName;
+	// 		queryParams.value.jobGroup = response.data.jobGroup;
+	// 		getList();
+	// 	});
+	// } else {}
+	getList();
+	
+
+    // prettier-ignore
+    return {
+        loading, exportLoading, multiple, showSearch, total, jobLogList, open, dateRange, formData, queryParams, sys_job_group, sys_job_status, 
+        pageTableRef, getList, handleClose, handleQuery, resetQuery, handleSelectionChange, handleView, handleDelete, handleDeleteOne, handleClean, 
+        handleExport, cleanSelect, 
+    }
+
+};

+ 161 - 0
src/api/request/monitor/log/loginLog.ts

@@ -0,0 +1,161 @@
+import { ref, getCurrentInstance } from "vue";
+// prettier-ignore
+import { getlist, delLogininfor, cleanLogininfor, unlockUser, } from "@/api/system/logininfor";
+import { ElForm, ElTable } from "element-plus";
+import { uniqueArr } from "@/utils";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+    const queryFormRef = ref<InstanceType<typeof ElForm>>();
+    const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	// 遮罩层
+	let loading = ref<boolean>(true);
+	// 选中数组
+	const ids = ref<any>();
+	// 非多个禁用
+	let multiple = ref<boolean>(true);
+    // 选中的用户名
+    let selectedNames = ref<string[]>();
+	// 显示搜索条件
+	let showSearch = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 表格数据
+	const list = ref<any>();
+	// 状态数据字典
+	const statusOptions = ref<any>();
+	// 日期范围
+	const dateRange = ref<any>();
+	// 查询参数
+	const queryParams = ref<any>({
+		pageNum: 1,
+		pageSize: 10,
+		ipaddr: undefined,
+		userName: undefined,
+		status: undefined,
+		msg: undefined,
+	});
+
+	/** 查询登录日志列表 */
+	const getList = () => {
+		loading.value = true;
+		// prettier-ignore
+		getlist(proxy.addDateRange(queryParams.value, dateRange.value)).then((response: any) => {
+				list.value = response.rows;
+				total.value = parseInt(response.total);
+				loading.value = false;
+			}
+		);
+	};
+	// 登录状态字典翻译
+	const statusFormat = (row: { status: any }) => {
+		return proxy.selectDictLabel(statusOptions.value, row.status);
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getList();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		dateRange.value = [];
+		proxy.resetForm(queryFormRef);
+		handleQuery();
+	};
+	// 多选框选中数据
+	const handleSelectionChange = (selection: any) => {
+		ids.value = selection.map((item: { infoId: any }) => item.infoId);
+		multiple.value = !selection.length;
+        selectedNames.value = selection.map((item: { userName: string  }) => item.userName);
+	};
+	/** 删除按钮操作 */
+	const handleDelete = async (row: any) => {
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		const infoIds = row.infoId || ids.value;
+		// prettier-ignore
+		await proxy.$modal.confirm('是否确认删除访问编号为"' + infoIds + '"的数据项?', "警告")
+            .then(() => {
+                return delLogininfor(infoIds);
+            })
+            .then((response: any) => {
+               if (response.code === 200 ) {
+                    getList();
+                    proxy.$modal.msgSuccess("删除成功");
+               }
+            }).catch(() => {
+                pageTableRef.value?.clearSelection();
+                console.log("取消了删除");
+            });
+	};
+	/** 清空按钮操作 */
+	const handleClean = async () => {
+		// prettier-ignore
+		await proxy.$modal.confirm("是否确认清空所有登录日志数据项?", "警告")
+            .then(() => {
+                return cleanLogininfor();
+            })
+            .then((response: any) => {
+                if (response.code === 200) {
+                    getList();
+                    proxy.$modal.msgSuccess("清空成功");
+                }
+            }).catch(() => {
+                console.log("取消了清空");
+            });
+	};
+	/** 导出按钮操作 */
+	const handleExport = () => {
+        // prettier-ignore
+		proxy.download("/monitor/operlog/exportByStream", { ...queryParams }, `登录日志信息${new Date().getTime()}.xlsx`);
+	};
+
+    const unlock = async () => {
+        const userName = uniqueArr(selectedNames.value)
+        console.log("aaaa", userName);
+        await proxy.$modal.confirm('是否要解除"' + userName + '"锁定?', "警告").then(() => {
+            return unlockUser(userName);
+        }).then((response: any) => {
+            if (response.code === 200) {
+                getList();
+                proxy.$modal.msgSuccess("解除锁定成功");
+            }
+        }).catch(() => {
+            pageTableRef.value?.clearSelection();
+            console.log("取消解除锁定");
+        });
+    };
+
+    const checkSelected  = (row: any) => {
+        // 设置不可选中
+        console.log("是否锁定", row.lock);
+        return row.lock;
+    };
+
+	getList();
+	proxy.getDicts("sys_common_status").then((response: any) => {
+		statusOptions.value = response.data;
+	});
+
+	return {
+        queryFormRef,
+		loading,
+		multiple,
+		showSearch,
+		total,
+		list,
+		statusOptions,
+		dateRange,
+		queryParams,
+    pageTableRef,
+		getList,
+		statusFormat,
+		handleQuery,
+		resetQuery,
+		handleSelectionChange,
+		handleDelete,
+		handleClean,
+		handleExport,
+    unlock,
+    checkSelected
+	};
+};

+ 172 - 0
src/api/request/monitor/log/operaLog.ts

@@ -0,0 +1,172 @@
+// prettier-ignore
+import { getPageList, delOperlog, cleanOperlog } from "@/api/system/operlog";
+import { ElForm, ElTable } from "element-plus";
+import { ref, getCurrentInstance, onMounted } from "vue";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	// 遮罩层
+	const loading = ref<boolean>(true);
+	// 导出遮罩层
+	const exportLoading = ref<boolean>(false);
+	// 选中数组
+	let ids: never[] = [];
+	// 非多个禁用
+	const multiple = ref<boolean>(true);
+	// 显示搜索条件
+	const showSearch = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 表格数据
+	const list = ref<any>();
+	// 是否显示弹出层
+	const open = ref<boolean>(false);
+	// 日期范围
+	const dateRange = ref<string>("");
+	// 默认排序
+	const defaultSort = { prop: "operTime", order: "descending" } as any;
+	// 表单参数
+	let form = ref<any>();
+
+	// 查询参数
+	const queryParams = ref<any>({
+		pageNum: 1,
+		pageSize: 10,
+		title: undefined,
+		operName: undefined,
+		businessType: undefined,
+		status: undefined,
+	});
+	const { sys_common_status } = proxy.useDict("sys_common_status") as any;
+	const { sys_oper_type } = proxy.useDict("sys_oper_type") as any;
+	const formRef = ref<InstanceType<typeof ElForm>>();
+	const queryForm = ref<InstanceType<typeof ElForm>>();
+	const statusOptions = ref<any>();
+    const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	/** 查询登录日志 */
+	const getList = () => {
+		loading.value = true;
+		getPageList(
+			proxy.addDateRange(queryParams.value, dateRange.value)
+		).then((response: any) => {
+			if (response.code === 200) {
+				list.value = response.rows;
+				total.value = parseInt(response.total);
+				loading.value = false;
+			}
+		});
+	};
+	// 操作日志类型字典翻译
+	const typeFormat = (row: any) => {
+		// prettier-ignore
+		return proxy.selectDictLabel(sys_oper_type.value, row.businessType);
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getList();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		dateRange.value = "";
+		proxy.resetForm(queryForm);
+		proxy.$refs.tables.sort(defaultSort.prop, defaultSort.order);
+		handleQuery();
+	};
+	/** 多选框选中数据 */
+	const handleSelectionChange = (selection: any) => {
+		ids = selection.map((item: { operId: any }) => item.operId);
+		multiple.value = !selection.length;
+	};
+	/** 排序触发事件 */
+	const handleSortChange = (column: any) => {
+		queryParams.value.orderByColumn = column.prop;
+		queryParams.value.isAsc = column.order;
+		getList();
+	};
+    const cleanSelect = () => {
+        proxy.cleanTableSelection(pageTableRef);
+    };
+	/** 详细按钮操作 */
+	const handleView = (row: any) => {
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		open.value = true;
+		form.value = row;
+	};
+	/** 删除按钮操作 */
+	const handleDelete = (row: any) => {
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		const operIds = row.operId || ids;
+		// prettier-ignore
+		proxy.$modal.confirm('是否确认删除日志编号为"' + operIds + '"的数据项?', "警告")
+            .then(() => {
+                return delOperlog(operIds);
+            })
+            .then((response: any) => {
+                if (response.code === 200) {
+                    getList();
+                    proxy.$modal.msgSuccess("删除成功");
+                }
+            })
+            .catch(() => {
+                cleanSelect();
+                console.log("取消了删除");
+            });
+	};
+	/** 清空按钮操作 */
+	const handleClean = () => {
+		// prettier-ignore
+		proxy.$modal.confirm("是否确认清空所有操作日志数据项?", "警告")
+            .then(() => {
+                return cleanOperlog();
+            })
+            .then((response: any) => {
+                if (response.code === 200) {
+                    getList();
+                    proxy.$modal.msgSuccess("清空成功");
+                }
+            })
+            .catch(() => {
+                console.log("取消了清空");
+            });
+	};
+	/** 导出按钮操作 */
+	const handleExport = () => {
+		// prettier-ignore
+		proxy.download('/monitor/operlog/exportByStream', {...queryParams}, `操作日志导出${new Date().getTime()}.xlsx`);
+	};
+
+	/**
+	 * 绑定回车
+	 */
+	const keyupEnter = () => {
+		document.onkeydown = (e: any) => {
+			if (e.defaultPrevented) {
+				return;
+			}
+			// prettier-ignore
+			const body = document.getElementsByTagName('body')[0];
+			// prettier-ignore
+            // match(此处应填写文件在浏览器中的地址,如 '/home/index')
+			if (e.keyCode === 13 && e.target.baseURI.match("/system/log/operlog") && e.target === body) {
+                console.log("按下了回车键");
+                getList();
+            }
+		};
+	};
+
+	onMounted(() => {
+		getList();
+		proxy.getDicts("sys_normal_disable").then((response: { data: any }) => {
+			statusOptions.value = response.data;
+		});
+		keyupEnter();
+	});
+
+	// prettier-ignore
+	return {
+        loading, exportLoading, multiple, showSearch, total, list, open, dateRange, defaultSort, form, queryParams, sys_common_status, sys_oper_type, 
+        formRef, statusOptions, queryForm, pageTableRef, cleanSelect, getList, typeFormat, handleQuery, resetQuery, handleSelectionChange, 
+        handleSortChange, handleView, handleDelete, handleClean, handleExport
+    }
+};

+ 72 - 0
src/api/request/monitor/online/index.ts

@@ -0,0 +1,72 @@
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { list, forceLogout } from "@/api/system/online";
+import { ElForm } from "element-plus";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	// 遮罩层
+	const loading = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 表格数据
+	const tablelist = ref<any>([]);
+	// 表单查询ref
+	const queryFormRef = ref<InstanceType<typeof ElForm>>();
+	// 表单查询参数
+	const queryParams = ref({
+		pageNum: 1,
+		pageSize: 10,
+		ipaddr: undefined,
+		userName: undefined,
+	});
+
+	/** 查询在线用户列表 */
+	const getList = () => {
+		loading.value = true;
+		list(queryParams.value).then((response: any) => {
+			tablelist.value = response.rows;
+			total.value = parseInt(response.total);
+			loading.value = false;
+		});
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getList();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		proxy.resetForm(queryFormRef);
+		handleQuery();
+	};
+	/**
+	 * 强退按钮操作
+	 *
+	 * @param row 当前行数据
+	 */
+	const handleForceLogout = (row: any) => {
+		// prettier-ignore
+		proxy.$modal.confirm('是否强退【' + row.userName + '】的用户?', "警告")
+            .then(() => {
+                return forceLogout(row.tokenId);
+            })
+            .then((response: any) => {
+                if (response.code === 200) {
+                    getList();
+                    proxy.$modal.msgSuccess(row.userName + "强退成功!");
+                }
+            })
+            .catch(() => {
+                console.log("取消了强退");
+            });
+	};
+
+	onMounted(() => {
+		getList();
+	});
+
+	// prettier-ignore
+	return {
+        loading, total, tablelist, queryParams, queryFormRef, handleQuery, resetQuery, handleForceLogout
+    };
+};

+ 24 - 0
src/api/request/monitor/server/index.ts

@@ -0,0 +1,24 @@
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { getServer } from "@/api/system/server";
+
+export default () => {
+	// 服务器信息
+	const server = ref<any>([]);
+	const { proxy } = getCurrentInstance() as any;
+
+	/** 查询服务器信息 */
+	const getList = () => {
+		proxy.$modal.loading("正在加载服务监控数据,请稍候!");
+		getServer().then((response: any) => {
+			server.value = response.data;
+			proxy.$modal.closeLoading();
+		});
+	};
+	onMounted(() => {
+		getList();
+	});
+
+    return {
+        server
+    }
+};

+ 210 - 0
src/api/request/system/config/index.ts

@@ -0,0 +1,210 @@
+import { ref, getCurrentInstance, onMounted } from "vue";
+// prettier-ignore
+import { listConfig, getConfig, delConfig, addConfig, updateConfig, exportConfig, clearCache } from "@/api/system/config";
+import { ElForm, ElTable } from "element-plus";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	// 遮罩层
+	const loading = ref<boolean>(true);
+	// 选中数组
+	const ids = ref<any>();
+	// 非单个禁用
+	const single = ref<boolean>(true);
+	// 非多个禁用
+	const multiple = ref<boolean>(true);
+	// 显示搜索条件
+	const showSearch = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 参数表格数据
+	const configList = ref<any>();
+	// 弹出层标题
+	const title = ref<string>("");
+	// 是否显示弹出层
+	const open = ref<boolean>(false);
+	// 类型数据字典
+	const typeOptions = ref<any>();
+	// 日期范围
+	const dateRange = ref<any>();
+	// 查询参数
+	const queryParams = ref({
+		pageNum: 1,
+		pageSize: 10,
+		configName: undefined,
+		configKey: undefined,
+		configType: undefined,
+	});
+	const queryFormRef = ref<InstanceType<typeof ElForm>>();
+	// 表单参数
+	const form = ref<any>();
+	const formRef = ref<InstanceType<typeof ElForm>>();
+    const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	// 表单校验
+	const rules = ref({
+		configName: [
+			{
+				required: true,
+				message: "参数名称不能为空",
+				trigger: "blur",
+			},
+		],
+		configKey: [
+			{
+				required: true,
+				message: "参数键名不能为空",
+				trigger: "blur",
+			},
+		],
+		configValue: [
+			{
+				required: true,
+				message: "参数键值不能为空",
+				trigger: "blur",
+			},
+		],
+	});
+
+	/** 查询参数列表 */
+	const getList = () => {
+		loading.value = true;
+		// prettier-ignore
+		listConfig(proxy.addDateRange(queryParams.value, dateRange.value)).then((response: any) => {
+				configList.value = response.rows;
+				total.value = parseInt(response.total);
+				loading.value = false;
+			});
+	};
+	// 参数系统内置字典翻译
+	const typeFormat = (row: any, column: any) => {
+		return proxy.selectDictLabel(typeOptions.value, row.configType);
+	};
+    const cleanSelect = () => {
+        pageTableRef.value?.clearSelection();
+    };
+	// 取消按钮
+	const cancel = () => {
+		open.value = false;
+		reset();
+        cleanSelect();
+	};
+	// 表单重置
+	const reset = () => {
+		form.value = {
+			configId: undefined,
+			configName: undefined,
+			configKey: undefined,
+			configValue: undefined,
+			configType: "Y",
+			remark: undefined,
+		};
+		proxy.resetForm(formRef);
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getList();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		dateRange.value = [];
+		proxy.resetForm(queryFormRef);
+		handleQuery();
+	};
+	/** 新增按钮操作 */
+	const handleAdd = () => {
+		reset();
+		title.value = "添加参数";
+        open.value = true;
+	};
+	// 多选框选中数据
+	const handleSelectionChange = (selection: any) => {
+		ids.value = selection.map((item: any) => item.configId);
+		single.value = selection.length != 1;
+		multiple.value = !selection.length;
+	};
+	/** 修改按钮操作 */
+	const handleUpdate = (row: any) => {
+		reset();
+		const configId = row.configId || ids.value;
+		getConfig(configId).then((response: any) => {
+			form.value = response.data;
+			open.value = true;
+			title.value = "修改参数";
+            proxy.setTableRowSelected(pageTableRef, row, true);
+		});
+	};
+	/** 提交按钮 */
+	const submitForm = async () => {
+		await formRef.value?.validate((valid: boolean) => {
+			if (valid) {
+				if (form.value.configId != undefined) {
+					updateConfig(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("修改成功");
+							open.value = false;
+							getList();
+						}
+					});
+				} else {
+					addConfig(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("新增成功");
+							open.value = false;
+							getList();
+						}
+					});
+				}
+			}
+		});
+	};
+	/** 删除按钮操作 */
+	const handleDelete = (row: any) => {
+		const configIds = row.configId || ids.value;
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		// prettier-ignore
+		proxy.$modal.confirm('是否确认删除参数编号为"' + configIds + '"的数据项?', "警告")
+            .then(() =>{
+                return delConfig(configIds);
+            })
+            .then((response: any) => {
+                if (response.code === 200) {
+                    getList();
+                    proxy.$modal.msgSuccess("删除成功");
+                }
+            })
+            .catch(() => {
+                cleanSelect();
+                console.log("取消了删除");
+            });
+	};
+	/** 导出按钮操作 */
+	const handleExport = () => {
+		// prettier-ignore
+		proxy.download('/system/config/exportByStream', {...queryParams}, `参数配置${new Date().getTime()}.xlsx`);
+	};
+	/** 清理缓存按钮操作 */
+	const handleClearCache = () => {
+		clearCache().then((response: any) => {
+            if (response.code === 200) {
+                proxy.$modal.msgSuccess("清理成功");
+            }
+		});
+	};
+
+    onMounted(() => {
+        getList();
+		proxy.getDicts("sys_yes_no").then((response: any) => {
+            if (response.code === 200) {
+                typeOptions.value = response.data;
+            }
+		});
+    });
+
+    // prettier-ignore
+    return {
+        loading, single, multiple, open, showSearch, total, configList, title, typeOptions, dateRange, queryParams, queryFormRef, form, formRef, rules, 
+        getList, typeFormat, cancel, reset, handleQuery, resetQuery, handleAdd, handleSelectionChange, handleUpdate, submitForm, handleDelete, 
+        handleExport, handleClearCache, pageTableRef, cleanSelect, 
+    };
+};

+ 284 - 0
src/api/request/system/dept/index.ts

@@ -0,0 +1,284 @@
+import { setTableRowSelected } from './../../../../utils/ruoyi';
+import { ref, getCurrentInstance, nextTick, onMounted, } from "vue";
+// prettier-ignore
+import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild, page, batchDelDept } from "@/api/system/dept";
+import { ElForm, ElTable } from "element-plus";
+import { debounce } from '@/utils';
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
+	const statusOptions = ref<any>();
+	const deptList = ref<any>();
+	const open = ref<boolean>(false);
+	const loading = ref<boolean>(true);
+	const showSearch = ref<boolean>(true);
+	const title = ref<string>("");
+	const deptOptions = ref<any>();
+	const isExpandAll = ref<boolean>(true);
+	const refreshTable = ref<boolean>(true);
+	const form = ref<any>();
+	const queryParams = ref<any>({
+		pageNum: 1,
+		pageSize: 10,
+		deptName: undefined,
+		status: undefined,
+	});
+	const rules = ref<any>({
+		parentId: [
+			{ required: true, message: "上级部门不能为空", trigger: "blur" },
+		],
+		deptName: [
+			{ required: true, message: "部门名称不能为空", trigger: "blur" },
+		],
+		orderNum: [
+			{ required: true, message: "显示排序不能为空", trigger: "blur" },
+		],
+		email: [
+			{
+				type: "email",
+				message: "请输入正确的邮箱地址",
+				trigger: ["blur", "change"],
+			},
+		],
+		phone: [
+			{
+				pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
+				message: "请输入正确的手机号码",
+				trigger: "blur",
+			},
+		],
+	});
+	// 选中数组
+	const ids = ref<any>();
+	// 非单个禁用
+	const single = ref<boolean>(true);
+	// 非多个禁用
+	const multiple = ref<boolean>(true);
+	const pageTable = ref<boolean>(false);
+	// 总条数
+	const total = ref<number>(0);
+	const pageTableList = ref<any>();
+	const tableSwitch = ref<string>("分页表格");
+	const switchIcon = ref<string>("list");
+	const pageLoading = ref<boolean>(true);
+
+	const deptRef = ref<InstanceType<typeof ElForm>>();
+	const queryRef = ref<InstanceType<typeof ElForm>>();
+	const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	/** 查询部门列表 */
+	const getList = async () => {
+		loading.value = true;
+		await listDept(queryParams.value).then((response: any) => {
+			if (response.code === 200) {
+				deptList.value = proxy.handleTree(response.data, "deptId");
+				loading.value = false;
+			}
+		});
+	};
+	/**
+	 * 分页数据
+	 */
+	const getPage = async () => {
+		pageLoading.value = true;
+		// prettier-ignore
+		await page(queryParams.value).then((response: any) => {
+			if (response.code === 200) {
+                const data =  response.data;
+                pageTableList.value = data.rows;
+                total.value = parseInt(data.total);
+                pageLoading.value = false;
+            }
+		});
+	};
+
+    const cleanSelect = () => {
+        proxy.cleanTableSelection(pageTableRef);
+    };
+
+	/** 取消按钮 */
+	const cancel = () => {
+		reset();
+        cleanSelect();
+		open.value = false;
+	};
+	/** 表单重置 */
+	const reset = () => {
+		form.value = {
+			deptId: undefined,
+			parentId: undefined,
+			deptName: undefined,
+			orderNum: 0,
+			leader: undefined,
+			phone: undefined,
+			email: undefined,
+			status: "0",
+		};
+		proxy.resetForm(deptRef);
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		if (total.value === 0 && !pageTable.value) {
+			getList();
+		} else {
+			getPage();
+		}
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		proxy.resetForm(queryRef);
+		handleQuery();
+	};
+	/**
+	 * 切换表格数据
+	 */
+	const switchTable = () => {
+		ids.value = [];
+		pageTable.value = !pageTable.value;
+		refreshTable.value = !refreshTable.value;
+		if (!pageTable.value && refreshTable.value) {
+			total.value = 0;
+			tableSwitch.value = "分页表格";
+			switchIcon.value = "list";
+			getList();
+		} else {
+			tableSwitch.value = "树形表格";
+			switchIcon.value = "grid";
+			getPage();
+		}
+	};
+
+    // 切换表格增加防抖
+    const handleSwitch = debounce(switchTable, 700, true);
+	// 多选框选中数据
+	const multipleSelection = (selection: any) => {
+		ids.value = selection.map((item: any) => item.deptId);
+		single.value = selection.length != 1;
+		multiple.value = !selection.length;
+	};
+	/** 新增按钮操作 */
+	const handleAdd = async (row: any) => {
+		reset();
+		await listDept().then((response: any) => {
+			if (response.code === 200) {
+				deptOptions.value = proxy.handleTree(response.data, "deptId");
+			}
+		});
+		if (row != undefined) {
+			form.value.parentId = row.deptId;
+		}
+		title.value = "添加部门";
+		open.value = true;
+	};
+	/** 展开/折叠操作 */
+	const toggleExpandAll = () => {
+		refreshTable.value = false;
+		isExpandAll.value = !isExpandAll.value;
+		nextTick(() => {
+			refreshTable.value = true;
+		});
+	};
+	/** 修改按钮操作 */
+	const handleUpdate = async (row: any) => {
+		const deptId = row.deptId || ids.value[0];
+		reset();
+		await listDeptExcludeChild(deptId).then((response: any) => {
+			if (response.code === 200) {
+				deptOptions.value = proxy.handleTree(response.data, "deptId");
+			}
+		});
+		await getDept(deptId).then((response: any) => {
+			if (response.code === 200) {
+				const data = response.data;
+				data.orderNum = parseInt(data.orderNum);
+				// 修复顶级父部门显示为0的问题
+				if (data.parentId === "0") {
+					data.parentId = parseInt(data.parentId);
+				}
+				form.value = data;
+				title.value = "修改部门";
+                proxy.setTableRowSelected(pageTableRef, row, true);
+				open.value = true;
+			}
+		});
+	};
+	/** 提交按钮 */
+	const submitForm = async () => {
+		await deptRef.value?.validate((valid: boolean) => {
+			if (valid) {
+				if (form.value.deptId !== undefined) {
+					updateDept(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("修改成功");
+							open.value = false;
+							handleQuery();
+						}
+					});
+				} else {
+					addDept(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("新增成功");
+							open.value = false;
+							handleQuery();
+						}
+					});
+				}
+			}
+		});
+	};
+	/** 删除按钮操作 */
+	const handleDelete = (row: any) => {
+        // 设置当前行被选中
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		proxy.$modal
+			.confirm('是否确认删除名称为"' + row.deptName + '"的数据项?')
+			.then(() => {
+				return delDept(row.deptId);
+			})
+			.then((response: any) => {
+				if (response.code === 200) {
+					proxy.$modal.msgSuccess("删除成功");
+					getList();
+				}
+			})
+			.catch(() => {
+                // 取消当前行选中
+                proxy.setTableRowSelected(pageTableRef, row, false);
+				console.log("取消了删除");
+			});
+	};
+
+	/** 删除按钮操作 */
+	const batchDelete = () => {
+		const deptIds = ids.value;
+		// prettier-ignore
+		proxy.$modal.confirm('是否确认删除编号为【"' + deptIds + '"】的数据?')
+			.then(() => {
+				return batchDelDept(deptIds);
+			})
+			.then((response: any) => {
+				if (response.code === 200) {
+					proxy.$modal.msgSuccess("批量删除成功");
+				}
+				getPage();
+			})
+			.catch(() => {
+                // 取消表格选中项
+                cleanSelect();
+				console.log("取消了批量删除");
+			});
+	};
+	onMounted(() => {
+		getList();
+		proxy.getDicts("sys_normal_disable").then((response: any) => {
+			statusOptions.value = response.data;
+		});
+	});
+	// prettier-ignore
+	return {
+        loading, open, showSearch, title, deptOptions, deptList,  isExpandAll, refreshTable, queryParams, form, rules, sys_normal_disable, queryRef, 
+        statusOptions, deptRef, single, multiple, pageTable, pageLoading, total, pageTableList, switchIcon, tableSwitch, getPage, handleSwitch, cancel, 
+        multipleSelection, batchDelete, handleQuery, resetQuery, handleAdd, toggleExpandAll, handleUpdate, submitForm, handleDelete, ids, 
+        pageTableRef, cleanSelect
+    };
+};

+ 230 - 0
src/api/request/system/dict/data.ts

@@ -0,0 +1,230 @@
+import { setTableRowSelected } from './../../../../utils/ruoyi';
+// prettier-ignore
+import { listData, getData, delData, addData, updateData } from "@/api/system/dict/data";
+import { listType, getDataType } from "@/api/system/dict/type";
+import { ElForm, ElTable } from "element-plus";
+import { ref, getCurrentInstance, onMounted } from "vue";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	// 遮罩层
+	const loading = ref<boolean>(true);
+	// 选中数组
+	const ids = ref<any>();
+	// 非单个禁用
+	const single = ref<boolean>(true);
+	// 非多个禁用
+	const multiple = ref<boolean>(true);
+	// 显示搜索条件
+	const showSearch = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 字典表格数据
+	const dataList = ref<any>();
+	// 默认字典类型
+	const defaultDictType = ref<string>("");
+	// 弹出层标题
+	const title = ref<string>("");
+	// 是否显示弹出层
+	const open = ref<boolean>(false);
+	// 状态数据字典
+	const statusOptions = ref<any>();
+	// 类型数据字典
+	const typeOptions = ref<any>();
+    // 日期范围
+	const dateRange = ref<any>();
+	// 查询参数
+	const queryParams = ref<any>({
+		pageNum: 1,
+		pageSize: 10,
+		dictName: undefined,
+		dictType: undefined,
+		status: undefined,
+	});
+	// 表单参数
+	const form = ref<any>();
+	const formRef = ref<InstanceType<typeof ElForm>>();
+	const queryFormRef = ref<InstanceType<typeof ElForm>>();
+    const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	// 表单校验
+	const rules = {
+		dictLabel: [
+			{
+				required: true,
+				message: "数据标签不能为空",
+				trigger: "blur",
+			},
+		],
+		dictValue: [
+			{
+				required: true,
+				message: "数据键值不能为空",
+				trigger: "blur",
+			},
+		],
+		dictSort: [
+			{
+				required: true,
+				message: "数据顺序不能为空",
+				trigger: "blur",
+			},
+		],
+	};
+
+	/** 查询字典类型详细 */
+	const getType = (dictId: string) => {
+		getDataType(dictId).then((response: any) => {
+			queryParams.value.dictType = response.data.dictType;
+			defaultDictType.value = response.data.dictType;
+			getList();
+		});
+	};
+	/** 查询字典类型列表 */
+	const getTypeList = () => {
+		listType().then((response: any) => {
+			typeOptions.value = response.rows;
+		});
+	};
+	/** 查询字典数据列表 */
+	const getList = () => {
+		loading.value = true;
+		listData(proxy.addDateRange(queryParams.value, dateRange.value)).then((response: any) => {
+			dataList.value = response.rows;
+			total.value = parseInt(response.total);
+			loading.value = false;
+		});
+	};
+	// 数据状态字典翻译
+	const statusFormat = (row: any) => {
+		return proxy.selectDictLabel(statusOptions.value, row.status);
+	};
+
+    /**
+     * 取消表格选中
+     */
+     const cleanSelect = () => {
+        proxy.cleanTableSelection(pageTableRef);
+    };
+
+	// 取消按钮
+	const cancel = () => {
+		open.value = false;
+		reset();
+        cleanSelect();
+	};
+	// 表单重置
+	const reset = () => {
+		form.value = {
+			dictCode: undefined,
+			dictLabel: undefined,
+			dictValue: undefined,
+			dictSort: 0,
+			status: "0",
+			remark: undefined,
+		};
+		proxy.resetForm(formRef);
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getList();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+        dateRange.value = [];
+		proxy.resetForm(queryFormRef);
+		queryParams.value.dictType = defaultDictType.value;
+		handleQuery();
+	};
+	/** 新增按钮操作 */
+	const handleAdd = () => {
+		reset();
+		title.value = "添加字典数据";
+		form.value.dictType = queryParams.value.dictType;
+		open.value = true;
+	};
+	// 多选框选中数据
+	const handleSelectionChange = (selection: any) => {
+		ids.value = selection.map((item: any) => item.dictCode);
+		single.value = selection.length != 1;
+		multiple.value = !selection.length;
+	};
+	/** 修改按钮操作 */
+	const handleUpdate = (row: any) => {
+		reset();
+		const dictCode = row.dictCode || ids.value;
+		getData(dictCode).then((response) => {
+			response.data.dictSort = parseInt(response.data.dictSort);
+			form.value = response.data;
+			title.value = "修改字典数据";
+            // 设置当前行选中
+            proxy.setTableRowSelected(pageTableRef, row, true);
+			open.value = true;
+		});
+	};
+	/** 提交按钮 */
+	const submitForm = () => {
+		formRef.value?.validate((valid: boolean) => {
+			if (valid) {
+				if (form.value.dictCode != undefined) {
+					updateData(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("修改成功");
+							open.value = false;
+							getList();
+						}
+					});
+				} else {
+					addData(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("新增成功");
+							open.value = false;
+							getList();
+						}
+					});
+				}
+			}
+		});
+	};
+	/** 删除按钮操作 */
+	const handleDelete = (row: any) => {
+		const dictCodes = row.dictCode || ids.value;
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		// prettier-ignore
+		proxy.$modal.confirm('是否确认删除字典编码为"' + dictCodes + '"的数据项?', "警告")
+        .then(() => {
+            return delData(dictCodes);
+        })
+        .then((response: any) => {
+            if (response.code === 200) {
+                getList();
+                proxy.$modal.msgSuccess("删除成功");
+            }
+        })
+        .catch(() => {
+            cleanSelect();
+            console.log("取消了删除");
+        });
+	};
+	/** 导出按钮操作 */
+	const handleExport = () => {
+		// prettier-ignore
+		proxy.download('/system/dict/data/exportByStream', {...queryParams}, `字典数据信息${new Date().getTime()}.xlsx`);
+	};
+
+	onMounted(() => {
+		const dictId = proxy.$route.params && proxy.$route.params.dictId;
+		getType(dictId);
+		getTypeList();
+		proxy.getDicts("sys_normal_disable").then((response: any) => {
+			statusOptions.value = response.data;
+		});
+	});
+
+	// prettier-ignore
+	return {
+        loading, single, multiple, showSearch, total, dataList, title, open, statusOptions, typeOptions, dateRange, queryParams, form, formRef, 
+        queryFormRef, rules, pageTableRef, getList, statusFormat, cancel, handleQuery, resetQuery, handleSelectionChange, handleAdd, handleUpdate, 
+        submitForm, handleDelete, handleExport, cleanSelect, 
+    };
+};

+ 242 - 0
src/api/request/system/dict/index.ts

@@ -0,0 +1,242 @@
+import { getCurrentInstance, ref } from "vue";
+// prettier-ignore
+import { listType, getDataType, delType, addType, updateType, exportType, clearCache, updateDictTypeStatus, } from "@/api/system/dict/type";
+import { ElForm, ElTable } from "element-plus";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	// 遮罩层
+	const loading = ref<boolean>(true);
+	// 选中数组
+	const ids = ref<any>();
+	// 非单个禁用
+	const single = ref<boolean>(true);
+	// 非多个禁用
+	const multiple = ref<boolean>(true);
+	// 显示搜索条件
+	const showSearch = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 字典表格数据
+	const typeList = ref<any>();
+	// 弹出层标题
+	const title = ref<string>("");
+	// 是否显示弹出层
+	const open = ref<boolean>(false);
+	// 状态数据字典
+	const statusOptions = ref<any>();
+	// 查询参数
+	const queryParams = ref({
+		pageNum: 1,
+		pageSize: 10,
+		dictName: undefined,
+		dictType: undefined,
+		status: undefined,
+	});
+    // 日期范围
+	const dateRange = ref<any>();
+	// 表单参数
+	const form = ref<any>();
+	const formRef = ref<InstanceType<typeof ElForm>>();
+	const queryFormRef = ref<InstanceType<typeof ElForm>>();
+    const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	// 表单校验
+	const rules = ref({
+		dictName: [
+			{
+				required: true,
+				message: "字典名称不能为空",
+				trigger: "blur",
+			},
+		],
+		dictType: [
+			{
+				required: true,
+				message: "字典类型不能为空",
+				trigger: "blur",
+			},
+		],
+	});
+
+	/** 查询字典类型列表 */
+	const getList = () => {
+        typeList.value = [];
+		loading.value = true;
+		listType(proxy.addDateRange(queryParams.value, dateRange.value)).then(
+			(response: any) => {
+				typeList.value = response.rows;
+				total.value = parseInt(response.total);
+				loading.value = false;
+			}
+		);
+	};
+	// 字典状态字典翻译
+	const statusFormat = (row: any) => {
+		return proxy.selectDictLabel(statusOptions.value, row.status);
+	};
+
+    /**
+     * 取消表格选中
+     */
+    const cleanSelect = () => {
+        proxy.cleanTableSelection(pageTableRef);
+    };
+
+	// 取消按钮
+	const cancel = () => {
+		open.value = false;
+		reset();
+        cleanSelect();
+	};
+	// 表单重置
+	const reset = () => {
+		form.value = {
+			dictId: undefined,
+			dictName: undefined,
+			dictType: undefined,
+			status: "0",
+			remark: undefined,
+		};
+		proxy.resetForm(formRef);
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getList();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		dateRange.value = [];
+		proxy.resetForm(queryFormRef);
+		handleQuery();
+	};
+	/** 新增按钮操作 */
+	const handleAdd = () => {
+		reset();
+		title.value = "添加字典类型";
+		open.value = true;
+	};
+	// 多选框选中数据
+	const handleSelectionChange = (selection: any) => {
+		ids.value = selection.map((item: any) => item.dictId);
+		single.value = selection.length != 1;
+		multiple.value = !selection.length;
+	};
+	/** 修改按钮操作 */
+	const handleUpdate = (row: any) => {
+		reset();
+		const dictId = row.dictId || ids.value;
+		getDataType(dictId).then((response: any) => {
+			form.value = response.data;
+			title.value = "修改字典类型";
+            proxy.setTableRowSelected(pageTableRef, row, true);
+			open.value = true;
+		});
+	};
+    /**
+     * 修改状态
+     * 
+     * @param val 当前选中的值
+     * @param row 当前行数据
+     */
+    const updateStatus = async (val: any, row: any) => {
+        /* console.log("aaaaa", row.status);
+        const text = row.status === "0" ? "停用" : "启用";
+        await proxy.$confirm(
+            "确认要" + text + "吗?", "警告",
+            {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning",
+            }
+        ).then(() => {
+            return updateDictTypeStatus(row.dictId, val);
+        })
+        .then((response: any) => {
+            if (response.code === 200) {
+                proxy.$modal.msgSuccess(response.msg);
+                getList();
+            }
+        })
+        .catch(() => {
+            console.log("ssssss", row.status, val);
+            row.status = val === "0" ? "1" : "0";
+        }); */
+        await updateDictTypeStatus(row.dictId, val).then((response: any) => {
+            if (response.code === 200) {
+                proxy.$modal.msgSuccess(response.msg);
+                getList();
+            }
+        })
+    };
+	/** 提交按钮 */
+	const submitForm = () => {
+		formRef.value?.validate((valid) => {
+			if (valid) {
+				if (form.value.dictId != undefined) {
+					updateType(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("修改成功");
+							open.value = false;
+							getList();
+						}
+					});
+				} else {
+					addType(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("新增成功");
+							open.value = false;
+							getList();
+						}
+					});
+				}
+			}
+		});
+	};
+	/** 删除按钮操作 */
+	const handleDelete = (row: any) => {
+		const dictIds = row.dictId || ids.value;
+        if (row) {
+            proxy.setTableRowSelected(pageTableRef, row, true);
+        }
+		// prettier-ignore
+		proxy.$modal.confirm('是否确认删除字典编号为"' + dictIds + '"的数据项?', "警告")
+            .then(() => {
+                return delType(dictIds);
+            })
+            .then((response: any) => {
+                if (response.code === 200) {
+                    getList();
+                    proxy.$modal.msgSuccess("删除成功");
+                }
+            }).catch(() => {
+                cleanSelect();
+                console.log("取消了删除");
+            });
+	};
+	/** 导出按钮操作 */
+	const handleExport = () => {
+		// prettier-ignore
+		proxy.download('/system/dict/type/exportByStream', {...queryParams}, `字典信息${new Date().getTime()}.xlsx`);
+	};
+	/** 清理缓存按钮操作 */
+	const handleClearCache = () => {
+		clearCache().then((response) => {
+			proxy.$modal.msgSuccess("清理成功");
+		});
+	};
+
+
+    getList();
+    proxy.getDicts("sys_normal_disable").then((response: { data: any }) => {
+        statusOptions.value = response.data;
+    });
+
+    // prettier-ignore
+	return {
+        loading, single, multiple, showSearch, total, typeList, title, open, statusOptions, queryParams, dateRange, form, formRef, queryFormRef, rules, 
+        getList, cancel, handleQuery, resetQuery, handleSelectionChange, handleAdd, handleUpdate, updateStatus, submitForm, handleDelete, handleExport, 
+        handleClearCache, pageTableRef, cleanSelect
+    };
+
+};

+ 319 - 0
src/api/request/system/menu/index.ts

@@ -0,0 +1,319 @@
+import { ElForm, ElTable } from "element-plus";
+// prettier-ignore
+import { ref, getCurrentInstance, nextTick, onMounted } from "vue";
+// prettier-ignore
+import { addMenu, batchDelMenu, delMenu, getMenu, listMenu, pageList, updateMenu, } from "@/api/system/menu";
+import { lodashFunc } from "@/utils/ruoyi";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	const open = ref<boolean>(false);
+	const loading = ref<boolean>(true);
+	const pageLoading = ref<boolean>(true);
+	const showSearch = ref<boolean>(true);
+	// 选中数组
+	const ids = ref<any>();
+	// 非单个禁用
+	const single = ref<boolean>(true);
+	// 非多个禁用
+	const multiple = ref<boolean>(true);
+	const title = ref<string>("");
+	// 总条数
+	const total = ref<number>(0);
+	const menuList = ref<any>();
+	const pageTable = ref<boolean>(false);
+	const menuPage = ref<any>();
+	const menuOptions = ref<any>([]);
+	const isExpandAll = ref<boolean>(false);
+	const refreshTable = ref<boolean>(true);
+	const showChooseIcon = ref<boolean>(false);
+	const iconSelectRef = ref<any>();
+	const menuRef = ref<InstanceType<typeof ElForm>>();
+	const queryRef = ref<InstanceType<typeof ElForm>>();
+    const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	const dateRange = ref<any>([]);
+    const dateRange2 = ref<string>("");
+	const elTreeProps = ref({
+		value: "menuId",
+		label: "menuName",
+		children: "children",
+	});
+	const form = ref<any>();
+	const queryParams = ref<any>({
+		pageNum: 1,
+		pageSize: 10,
+		menuName: undefined,
+		visible: undefined,
+		status: undefined,
+        editTimeScope: undefined
+	});
+	const rules = ref({
+		menuName: [
+			{
+				required: true,
+				message: "菜单名称不能为空",
+				trigger: "blur",
+			},
+		],
+		orderNum: [
+			{
+				required: true,
+				message: "菜单顺序不能为空",
+				trigger: "blur",
+			},
+		],
+		path: [
+			{
+				required: true,
+				message: "路由地址不能为空",
+				trigger: "blur",
+			},
+		],
+	});
+
+	// prettier-ignore
+	const { sys_show_hide, sys_normal_disable } = proxy.useDict("sys_show_hide", "sys_normal_disable");
+
+	const tableSwitch = ref<string>("分页表格");
+	const switchIcon = ref<string>("list");
+
+	/** 查询菜单列表 */
+	const getList = async () => {
+		loading.value = true;
+        proxy.addDateRange(queryParams.value, dateRange.value);
+        queryParams.value.editTimeScope =  dateRange2.value.toString();
+		await listMenu(queryParams.value
+		).then((response: any) => {
+			menuList.value = proxy.handleTree(response.data, "menuId");
+			loading.value = false;
+		});
+	};
+
+	/** 查询菜单分页列表 */
+	const getPage = async () => {
+		pageLoading.value = true;
+        queryParams.value.editTimeScope =  dateRange2.value.toString();
+        proxy.addDateRange(queryParams.value, dateRange.value);
+		await pageList(queryParams.value).then((response: any) => {
+			if (response.code === 200) {
+				const data = response.data;
+				menuPage.value = data.rows;
+				total.value = parseInt(data.total);
+				pageLoading.value = false;
+			}
+		});
+	};
+	/** 查询菜单下拉树结构 */
+	const getTreeselect = async () => {
+		menuOptions.value = [];
+		await listMenu().then((response: any) => {
+			const data = response.data;
+			const menu = { menuId: 0, menuName: "主类目", children: [] };
+			menu.children = proxy.handleTree(data, "menuId");
+			menuOptions.value.push(menu);
+		});
+	};
+
+    const cleanSelect = () => {
+        pageTableRef.value?.clearSelection();
+    };
+
+	/** 取消按钮 */
+	const cancel = () => {
+		reset();
+        cleanSelect();
+		open.value = false;
+	};
+	/** 表单重置 */
+	const reset = () => {
+		form.value = {
+			menuId: undefined,
+			parentId: 0,
+			menuName: undefined,
+			icon: undefined,
+			menuType: "M",
+			orderNum: undefined,
+			isFrame: "1",
+			isCache: "0",
+			visible: "0",
+			status: "0",
+		};
+		proxy.resetForm(menuRef);
+	};
+	/** 展示下拉图标 */
+	const showSelectIcon = () => {
+		iconSelectRef.value?.reset();
+		showChooseIcon.value = true;
+	};
+	/** 选择图标 */
+	const selected = (name: string) => {
+		form.value.icon = name;
+		showChooseIcon.value = false;
+	};
+	/** 图标外层点击隐藏下拉列表 */
+	const hideSelectIcon = () => {
+		showChooseIcon.value = false;
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		if (total.value === 0 && !pageTable.value) {
+			getList();
+		} else {
+			getPage();
+		}
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		dateRange.value = [];
+        dateRange2.value ="";
+		proxy.resetForm(queryRef);
+		handleQuery();
+	};
+	/** 新增按钮操作 */
+	const handleAdd = (row: any) => {
+		reset();
+		getTreeselect();
+		if (row != null && row.menuId) {
+			form.value.parentId = row.menuId;
+		} else {
+			form.value.parentId = 0;
+		}
+		open.value = true;
+		title.value = "添加菜单";
+	};
+	// 多选框选中数据
+	const multipleSelection = (selection: any) => {
+		ids.value = selection.map((item: any) => item.menuId);
+		single.value = selection.length != 1;
+		multiple.value = !selection.length;
+	};
+	/**
+	 * 切换表格数据
+	 */
+	const witchTable = () => {
+        ids.value = [];
+		pageTable.value = !pageTable.value;
+		refreshTable.value = !refreshTable.value;
+		if (!pageTable.value && refreshTable.value) {
+			total.value = 0;
+			tableSwitch.value = "分页表格";
+            switchIcon.value = "list";
+			getList();
+		} else {
+			tableSwitch.value = "树形表格";
+            switchIcon.value = "grid";
+			getPage();
+		}
+	};
+    // 切换表格增加防抖
+    const handleSwitch = lodashFunc(witchTable, 700);
+
+	/** 展开/折叠操作 */
+	const toggleExpandAll = () => {
+		refreshTable.value = false;
+		isExpandAll.value = !isExpandAll.value;
+		nextTick(() => {
+			refreshTable.value = true;
+		});
+	};
+	/** 修改按钮操作 */
+	const handleUpdate = (row: any) => {
+		const menuId = row.menuId || ids.value;
+		reset();
+		getTreeselect();
+		// prettier-ignore
+		getMenu(menuId).then((response: any) => {
+				if (response.code === 200) {
+					const data = response.data;
+					// 后端返回parentId为字符串并且是父目录情况下需要转换下parentId,不然会显示为0
+					if (data.parentId === "0") {
+						data.parentId = parseInt(data.parentId);
+					}
+					/* [Vue warn]: Invalid prop: type check failed for prop "modelValue". Expected Number with value 3, got String with value "3".*/
+					data.orderNum = parseInt(data.orderNum);
+					form.value = data;
+				}
+			})
+			.finally(() => {
+				title.value = "修改菜单";
+				open.value = true;
+			});
+	};
+	/** 提交按钮 */
+	const submitForm = async () => {
+		await menuRef.value?.validate((valid: boolean) => {
+			if (valid) {
+				if (form.value.menuId !== undefined) {
+					updateMenu(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("修改成功");
+							open.value = false;
+							handleQuery();
+						}
+					});
+				} else {
+					addMenu(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("新增成功");
+							open.value = false;
+							handleQuery();
+						}
+					});
+				}
+			}
+		});
+	};
+	/** 删除按钮操作 */
+	const handleDelete = (row: any) => {
+        // 设置当前行被选中
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		// prettier-ignore
+		proxy.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?')
+			.then(() => {
+				return delMenu(row.menuId);
+			})
+			.then((response: any) => {
+				if (response.code === 200) {
+					proxy.$modal.msgSuccess("删除成功");
+                    getList();
+				}
+			})
+			.catch(() => {
+                proxy.setTableRowSelected(pageTableRef, row, false);
+				console.log("取消了删除");
+			});
+	};
+
+	/** 批量删除按钮操作 */
+	const batchDelete = () => {
+		const menuIds = ids.value;
+		// prettier-ignore
+		proxy.$modal.confirm('是否确认删除编号为【"' + menuIds + '"】的数据?')
+			.then(() => {
+				return batchDelMenu(menuIds);
+			})
+			.then((response: any) => {
+				if (response.code === 200) {
+					proxy.$modal.msgSuccess("批量删除成功");
+                    getPage();
+				}
+			})
+			.catch(() => {
+                // 取消表格选中项
+                cleanSelect();
+				console.log("取消了批量删除");
+			});
+	};
+
+	onMounted(() => {
+		getList();
+	});
+
+	// prettier-ignore
+	return {
+        loading, open, queryRef, showSearch, title, total, menuList, menuOptions, isExpandAll, refreshTable, showChooseIcon, iconSelectRef, menuRef, 
+        queryParams, form, rules, sys_show_hide, sys_normal_disable, dateRange, elTreeProps, menuPage, pageTable, single, multiple, pageLoading,  
+        getList, cancel, showSelectIcon, selected, hideSelectIcon, handleQuery, resetQuery, handleAdd, toggleExpandAll, handleUpdate, submitForm, 
+        handleDelete, handleSwitch, getPage, multipleSelection, batchDelete, switchIcon, tableSwitch, ids, pageTableRef, cleanSelect, dateRange2,
+    }
+};

+ 225 - 0
src/api/request/system/notice/notice.ts

@@ -0,0 +1,225 @@
+import { setTableRowSelected } from './../../../../utils/ruoyi';
+import { ref, getCurrentInstance, onMounted } from "vue";
+// prettier-ignore
+import { listNotice, getNotice, delNotice, addNotice, updateNotice, } from "@/api/system/notice";
+import { ElForm, ElTable } from "element-plus";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	// 遮罩层
+	const loading = ref<boolean>(true);
+	// 选中数组
+	const ids = ref<any>();
+	// 非单个禁用
+	const single = ref<boolean>(true);
+	// 非多个禁用
+	const multiple = ref<boolean>(true);
+	// 显示搜索条件
+	const showSearch = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 公告表格数据
+	const noticeList = ref<any>();
+	// 弹出层标题
+	const title = ref<string>("");
+	// 是否显示弹出层
+	const open = ref<boolean>(false);
+	// 类型数据字典
+	const statusOptions = ref<any>();
+	// 状态数据字典
+	const typeOptions = ref<any>();
+	// 查询参数
+	const queryParams = ref<any>({
+		pageNum: 1,
+		pageSize: 10,
+		noticeTitle: undefined,
+		createBy: undefined,
+		status: undefined,
+	});
+	// 表单参数
+	const form = ref<any>();
+	// 表单ref
+	const formRef = ref<InstanceType<typeof ElForm>>();
+	const queryFormRef = ref<InstanceType<typeof ElForm>>();
+    const pageTable = ref<InstanceType<typeof ElTable>>();
+	// 表单校验
+	const rules = ref({
+		noticeTitle: [
+			{
+				required: true,
+				message: "公告标题不能为空",
+				trigger: "blur",
+			},
+		],
+		noticeType: [
+			{
+				required: true,
+				message: "公告类型不能为空",
+				trigger: "change",
+			},
+		],
+	});
+
+	/**
+	 * 查询公告列表
+	 */
+	const getList = async () => {
+		loading.value = true;
+		await listNotice(queryParams.value).then((response: any) => {
+			noticeList.value = response.rows;
+			total.value = parseInt(response.total);
+			loading.value = false;
+		});
+	};
+	/**
+	 * 公告状态字典翻译
+	 *
+	 * @param row
+	 * @returns
+	 */
+	const statusFormat = (row: any) => {
+		return proxy.selectDictLabel(statusOptions.value, row.status);
+	};
+	/**
+	 * 公告类型字典翻译
+	 *
+	 * @param row
+	 * @returns
+	 */
+	const typeFormat = (row: any) => {
+		return proxy.selectDictLabel(typeOptions.value, row.noticeType);
+	};
+
+    const cleanSelect = () => {
+        proxy.cleanTableSelection(pageTable);
+    };
+
+	/**
+	 * 取消按钮
+	 */
+	const cancel = () => {
+		open.value = false;
+		reset();
+        pageTable.value?.clearSelection();
+	};
+	/**
+	 * 表单重置
+	 */
+	const reset = () => {
+		form.value = {
+			noticeId: undefined,
+			noticeTitle: undefined,
+			noticeType: undefined,
+			noticeContent: undefined,
+			status: "0",
+		};
+		proxy.resetForm(formRef);
+	};
+	/**
+	 * 搜索按钮操作
+	 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getList();
+	};
+	/**
+	 * 重置按钮操作
+	 */
+	const resetQuery = () => {
+		queryParams.value.noticeType = "";
+		proxy.resetForm(queryFormRef);
+		handleQuery();
+	};
+	/**
+	 * 多选框选中数据
+	 *
+	 * @param selection
+	 */
+	const handleSelectionChange = (selection: any) => {
+		ids.value = selection.map((item: any) => item.noticeId);
+		single.value = selection.length != 1;
+		multiple.value = !selection.length;
+	};
+	/**
+	 * 新增操作
+	 */
+	const handleAdd = () => {
+		reset();
+		open.value = true;
+		title.value = "添加公告";
+	};
+	/** 修改按钮操作 */
+	const handleUpdate = async (row: any) => {
+		reset();
+		const noticeId = row.noticeId || ids.value;
+		await getNotice(noticeId).then((response) => {
+			form.value = response.data;
+			title.value = "修改公告";
+            proxy.setTableRowSelected(pageTable, row, true)
+            open.value = true;
+		});
+	};
+	/**
+	 * 提交
+	 */
+	const submitForm = async () => {
+		await formRef.value?.validate((valid) => {
+			if (valid) {
+				if (form.value.noticeId != undefined) {
+					updateNotice(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("修改成功");
+							open.value = false;
+							getList();
+						}
+					});
+				} else {
+					addNotice(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("新增成功");
+							open.value = false;
+							getList();
+						}
+					});
+				}
+			}
+		});
+	};
+	/** 删除按钮操作 */
+	const handleDelete = (row: any) => {
+		const noticeIds = row.noticeId || ids.value;
+        proxy.setTableRowSelected(pageTable, row, true)
+		// prettier-ignore
+		proxy.$modal.confirm('是否确认删除公告编号为"' + noticeIds + '"的数据项?', "警告")
+            .then(() =>{
+                return delNotice(noticeIds);
+            })
+            .then((response: any) => {
+                if (response.code === 200) {
+                    getList();
+                    proxy.$modal.msgSuccess("删除成功");
+                }
+            })
+            .catch(() => {
+                cleanSelect();
+                console.log("取消了删除");
+            });
+	};
+
+	onMounted(() => {
+		getList();
+		proxy.getDicts("sys_notice_status").then((response: { data: any }) => {
+			statusOptions.value = response.data;
+		});
+		proxy.getDicts("sys_notice_type").then((response: { data: any }) => {
+			typeOptions.value = response.data;
+		});
+	});
+
+	// prettier-ignore
+	return {
+        loading, single, multiple, showSearch, total, noticeList, title, open, statusOptions, typeOptions, queryParams, form, formRef, queryFormRef, 
+        rules, getList, statusFormat, typeFormat, cancel, handleQuery, resetQuery, handleSelectionChange, handleAdd, handleUpdate, submitForm, 
+        handleDelete, pageTable, cleanSelect, 
+    }
+};

+ 217 - 0
src/api/request/system/post/post.ts

@@ -0,0 +1,217 @@
+import { ref, getCurrentInstance, onMounted } from "vue";
+// prettier-ignore
+import { listPost, getPost, delPost, addPost, updatePost, exportPost } from "@/api/system/post";
+import { ElForm, ElTable } from "element-plus";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	// 遮罩层
+	const loading = ref<boolean>(true);
+	// 选中数组
+	const ids = ref<any>();
+	// 非单个禁用
+	const single = ref<boolean>(true);
+	// 非多个禁用
+	const multiple = ref<boolean>(true);
+	// 显示搜索条件
+	const showSearch = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 岗位表格数据
+	const postList = ref<any>();
+	// 弹出层标题
+	const title = ref<string>("");
+	// 是否显示弹出层
+	const open = ref<boolean>(false);
+	// 状态数据字典
+	const statusOptions = ref<any>();
+	// 查询参数
+	const queryParams = ref({
+		pageNum: 1,
+		pageSize: 10,
+		postCode: undefined,
+		postName: undefined,
+		status: undefined,
+	});
+	const dateRange = ref<any>();
+	// 表单参数
+	const form = ref<any>();
+	const formRef = ref<InstanceType<typeof ElForm>>();
+	const queryFormRef = ref<InstanceType<typeof ElForm>>();
+    const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	// 表单校验
+	const rules = ref({
+		postName: [
+			{
+				required: true,
+				message: "岗位名称不能为空",
+				trigger: "blur",
+			},
+		],
+		postCode: [
+			{
+				required: true,
+				message: "岗位编码不能为空",
+				trigger: "blur",
+			},
+		],
+		postSort: [
+			{
+				required: true,
+				message: "岗位顺序不能为空",
+				trigger: "blur",
+			},
+		],
+	});
+
+	/** 查询岗位列表 */
+	const getList = async () => {
+		loading.value = true;
+        // prettier-ignore
+		await listPost(proxy.addDateRange(queryParams.value, dateRange.value)
+		).then((response: any) => {
+			postList.value = response.rows;
+			total.value = parseInt(response.total);
+			loading.value = false;
+		});
+	};
+	// 岗位状态字典翻译
+	const statusFormat = (row: any) => {
+		return proxy.selectDictLabel(statusOptions.value, row.status);
+	};
+    const cleanSelect = () => {
+        pageTableRef.value?.clearSelection();
+    };
+	// 取消按钮
+	const cancel = () => {
+		reset();
+        cleanSelect();
+        open.value = false;
+	};
+	// 表单重置
+	const reset = () => {
+		form.value = {
+			postId: undefined,
+			postCode: undefined,
+			postName: undefined,
+			postSort: 0,
+			status: "0",
+			remark: undefined,
+		};
+		proxy.resetForm(formRef);
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getList();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		dateRange.value = [];
+		proxy.resetForm(queryFormRef);
+		handleQuery();
+	};
+	// 多选框选中数据
+	const handleSelectionChange = (selection: any) => {
+		ids.value = selection.map((item: any) => item.postId);
+		single.value = selection.length != 1;
+		multiple.value = !selection.length;
+	};
+	/** 新增按钮操作 */
+	const handleAdd = () => {
+		reset();
+		title.value = "添加岗位";
+        open.value = true;
+	};
+	/** 修改按钮操作 */
+	const handleUpdate = async (row: any) => {
+		reset();
+		const postId = row.postId || ids.value;
+		await getPost(postId).then((response: any) => {
+            response.data.postSort = parseInt(response.data.postSort);
+			form.value = response.data;
+			title.value = "修改岗位";
+            proxy.setTableRowSelected(pageTableRef, row, true);
+            open.value = true;
+		});
+	};
+	/** 提交按钮 */
+	const submitForm = async () => {
+		await formRef.value?.validate((valid) => {
+			if (valid) {
+				if (form.value.postId !== undefined) {
+					updatePost(form.value)
+						.then((response: any) => {
+							if (response.code === 200) {
+								proxy.$modal.msgSuccess("修改成功");
+							}
+						})
+						.finally(() => {
+							open.value = false;
+							getList();
+						});
+				} else {
+					addPost(form.value)
+						.then((response: any) => {
+							if (response.code === 200) {
+								proxy.$modal.msgSuccess("新增成功");
+							}
+						})
+						.finally(() => {
+							open.value = false;
+							getList();
+						});
+				}
+			}
+		});
+	};
+	/** 删除按钮操作 */
+	const handleDelete = async (row: any) => {
+		const postIds = row.postId || ids.value;
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		// prettier-ignore
+		await proxy.$modal.confirm('是否确认删除岗位编号为"' + postIds + '"的数据项?', "警告")
+			.then(() => {
+				return delPost(postIds);
+			})
+			.then((response: any) => {
+				if (response.code === 200) {
+					proxy.$modal.msgSuccess("删除成功");
+					getList();
+				}
+			})
+			.catch(() => {
+                cleanSelect();
+				console.log("取消了删除");
+			});
+	};
+	/** 导出按钮操作 */
+	const handleExport = async () => {
+		/* const queryParams = this.queryParams;
+                this.$confirm('是否确认导出所有岗位数据项?', "警告", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning"
+                }).then(function() {
+                return exportPost(queryParams);
+                }).then(response => {
+                this.download(response.msg);
+                }) */
+		// prettier-ignore
+		await proxy.download('/system/post/exportByStream', {...queryParams}, `岗位信息${new Date().getTime()}.xlsx`);
+	};
+
+	onMounted(() => {
+		getList();
+		proxy.getDicts("sys_normal_disable").then((response: { data: any }) => {
+			statusOptions.value = response.data;
+		});
+	});
+
+	// prettier-ignore
+	return {
+        loading, single, multiple, showSearch, total, postList, title, open, queryParams, queryFormRef, form, dateRange, formRef, rules, pageTableRef, 
+        statusOptions, getList, statusFormat, cancel, handleQuery, resetQuery, handleSelectionChange, handleAdd, handleUpdate, submitForm, 
+        handleDelete, handleExport, cleanSelect,
+    };
+};

+ 462 - 0
src/api/request/system/role/role.ts

@@ -0,0 +1,462 @@
+import { ElTable } from "element-plus";
+// prettier-ignore
+import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus } from "@/api/system/role";
+// prettier-ignore
+import { treeselect as menuTreeselect, roleMenuTreeSelect } from "@/api/system/menu";
+// prettier-ignore
+import { roleDeptTreeselect } from "@/api/system/dept";
+import { addDateRange } from "@/utils/ruoyi";
+import { ref, getCurrentInstance, nextTick } from "vue";
+import { getDicts } from "@/api/system/dict/data";
+import { ElForm, ElTree } from "element-plus";
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	const menuRef = ref<InstanceType<typeof ElTree>>();
+	const deptRef = ref<InstanceType<typeof ElTree>>();
+	const pageTable = ref<InstanceType<typeof ElTable>>();
+	// 遮罩层
+	const loading = ref<boolean>(true);
+	// 导出遮罩层
+	const exportLoading = ref<boolean>(false);
+	// 选中数组
+	const ids = ref<any>();
+	// 非单个禁用
+	const single = ref<boolean>(true);
+	// 非多个禁用
+	const multiple = ref<boolean>(true);
+	// 显示搜索条件
+	const showSearch = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 角色表格数据
+	const roleList = ref<any>();
+	// 弹出层标题
+	const title = ref<string>("");
+	// 是否显示弹出层
+	const open = ref<boolean>(false);
+	// 是否显示弹出层(数据权限)
+	const openDataScope = ref<boolean>(false);
+	const menuExpand = ref<any>();
+	const menuNodeAll = ref<any>(false);
+	const deptExpand = ref<any>();
+	const deptNodeAll = ref<any>(false);
+	// 日期范围
+	const dateRange = ref<any>();
+	// 状态数据字典
+	const statusOptions = ref<any>();
+	// 数据范围选项
+	const dataScopeOptions = [
+		{
+			value: "1",
+			label: "全部数据权限",
+		},
+		{
+			value: "2",
+			label: "自定数据权限",
+		},
+		{
+			value: "3",
+			label: "本部门数据权限",
+		},
+		{
+			value: "4",
+			label: "本部门及以下数据权限",
+		},
+		{
+			value: "5",
+			label: "仅本人数据权限",
+		},
+	];
+	// 菜单列表
+	const menuOptions = ref<any>();
+	// 部门列表
+	const deptOptions = ref<any>();
+	// 查询参数
+	const queryParams = ref({
+		pageNum: 1,
+		pageSize: 10,
+		roleName: undefined,
+		roleKey: undefined,
+		status: undefined,
+	});
+	// 表单参数
+	const form = ref<any>({});
+	const queryFormRef = ref<InstanceType<typeof ElForm>>();
+	const formRef = ref<InstanceType<typeof ElForm>>();
+	const defaultProps = {
+		children: "children",
+		label: "label",
+	};
+	// 表单校验
+	const rules = {
+		roleName: [
+			{
+				required: true,
+				message: "角色名称不能为空",
+				trigger: "blur",
+			},
+		],
+		roleKey: [
+			{
+				required: true,
+				message: "权限字符不能为空",
+				trigger: "blur",
+			},
+		],
+		roleSort: [
+			{
+				required: true,
+				message: "角色顺序不能为空",
+				trigger: "blur",
+			},
+		],
+	};
+
+	/** 查询角色列表 */
+	const getList = () => {
+        roleList.value = [];
+		loading.value = true;
+		listRole(proxy.addDateRange(queryParams.value, dateRange.value)).then(
+			(response: any) => {
+				roleList.value = response.rows;
+				total.value = parseInt(response.total);
+				loading.value = false;
+			}
+		);
+	};
+	/** 查询菜单树结构 */
+	const getMenuTreeselect = () => {
+		menuTreeselect().then((response: any) => {
+			if (response.code === 200) {
+				menuOptions.value = response.data;
+			}
+		});
+	};
+	/** 查询部门树结构 */
+	/* getDeptTreeselect() {
+                deptTreeselect().then(response => {
+                    if (response.code === 200) {
+                        this.deptOptions = response.data;
+                    }
+                });
+            }, */
+	// 所有菜单节点数据
+	const getMenuAllCheckedKeys = () => {
+		// 目前被选中的菜单节点
+		let checkedKeys = menuRef.value?.getCheckedKeys() as any;
+		// 半选中的菜单节点
+		let halfCheckedKeys = menuRef.value?.getHalfCheckedKeys();
+		checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
+		return checkedKeys;
+	};
+	// 所有部门节点数据
+	const getDeptAllCheckedKeys = () => {
+		// 目前被选中的部门节点
+		let checkedKeys = deptRef.value?.getCheckedKeys() as any;
+		// 半选中的部门节点
+		let halfCheckedKeys = deptRef.value?.getHalfCheckedKeys();
+		checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
+		return checkedKeys;
+	};
+	/** 根据角色ID查询菜单树结构 */
+	const getRoleMenuTreeselect = (roleId: string) => {
+		return roleMenuTreeSelect(roleId).then((response: any) => {
+			if (response.code === 200) {
+				menuOptions.value = response.data.menus;
+				return response;
+			}
+		});
+	};
+	/** 根据角色ID查询部门树结构 */
+	const getRoleDeptTreeselect = (roleId: string) => {
+		return roleDeptTreeselect(roleId).then((response: any) => {
+			if (response.code === 200) {
+				deptOptions.value = response.data.depts;
+				return response;
+			}
+		});
+	};
+	const cleanSelect = () => {
+		proxy.cleanTableSelection(pageTable);
+	};
+	// 角色状态修改
+	const handleStatusChange = async (row: any) => {
+		proxy.setTableRowSelected(pageTable, row, true);
+		let text = row.status === "0" ? "启用" : "停用";
+		// prettier-ignore
+		await proxy.$modal.confirm('确认要"' + text + '""' + row.roleName + '"角色吗?', "警告",
+				{
+					confirmButtonText: "确定",
+					cancelButtonText: "取消",
+					type: "warning",
+				}
+			)
+			.then(() => {
+				return changeRoleStatus(row.roleId, row.status);
+			})
+			.then((response: any) => {
+				if (response.code === 200) {
+                    proxy.$modal.msgSuccess(text + "成功");
+                }
+			})
+			.catch(() => {
+                cleanSelect();
+				row.status = row.status === "0" ? "1" : "0";
+				console.log("角色状态修改取消");
+			});
+	};
+	// 取消按钮
+	const cancel = () => {
+		open.value = false;
+		reset();
+		cleanSelect();
+	};
+	// 取消按钮(数据权限)
+	const cancelDataScope = () => {
+		openDataScope.value = false;
+		reset();
+		cleanSelect();
+	};
+	// 表单重置
+	const reset = () => {
+		if (menuRef.value != undefined) {
+			menuRef.value.setCheckedKeys([]);
+		}
+		menuExpand.value = false;
+		menuNodeAll.value = false;
+		deptExpand.value = true;
+		deptNodeAll.value = false;
+		form.value = {
+			roleId: undefined,
+			roleName: undefined,
+			roleKey: undefined,
+			roleSort: 0,
+			status: "0",
+			menuIds: [],
+			deptIds: [],
+			menuCheckStrictly: true,
+			deptCheckStrictly: true,
+			remark: undefined,
+		};
+		proxy.resetForm(formRef);
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getList();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		dateRange.value = [];
+		proxy.resetForm(queryFormRef);
+		handleQuery();
+	};
+    const checkSelected  = (row: any) => {
+        // 设置不可选中
+        return row.roleId !== "1";
+    };
+	// 多选框选中数据
+	const handleSelectionChange = (selection: any) => {
+		ids.value = selection.map((item: { roleId: any }) => item.roleId);
+		single.value = selection.length != 1;
+		multiple.value = !selection.length;
+	};
+	// 树权限(展开/折叠)
+	const handleCheckedTreeExpand = (value: any, type: string) => {
+		if (type === "menu") {
+			let treeList = menuOptions.value;
+			for (let i = 0; i < treeList.length; i++) {
+				// prettier-ignore
+				proxy.$refs.menuRef.store.nodesMap[treeList[i].id].expanded = value;
+			}
+		} else if (type === "dept") {
+			let treeList = deptOptions.value;
+			for (let i = 0; i < treeList.length; i++) {
+				// prettier-ignore
+				proxy.$refs.deptRef.store.nodesMap[treeList[i].id].expanded = value;
+			}
+		}
+	};
+	// 树权限(全选/全不选)
+	const handleCheckedTreeNodeAll = (value: any, type: string) => {
+		if (type === "menu") {
+			menuRef.value?.setCheckedNodes(value ? menuOptions.value : []);
+		} else if (type === "dept") {
+			deptRef.value?.setCheckedNodes(value ? deptOptions.value : []);
+		}
+	};
+	// 树权限(父子联动)
+	const handleCheckedTreeConnect = (value: any, type: string) => {
+		if (type == "menu") {
+			form.value.menuCheckStrictly = value ? true : false;
+		} else if (type == "dept") {
+			form.value.deptCheckStrictly = value ? true : false;
+		}
+	};
+	/** 新增按钮操作 */
+	const handleAdd = () => {
+		reset();
+		getMenuTreeselect();
+		open.value = true;
+		title.value = "添加角色";
+	};
+	/** 修改按钮操作 */
+	const handleUpdate = (row: any) => {
+		proxy.setTableRowSelected(pageTable, row, true);
+		reset();
+		const roleId = row.roleId || ids.value[0];
+        if (!roleId) {
+            return;
+        }
+		getRole(roleId).then((response: any) => {
+			if (response.code === 200) {
+				// 转换下避免出现警告
+				response.data.roleSort = parseInt(response.data.roleSort);
+				form.value = response.data;
+				open.value = true;
+				nextTick(() => {
+					getRoleMenuTreeselect(roleId).then(
+						(res: { code: number; data: { checkedKeys: any } }) => {
+							if (res.code === 200) {
+								const checkedKeys = res.data.checkedKeys;
+								checkedKeys.forEach((v: any) => {
+									nextTick(() => {
+										// prettier-ignore
+										menuRef.value?.setChecked(v, true, false);
+									});
+								});
+							}
+						}
+					);
+				});
+				title.value = "修改角色";
+			}
+		});
+	};
+	/** 选择角色权限范围触发 */
+	const dataScopeSelectChange = (value: string) => {
+		if (value !== "2") {
+			deptRef.value?.setCheckedKeys([]);
+		}
+	};
+	/** 分配数据权限操作 */
+	const handleDataScope = (row: any) => {
+		proxy.setTableRowSelected(pageTable, row, true);
+		reset();
+		getRole(row.roleId).then((response: any) => {
+			if (response.code === 200) {
+				openDataScope.value = true;
+				// 转换下避免出现警告
+				response.data.roleSort = parseInt(response.data.roleSort);
+				form.value = response.data;
+				setTimeout(() => {
+					nextTick(() => {
+						getRoleDeptTreeselect(row.roleId).then(
+							(res: { data: { checkedKeys: any } }) => {
+								// prettier-ignore
+								deptRef.value?.setCheckedKeys(res.data.checkedKeys);
+							}
+						);
+					});
+				}, 100);
+				title.value = "分配数据权限";
+			}
+		});
+	};
+	/** 提交按钮 */
+	const submitForm = () => {
+		formRef.value?.validate((valid: boolean) => {
+			if (valid) {
+				if (form.value.roleId !== undefined) {
+					form.value.menuIds = getMenuAllCheckedKeys();
+					updateRole(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("修改成功");
+							open.value = false;
+							getList();
+						}
+					});
+				} else {
+					form.value.menuIds = getMenuAllCheckedKeys();
+					addRole(form.value).then((response: any) => {
+						if (response.code === 200) {
+							proxy.$modal.msgSuccess("新增成功");
+							open.value = false;
+							getList();
+						}
+					});
+				}
+			}
+		});
+	};
+	/** 提交按钮(数据权限) */
+	const submitDataScope = () => {
+		if (form.value.roleId !== undefined) {
+			form.value.deptIds = getDeptAllCheckedKeys();
+			dataScope(form.value).then((response: any) => {
+				if (response.code === 200) {
+					proxy.$modal.msgSuccess("修改成功");
+					openDataScope.value = false;
+					getList();
+				}
+			});
+		}
+	};
+	/** 删除按钮操作 */
+	const handleDelete = (row: any) => {
+		if (!row || !ids.value) {
+			return;
+		}
+		proxy.setTableRowSelected(pageTable, row, true);
+		const roleIds = row.roleId || ids.value;
+        if (!roleIds) {
+            return;
+        }
+		// prettier-ignore
+		proxy.$modal.confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?',)
+                .then(() => {
+                    return delRole(roleIds);
+                })
+                .then((response: { code: number; }) => {
+                    if (response.code === 200) {
+                        getList();
+                        proxy.$modal.msgSuccess("删除成功");
+                    }
+                }).catch(() => {
+                    cleanSelect();
+                    console.log("删除操作取消");
+                });
+	};
+	/** 导出按钮操作 */
+	const handleExport = () => {
+		if (total.value > 10000) {
+			// prettier-ignore
+			proxy.$modal.confirm("是否确认导出所有角色数据项?", "警告", {})
+				.then(() => {
+					// prettier-ignore
+					proxy.download('/system/role/exportByStream', {...queryParams}, `角色信息导出${new Date().getTime()}.xlsx`);
+				})
+				.catch(() => {
+					console.log("导出操作取消");
+				});
+		} else {
+			// prettier-ignore
+			proxy.download('/system/role/exportByStream', {...queryParams}, `角色信息导出${new Date().getTime()}.xlsx`);
+		}
+	};
+
+    getList();
+    getDicts("sys_normal_disable").then((response: any) => {
+        statusOptions.value = response.data;
+    });
+	
+	// prettier-ignore
+	return {
+        menuRef, loading, exportLoading, deptRef, single, multiple, showSearch, total, roleList, title, open, openDataScope, menuExpand, menuNodeAll,
+        deptExpand, deptNodeAll, dateRange, statusOptions, dataScopeOptions, menuOptions, deptOptions, queryParams, form, defaultProps, rules, formRef,
+        queryFormRef, getList, handleStatusChange, handleQuery, resetQuery, handleSelectionChange, handleCheckedTreeExpand,  
+        handleCheckedTreeNodeAll, handleCheckedTreeConnect, handleAdd, handleUpdate, dataScopeSelectChange, handleDataScope, submitForm, cleanSelect,
+        submitDataScope, handleDelete, handleExport, pageTable, checkSelected, 
+    }
+};

+ 113 - 0
src/api/request/system/tool/gen/editTable.ts

@@ -0,0 +1,113 @@
+import { getGenTable, updateGenTable } from "@/api/tool/gen";
+// prettier-ignore
+import { optionselect as getDictOptionselect } from "@/api/system/dict/type";
+import { listMenu as getMenuTreeselect } from "@/api/system/menu";
+import { ref, getCurrentInstance, onMounted, } from "vue";
+
+export default () => {
+	// 选中选项卡的 name
+	const activeName = "cloum";
+	// 表格的高度
+	const tableHeight = document.documentElement.scrollHeight - 245 + "px";
+	// 表信息
+	const tables = ref<any>([]);
+	// 表列信息
+	const cloumns = ref<any>([]);
+	// 字典信息
+	const dictOptions = ref<any>([]);
+	// 菜单信息
+	const menus = ref<any>([]);
+	// 表详细信息
+	const info = ref<any>({});
+
+	const { proxy } = getCurrentInstance() as any;
+
+    const isRouter = ref<boolean>(false);
+
+	/** 提交按钮 */
+	const submitForm = () => {
+		const basicForm = proxy.$refs.basicInfo.$refs.basicInfoForm;
+		const genForm = proxy.$refs.genInfo.$refs.genInfoForm;
+		Promise.all([basicForm, genForm].map(getFormPromise)).then(
+			(res: any) => {
+				const validateResult = res.every((item: any) => !!item);
+				if (validateResult) {
+					const genTable = Object.assign({}, info.value);
+					genTable.columns = cloumns.value;
+					genTable.params = {
+						treeCode: genTable.treeCode,
+						treeName: genTable.treeName,
+						treeParentCode: genTable.treeParentCode,
+						parentMenuId: genTable.parentMenuId,
+					};
+					updateGenTable(genTable).then((res: any) => {
+						proxy.$modal.msgSuccess(res.msg);
+						if (res.code === 200) {
+							close();
+						}
+						proxy.$attrs.onOk();
+					});
+				} else {
+					// prettier-ignore
+					proxy.$modal.msgError("表单校验未通过,请重新检查提交内容");
+				}
+			}
+		);
+	};
+	const getFormPromise = (form: any) => {
+		return new Promise((resolve) => {
+			form.validate((res: any) => {
+				resolve(res);
+			});
+		});
+	};
+	/** 关闭按钮 */
+	const close = () => {
+		//this.$store.dispatch("tagsView/delView", this.$route);
+		// useTagsViewStore().delView(this.$route);
+		proxy.$router.push({ path: "/tool/gen"} );
+	};
+
+
+    const initTabsData = async (tableId: string) => {
+        console.log("传过来的表ID", tableId);
+        if (!tableId) {
+            console.log("参数异常");
+            return;
+        }
+        // 获取表详细信息
+        await getGenTable(tableId).then((response: any) => {
+            if (response.code === 200) {
+                const data = response.data;
+                cloumns.value = data.rows;
+                info.value = data.info;
+                tables.value = data.tables;
+            }
+        });
+        /** 查询字典下拉列表 */
+        await getDictOptionselect().then((response: any) => {
+            if (response.code === 200) {
+                dictOptions.value = response.data;
+            }
+        });
+        /** 查询菜单下拉列表 */
+        await getMenuTreeselect().then((response: any) => {
+            if (response.code === 200) {
+                menus.value = proxy.handleTree(response.data, "menuId");
+            }
+        });
+    };
+
+    onMounted(() => {
+        const tableId = proxy.$route.params && proxy.$route.params.tableId;
+        if (tableId) {
+            initTabsData(tableId);
+            isRouter.value = true;
+        }
+    });
+
+	// prettier-ignore
+	return {
+        activeName, tableHeight, tables, cloumns, dictOptions, menus, info, submitForm, close, initTabsData, isRouter
+    }
+};

+ 103 - 0
src/api/request/system/tool/gen/importTable.ts

@@ -0,0 +1,103 @@
+import { ElForm, ElTable } from "element-plus";
+import { ref, reactive, getCurrentInstance, defineEmits, defineExpose } from "vue";
+import { listDbTable, importTable } from "@/api/tool/gen";
+
+export default () => {
+	// 避免出现 Vue3警告:[Vue warn]: Extraneous non-emits event listeners (changeParentProps) were passed to component
+	// https://blog.csdn.net/weixin_47339511/article/details/118530865
+
+	const queryForm = ref<InstanceType<typeof ElForm>>();
+	// 表格
+	const tableRef = ref<InstanceType<typeof ElTable>>();
+	const visible = ref<boolean>(false);
+	// 选中数组值
+	const tables = ref<any>([]);
+	// 总条数
+	const total = ref<number>(0);
+	// 表数据
+	const dbTableList = ref<any>([]);
+	// 确定按钮可用
+	const okBtnEnabled = ref<boolean>(true);
+	// 查询参数
+	const queryParams = reactive<any>({
+		pageNum: 1,
+		pageSize: 10,
+		tableName: undefined,
+		tableComment: undefined,
+	});
+	const emit = defineEmits(["ok"]);
+	const { proxy } = getCurrentInstance() as any;
+	// 显示弹框
+	const show = () => {
+		visible.value = true;
+		getList();
+	};
+	const clickRow = (row: any) => {
+		tableRef.value?.toggleRowSelection(row, true);
+	};
+	// 多选框选中数据
+	const handleSelectionChange = (selection: any) => {
+		if (selection == null) {
+			return;
+		}
+
+		tables.value = selection.map(
+			(item: { tableName: any }) => item.tableName
+		);
+		if (tables.value && tables.value.length > 0) {
+			okBtnEnabled.value = false;
+		} else {
+			okBtnEnabled.value = true;
+		}
+	};
+	// 查询表数据
+	const getList = () => {
+		listDbTable(queryParams).then((res: any) => {
+			if (res.code === 200) {
+				dbTableList.value = res.rows;
+				total.value = parseInt(res.total);
+			}
+		});
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.pageNum = 1;
+		getList();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		proxy.resetForm(queryForm);
+		//queryForm.value?.resetFields();
+		handleQuery();
+	};
+
+	/** 导入按钮操作 */
+	const handleImportTable = async () => {
+		const tabs = tables.value.join(",");
+		if (tabs) {
+			await importTable({ tables: tabs }).then((res: any) => {
+				if (res.code === 200) {
+					proxy.$modal.msgSuccess(res.msg);
+					tables.value = [];
+					emit("ok");
+					visible.value = false;
+				}
+			});
+		} else {
+			console.log("tabls", tabs.length);
+			// prettier-ignore
+			proxy.$message.error(`请勾选需要导入的表后再提交!`);
+			return false;
+		}
+	};
+
+	defineExpose({
+		show,
+	});
+
+	// prettier-ignore
+	return {
+        queryForm, tableRef, visible, total, dbTableList, okBtnEnabled, queryParams, clickRow, handleSelectionChange, handleQuery, resetQuery,
+        getList, handleImportTable,
+    }
+};

+ 272 - 0
src/api/request/system/tool/gen/index.ts

@@ -0,0 +1,272 @@
+import router from "@/router";
+import { useRoute } from "vue-router";
+import { ElDialog, ElForm, ElTable } from "element-plus";
+// prettier-ignore
+import { getCurrentInstance, ref, reactive, toRefs, onActivated, watch, nextTick, } from "vue";
+// prettier-ignore
+import { listTable, previewTable, delTable, genCode, synchDb, updateStausOrVersion, } from "@/api/tool/gen";
+
+export default () => {
+	const route = useRoute();
+	const { proxy } = getCurrentInstance() as any;
+	const queryRef = ref<InstanceType<typeof ElForm>>();
+	const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	const loading = ref<boolean>(true);
+	const showSearch = ref<boolean>(true);
+	const ids = ref<any>();
+	const genCodeEnabled = ref<boolean>(true);
+	const single = ref<boolean>(true);
+	const multiple = ref<boolean>(true);
+	const total = ref<number>(0);
+	const tableList = ref<any>();
+	const tableNames = ref<any>();
+	const dateRange = ref<any>();
+	const uniqueId = ref<any>();
+	const data = reactive({
+		queryParams: {
+			pageNum: 1,
+			pageSize: 10,
+			tableName: undefined,
+			tableComment: undefined,
+		},
+		preview: {
+			open: false,
+			title: "代码预览",
+			data: {},
+			activeName: "domain.java",
+		},
+	});
+
+	const { queryParams, preview } = toRefs(data) as any;
+    // 编辑table
+    const editVisable = ref<boolean>(false);
+    const tableId = ref<string>("");
+    const editTableRef = ref<any>();
+    const editTypeTitle = ref<string>("弹窗模式");
+
+	onActivated(() => {
+		const time = route.query.t;
+		if (time != null && time != uniqueId.value) {
+			uniqueId.value = time;
+			queryParams.value.pageNum = Number(route.query.pageNum);
+			dateRange.value = [];
+			proxy.resetForm(queryRef);
+			getPageList();
+		}
+	});
+
+	const cleanSelect = () => {
+		pageTableRef.value?.clearSelection();
+	};
+
+    // prettier-ignore
+	watch(() => router.currentRoute.value.path,(newValue, oldValue) => {
+			console.log("watch", newValue);
+            // 路由变化清空选中
+            cleanSelect();
+		},
+		{ immediate: true }
+	);
+
+	/** 查询表集合 */
+	const getPageList = async () => {
+		loading.value = true;
+		// prettier-ignore
+		const data = proxy.addDateRange(queryParams.value, dateRange.value);
+		console.log("转换后的参数---", data);
+		await listTable(data).then((response: any) => {
+			tableList.value = response.rows;
+			total.value = parseInt(response.total);
+		}).finally(() => {
+            loading.value = false;
+        });
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		queryParams.value.pageNum = 1;
+		getPageList();
+	};
+	/** 生成代码操作 */
+	// prettier-ignore
+	const handleGenTable = async (row: any) => {
+		const tbNames = row.tableName || tableNames.value;
+		if (tbNames == "") {
+			proxy.$modal.msgError("请选择要生成的数据");
+			return;
+		} else {
+            if (row.genType === "1") {
+                await genCode(row.tableName).then((response: any) => {
+                    if (response.code === 200) {
+                        proxy.$modal.msgSuccess("成功生成到自定义路径:" + row.genPath);
+                    }
+                });
+            } else {
+                // prettier-ignore
+                const zipName = "ruoyi" + new Date().getTime();
+                await proxy.$download.zip("/tool/gen/batchGenCode?tables=" + tbNames, zipName);
+                proxy.$modal.msgSuccess("成功生成代码:" + zipName + ".zip,包括的表【" + tbNames + "】");
+                console.log("生成代码文件%s.zip成功", zipName);
+            }
+        }
+	};
+	/** 同步数据库操作 */
+	const handleSynchDb = async (row: { tableName: any }) => {
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		const tableName = row.tableName;
+		// prettier-ignore
+		await proxy.$modal.confirm('确认要强制同步"' + tableName + '"表结构吗?')
+			.then(() => {
+				return synchDb(tableName);
+			})
+			.then((response: any) => {
+				if (response.code === 200) {
+					proxy.$modal.msgSuccess("同步成功");
+				}
+			})
+			.catch(() => {
+                cleanSelect();
+				console.log("取消了同步");
+			});
+	};
+	/** 打开导入表弹窗 */
+	const openImportTable = () => {
+		proxy.$refs["importRef"].show();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		dateRange.value = [];
+		proxy.resetForm(queryRef);
+		handleQuery();
+	};
+	/** 预览按钮 */
+	const handlePreview = async (row: { tableId: string }) => {
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		await previewTable(row.tableId).then((response: any) => {
+			if (response.code === 200) {
+				preview.value.data = response.data;
+				preview.value.activeName = "domain.java";
+				preview.value.open = true;
+			}
+		});
+	};
+	/** 复制代码成功 */
+	const copyTextSuccess = () => {
+		proxy.$modal.msgSuccess("复制成功");
+	};
+	// 多选框选中数据
+	const handleSelectionChange = (selection: any) => {
+		ids.value = selection.map((item: { tableId: any }) => item.tableId);
+		tableNames.value = selection.map(
+			(item: { tableName: any }) => item.tableName
+		);
+		single.value = selection.length != 1;
+		multiple.value = !selection.length;
+		genCodeEnabled.value = !selection.length;
+        tableId.value = ids.value[0];
+	};
+
+	/** 修改按钮操作 */
+	const handleEditTable = (row?: any) => {
+        tableId.value = row.tableId || ids.value[0];
+        if (row) {
+            proxy.setTableRowSelected(pageTableRef, row, true);
+        }
+        if (editTypeTitle.value === "弹窗模式") {
+            nextTick(() => {
+                editTableRef.value.initTabsData(tableId.value);
+            });
+            editVisable.value = true;
+        } else if (editTypeTitle.value === "页面模式") {
+            // prettier-ignore
+            router.push({path: "/tool/gen-edit/index/" + tableId.value, query: { pageNum: queryParams.value.pageNum }});
+        }
+	};
+
+	/** 删除按钮操作 */
+	const handleDelete = async (row: any) => {
+		const tableIds = row.tableId || ids.value;
+        if (row) {
+            proxy.setTableRowSelected(pageTableRef, row, true);
+        }
+		// prettier-ignore
+		await proxy.$modal.confirm('是否确认删除表编号为"' + tableIds + '"的数据项?')
+			.then(() => {
+				return delTable(tableIds);
+			})
+			.then((response: any) => {
+				if (response.code === 200) {
+					proxy.$modal.msgSuccess("删除成功");
+					getPageList();
+				}
+			})
+			.catch(() => {
+                cleanSelect();
+				console.log("取消了删除");
+			});
+	};
+
+	/**
+	 * 修改注释状态或版本信息
+	 *
+	 * @param val 选中的值
+	 * @param row 行信息
+	 * @param e   类型
+	 */
+	const changeStatus = async (val: any, row: any, e: string) => {
+		if (e === "v") {
+			await updateStausOrVersion(e, row.tableId, val).then(
+				(response: any) => {
+					if (response.code === 200) {
+						proxy.$modal.msgSuccess(response.msg);
+						getPageList();
+					}
+				}
+			);
+		} else {
+			const text = val === 0 ? "启用" : "停用";
+			const info = e === "s" ? "swagger" : "excel";
+			// prettier-ignore
+			await proxy.$modal.confirm("确认要" + text + row.tableName + '"的' + info + "注释吗?", "警告")
+                .then(() => {
+                    return updateStausOrVersion(e, row.tableId, val);
+                })
+                .then((response: any) => {
+                    if (response.code === 200) {
+                        proxy.$modal.msgSuccess(response.msg);
+                        getPageList();
+                    }
+                })
+                .catch(() => {
+                    e === "s" ? row.swagger = row.swagger === 1 ? 0 : 1 : row.excelExport = row.excelExport === 1 ? 0 : 1;
+                });
+		}
+	};
+
+    const viewCodeClose = () => {
+        preview.value.open = false;
+        cleanSelect();
+    };
+
+    const submitChildForm  = () => {
+        editTableRef?.value.submitForm();
+        editVisable.value = false;
+    };
+
+    const switchEdit = () => {
+        if (editTypeTitle.value === "弹窗模式") {
+            editTypeTitle.value = "页面模式";
+        } else {
+            editTypeTitle.value = "弹窗模式";
+        }
+    };
+
+	getPageList();
+
+	// prettier-ignore
+	return {
+        loading, queryRef, pageTableRef, showSearch, genCodeEnabled, single, multiple, total, tableList, dateRange, tableNames, uniqueId, data,
+        queryParams, preview, getPageList, handleQuery, resetQuery, openImportTable, copyTextSuccess, handlePreview, handleSelectionChange,
+        handleDelete, handleEditTable, handleGenTable, handleSynchDb, changeStatus, cleanSelect, viewCodeClose, editVisable, tableId, editTableRef,
+        submitChildForm, switchEdit, editTypeTitle
+    }
+};

+ 464 - 0
src/api/request/system/user/index.ts

@@ -0,0 +1,464 @@
+import { getlist } from '@/api/system/logininfor';
+// prettier-ignore
+import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus} from "@/api/system/user";
+import { getToken } from "@/utils/auth";
+import { treeselect } from "@/api/system/dept";
+import { ref, getCurrentInstance, watch, toRefs, nextTick, } from "vue";
+import { ElForm, ElTable, ElUpload, FormItemRule } from "element-plus";
+const baseURL = import.meta.env.VITE_APP_BASE_API;
+
+export default () => {
+	const { proxy } = getCurrentInstance() as any;
+	// 遮罩层
+	const loading = ref<boolean>(true);
+	// 选中数组
+	let ids = ref<any>([]);
+
+	const deptTreeRef = ref<any>();
+	const queryFormRef = ref<InstanceType<typeof ElForm>>();
+	const formRef = ref<InstanceType<typeof ElForm>>();
+  const pageTableRef = ref<InstanceType<typeof ElTable>>();
+	// prettier-ignore
+	const { sys_normal_disable, sys_user_sex } = proxy.useDict("sys_normal_disable", "sys_user_sex");
+
+	// 非单个禁用
+	const single = ref<boolean>(true);
+	// 非多个禁用
+	const multiple = ref<boolean>(true);
+	// 显示搜索条件
+	const showSearch = ref<boolean>(true);
+	// 总条数
+	const total = ref<number>(0);
+	// 用户表格数据
+	const userList = ref<any>();
+	// 弹出层标题
+	const title = ref<string>("");
+	// 部门树选项
+	const deptOptions = ref<any>();
+	// 是否显示弹出层
+	const open = ref<boolean>(false);
+	// 部门名称
+	const deptName = ref<any>(undefined);
+	// 默认密码
+	const initPassword = ref<any>(undefined);
+	// 日期范围
+	const dateRange = ref<string>("");
+	// 岗位选项
+	const postOptions = ref<any>();
+	// 角色选项
+	const roleOptions = ref<any>();
+	// 表单参数
+	const form = ref<any>();
+	const defaultProps = {
+		children: "children",
+		label: "label",
+	};
+    const uploadRef = ref<InstanceType<typeof ElUpload>>();
+	// 用户导入参数
+	const upload = ref<any>({
+		// 是否显示弹出层(用户导入)
+		open: false,
+		// 弹出层标题(用户导入)
+		title: "",
+		// 是否禁用上传
+		isUploading: false,
+		// 是否更新已经存在的用户数据
+		updateSupport: 0,
+		// 设置上传的请求头部
+		headers: { Authorization: "Bearer " + getToken() },
+		// 上传的地址
+		url: baseURL + "/system/user/importData",
+	});
+	// 查询参数
+	const queryParams = ref<any>({
+		pageNum: 1,
+		pageSize: 10,
+		userName: undefined,
+		phonenumber: undefined,
+		status: undefined,
+		deptId: undefined,
+		sex: undefined,
+	});
+	// 列信息
+	const columns = [
+		{ key: 0, label: `用户编号`, visible: true },
+		{ key: 1, label: `用户名称`, visible: true },
+		{ key: 2, label: `用户昵称`, visible: true },
+		{ key: 3, label: `部门`, visible: true },
+		{ key: 4, label: `手机号码`, visible: true },
+		{ key: 5, label: `状态`, visible: true },
+		{ key: 6, label: `创建时间`, visible: true },
+	];
+	// 表单校验
+	const rules = ref<any>({
+		userName: [
+			{
+				required: true,
+				message: "用户名称不能为空",
+				trigger: "blur",
+			},
+		],
+		nickName: [
+			{
+				required: true,
+				message: "用户昵称不能为空",
+				trigger: "blur",
+			},
+		],
+		password: [
+			{
+				required: true,
+				message: "用户密码不能为空",
+				trigger: "blur",
+			},
+		],
+		email: [
+			{
+				type: "email",
+				message: "'请输入正确的邮箱地址",
+				trigger: ["blur", "change"],
+			},
+		],
+		phonenumber: [
+			{
+				pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
+				message: "请输入正确的手机号码",
+				trigger: "blur",
+			},
+		],
+	});
+
+	//const { rules } = toRefs(validate) as any;
+
+	watch(deptName, (val) => {
+		// 根据名称筛选部门树
+		proxy.$refs["deptTreeRef"].filter(val);
+	});
+
+	/** 查询用户列表 */
+	const getPageList = () => {
+        // TODO 查询之前先清空列表(不清空可能会因为数据缓存影响)
+        userList.value = [];
+		loading.value = true;
+		listUser(proxy.addDateRange(queryParams.value, dateRange.value)).then(
+			(response: any) => {
+				userList.value = response.rows;
+				total.value = parseInt(response.total);
+				loading.value = false;
+			}
+		);
+	};
+	/** 查询部门下拉树结构 */
+	const getTreeselect = () => {
+		treeselect().then((response: any) => {
+			deptOptions.value = response.data;
+		});
+	};
+	// 筛选节点
+	const filterNode = (value: any, data: any) => {
+		if (!value) return true;
+		return data.label.indexOf(value) !== -1;
+	};
+	// 节点单击事件
+	const handleNodeClick = (data: { id: any }) => {
+		queryParams.value.deptId = data.id;
+		getPageList();
+	};
+
+    const updateUserStatus = async (userId: string, val: string) => {
+        const text = val === "0" ? "启用" : "停用";
+        await changeUserStatus(userId, val).then((response: any) => {
+            if (response.code === 200) {
+                proxy.$modal.msgSuccess(text + "成功");
+                getPageList();
+            }
+        });
+    }
+
+	/**
+     * 用户状态修改
+     * 
+     * @param val 当前选中的值
+     * @param row 当前的行数据
+     */
+	const handleStatusChange = async (val: any, row: any) => {
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		const text = val === "0" ? "启用" : "停用";
+		// prettier-ignore
+		await proxy.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?',"警告")
+            .then(() => {
+                updateUserStatus(row.userId, val);
+            })
+            .catch(() => {
+                proxy.setTableRowSelected(pageTableRef, row, false);
+                row.status = row.status === "0" ? "1" : "0";
+                return;
+            });
+        //updateUserStatus(row.userId, val);   
+	};
+	// 取消按钮
+	const cancel = () => {
+		open.value = false;
+		reset();
+	};
+	// 表单重置
+	const reset = () => {
+		form.value = {
+			userId: undefined,
+			deptId: undefined,
+			userName: undefined,
+			nickName: undefined,
+			password: undefined,
+			phonenumber: undefined,
+			email: undefined,
+			sex: undefined,
+			status: "0",
+			remark: undefined,
+			postIds: [],
+			roleIds: [],
+		};
+		proxy.resetForm(formRef);
+	};
+	/** 搜索按钮操作 */
+	const handleQuery = () => {
+		total.value = 0;
+		queryParams.value.pageNum = 1;
+		getPageList();
+	};
+	/** 重置按钮操作 */
+	const resetQuery = () => {
+		//proxy.resetForm("queryFormRef");
+		//proxy.$refs.queryFormRef.resetFields();
+		// 表单重置并且移除校验结果(el-form-item必须有prop与表单里文本框v-model对应)
+		queryFormRef.value?.resetFields();
+		dateRange.value = "";
+		total.value = 0;
+		handleQuery();
+	};
+
+    const statusChange = (val: any) => {
+        console.log("group选中的值", val);
+    };
+	// 多选框选中数据
+	const handleSelectionChange = (selection: any) => {
+		ids.value = selection.map((item: { userId: any }) => item.userId);
+		single.value = selection.length != 1;
+		multiple.value = !selection.length;
+	};
+
+	const getUserBaseInfo = (dialogTitle: string, userId?: any) => {
+		if (userId) {
+			getUser(userId).then((response: any) => {
+				if (response.code === 200) {
+					const data = response.data;
+                    form.value = response.data.data;
+					postOptions.value = data.posts;
+					roleOptions.value = data.roles;
+                    form.value.postIds = data.postIds;
+				    form.value.roleIds = data.roleIds;
+                    /* form.value = {
+                        userId: formData.userId,
+                        userName: formData.userName,
+                        nickName: formData.nickName,
+                        deptId: formData.deptId,
+                        phonenumber: formData.phonenumber,
+                        email: formData.email,
+                        sex: formData.sex,
+                        status: formData.status,
+                        postIds: data.postIds,
+                        roleIds: data.roleIds,
+                        password: ""
+                    } */
+                    title.value = dialogTitle;
+					open.value = true;
+				}
+			});
+		} else {
+			getUser(null).then((response: any) => {
+				if (response.code === 200) {
+					const data = response.data;
+					postOptions.value = data.posts;
+					roleOptions.value = data.roles;
+					title.value = dialogTitle;
+					open.value = true;
+				}
+			});
+		}
+	};
+
+	/** 新增按钮操作 */
+	const handleAdd = () => {
+		reset();
+		getTreeselect();
+	
+		getUserBaseInfo("添加用户", null);
+	};
+	/** 修改按钮操作 */
+	const handleUpdate = (row: any) => {
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		reset();
+		getTreeselect();
+		const userId = row.userId || ids.value[0];
+		getUserBaseInfo("修改用户", userId);
+	};
+	/** 重置密码按钮操作 */
+	const handleResetPwd = async (row: { userName: string; userId: any }) => {
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		// prettier-ignore
+		await proxy.$modal.prompt('请输入"' + row.userName + '"的新密码', "提示")
+            .then(({ value }: any)  => {
+                resetUserPwd(row.userId, value).then((response: any) => {
+                    if (response.code === 200) {
+                        getPageList();
+                        proxy.setTableRowSelected(pageTableRef, row, false);
+                        proxy.$modal.msgSuccess("修改成功,新密码是:" + value);
+                    }
+                });
+            })
+            .catch(() => {
+                proxy.setTableRowSelected(pageTableRef, row, false);
+                console.log("密码重置取消");
+            });
+	};
+	/** 提交按钮 */
+	const submitForm = () => {
+		formRef.value?.validate((valid: boolean) => {
+			if (valid) {
+				if (form.value.userId) {
+					updateUser(form.value).then((response: any) => {
+						if (response.code === 200) {
+                            proxy.$modal.msgSuccess("修改成功");
+                            getPageList();
+                            open.value = false;
+                        }
+					});
+				} else {
+					addUser(form.value).then((response: any) => {
+						if (response.code === 200) {
+                            proxy.$modal.msgSuccess("新增成功");
+                        }
+					}).finally(() => {
+                        getPageList();
+                        open.value = false;
+                    });
+				}
+			}
+		});
+	};
+    const cleanSelect = () => {
+        proxy.cleanTableSelection(pageTableRef);
+    };
+	/** 删除按钮操作 */
+	const handleDelete = (row: any) => {
+		const userIds = row.userId || ids;
+		let isAdmin = false;
+		if (userIds instanceof Array) {
+			userIds.forEach((item) => {
+				if (item === "1") {
+					isAdmin = true;
+					return;
+				}
+			});
+		}
+
+		if (isAdmin) {
+			proxy.$modal.msgError("超级管理员不允许删除");
+			return;
+		}
+
+		if (userIds === "1") {
+			proxy.$modal.msgError("超级管理员不允许删除");
+			return;
+		}
+        proxy.setTableRowSelected(pageTableRef, row, true);
+		// prettier-ignore
+		proxy.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?', "警告")
+            .then(() => {
+                return delUser(userIds);
+            })
+            .then((response: any) => {
+                if (response.code === 200) {
+                    getPageList();
+                    proxy.$modal.msgSuccess("删除成功");
+                }
+            }).catch(() => {
+                cleanSelect();
+                console.log("取消了删除");
+            });
+	};
+	/** 导出按钮操作 */
+	const handleExport = () => {
+		proxy.download(
+			"/system/user/exportByStream",
+			{ ...queryParams.value },
+			`用户数据${new Date().getTime()}.xlsx`
+		);
+	};
+	/** 导入按钮操作 */
+	const handleImport = () => {
+		upload.value.title = "用户导入";
+		upload.value.open = true;
+	};
+    /**
+     * 清除上传控件选中文件
+     */
+     const cleanUploadRef = () => {
+        uploadRef.value?.clearFiles();
+        upload.value.updateSupport = 0;
+    };
+	/** 下载模板操作 */
+	const importTemplate = () => {
+		proxy.download(
+			"system/user/importTemplate",
+			{},
+			`user_template_${new Date().getTime()}.xlsx`
+		);
+	};
+	// 文件上传中处理
+	const handleFileUploadProgress = (event: any, file: any, fileList: any) => {
+		upload.value.isUploading = true;
+	};
+	// 文件上传成功处理
+	const handleFileSuccess = (response: any, file: any, fileList: any) => {
+		upload.value.open = false;
+		upload.isUploading = false;
+		// proxy.$refs.upload.clearFiles();
+        cleanUploadRef();
+		proxy.$alert(response.msg, "导入结果", {
+			dangerouslyUseHTMLString: true,
+		});
+		getPageList();
+	};
+	// 提交上传文件
+	const submitFileForm = () => {
+		proxy.$refs.upload.submit();
+	};
+
+    const checkSelected  = (row: any) => {
+        // 设置不可选中
+        return !row.admin;
+    };
+
+	getPageList();
+	getTreeselect();
+	// proxy.getDicts("sys_normal_disable").then((response: { data: any }) => {
+	// 	statusOptions.value = response.data;
+	// });
+	// proxy.getDicts("sys_user_sex").then((response: { data: any }) => {
+	// 	sexOptions.value = response.data;
+	// });
+	proxy
+		.getConfigKey("sys.user.initPassword")
+		.then((response: { msg: any }) => {
+			initPassword.value = response.msg;
+		});
+
+	// prettier-ignore
+	return {
+        loading, queryFormRef, formRef, sys_normal_disable, deptTreeRef, single, multiple, showSearch, total, userList, title, deptOptions, open, 
+        deptName, dateRange, sys_user_sex, postOptions, roleOptions, form, defaultProps, upload, queryParams, columns, rules, pageTableRef, uploadRef,
+        getPageList, filterNode, handleNodeClick, handleStatusChange,  cancel, handleQuery, resetQuery, handleSelectionChange, statusChange,
+        handleAdd, handleUpdate, handleResetPwd, submitForm, handleDelete, handleExport, handleImport, importTemplate, handleFileUploadProgress, 
+        handleFileSuccess, submitFileForm, checkSelected, cleanSelect, cleanUploadRef
+    };
+};

+ 57 - 0
src/api/system/cache.ts

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

+ 108 - 0
src/api/system/config.ts

@@ -0,0 +1,108 @@
+import request from "@/utils/request";
+
+/**
+ * 查询参数列表
+ *
+ * @param {object} query 参数Obj
+ * @returns
+ */
+export const listConfig = async (query: any) => {
+	return await request({
+		url: "/system/config/list",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 查询参数详细
+ *
+ * @param {string} configId 参数ID
+ * @returns
+ */
+export const getConfig = async (configId: string) => {
+	return await request({
+		url: "/system/config/" + configId,
+		method: "get",
+	});
+};
+
+/**
+ * 根据参数键名查询参数值
+ *
+ * @param {string} configKey 参数键名
+ * @returns
+ */
+export const getConfigKey = async (configKey: string) => {
+	return await request({
+		url: "/system/config/configKey/" + configKey,
+		method: "get",
+	});
+};
+
+/**
+ * 新增参数配置
+ *
+ * @param {object} param 参数Obj
+ * @returns
+ */
+export const addConfig = async (param: any) => {
+	return await request({
+		url: "/system/config",
+		method: "post",
+		data: param,
+	});
+};
+
+/**
+ * 修改参数配置
+ *
+ * @param {object} data 参数Obj
+ * @returns
+ */
+export const updateConfig = async (param: any) => {
+	return await request({
+		url: "/system/config",
+		method: "put",
+		data: param,
+	});
+};
+
+/**
+ * 删除参数配置
+ *
+ * @param {string} configId 参数ID
+ * @returns
+ */
+export const delConfig = async (configId: string) => {
+	return await request({
+		url: "/system/config/" + configId,
+		method: "delete",
+	});
+};
+
+/**
+ * 清理参数缓存
+ *
+ * @returns
+ */
+export const clearCache = async () => {
+	return await request({
+		url: "/system/config/clearCache",
+		method: "delete",
+	});
+};
+
+/**
+ * 导出参数
+ *
+ * @param {object} query 查询Obj
+ * @returns
+ */
+export const exportConfig = async (query: any) => {
+	return await request({
+		url: "/system/config/export",
+		method: "get",
+		params: query,
+	});
+};

+ 136 - 0
src/api/system/dept.ts

@@ -0,0 +1,136 @@
+import request from "@/utils/request";
+
+/**
+ * 查询部门列表
+ * 
+ * @param {object} query 查询参数Obj
+ * @returns
+ */
+export const listDept = async (query?: any) => {
+	return await request({
+		url: "/system/dept/list",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 查询部门分页列表
+ * 
+ * @param {object} query 查询参数Obj
+ * @returns
+ */
+ export const page = async (query?: any) => {
+	return await request({
+		url: "/system/dept/page",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 查询部门列表(排除节点
+ * 
+ * @param {string} deptId 部门ID
+ * @returns
+ */
+export const listDeptExcludeChild = async (deptId: string) => {
+	return await request({
+		url: "/system/dept/list/exclude/" + deptId,
+		method: "get",
+	});
+};
+
+/**
+ * 查询部门详细
+ * 
+ * @param {string} deptId 部门ID
+ * @returns
+ */
+export const getDept = async (deptId: string) => {
+	return await request({
+		url: "/system/dept/" + deptId,
+		method: "get",
+	});
+};
+
+/**
+ * 查询部门下拉树结构
+ *
+ * @returns
+ */
+export const treeselect = async () => {
+	return await request({
+		url: "/system/dept/treeselect",
+		method: "get",
+	});
+};
+
+/**
+ * 根据角色ID查询部门树结构
+ *
+ * @param {string} roleId 角色ID
+ * @returns
+ */
+export const roleDeptTreeselect = async (roleId: string) => {
+	return await request({
+		url: "/system/dept/roleDeptTreeselect/" + roleId,
+		method: "get",
+	});
+};
+
+/**
+ * 新增部门
+ *
+ * @param {object} param 部门Obj
+ * @returns
+ */
+export const addDept = async (param: any) => {
+	return await request({
+		url: "/system/dept",
+		method: "post",
+		data: param,
+	});
+};
+
+/**
+ * 修改部门
+ *
+ * @param {object} data 部门Obj
+ * @returns
+ */
+export const updateDept = async (data: any) => {
+	return await request({
+		url: "/system/dept",
+		method: "put",
+		data: data,
+	});
+};
+
+/**
+ * 删除
+ *
+ * @param {string} deptId 部门Id
+ * @returns
+ */
+export const delDept = async (deptId: string) => {
+	return await request({
+		url: "/system/dept/" + deptId,
+		method: "delete",
+	});
+};
+
+
+
+/**
+ * 批量删除
+ *
+ * @param {string} deptIds 部门Id数组
+ * @returns
+ */
+ export const batchDelDept = async (deptIds: string) => {
+	return await request({
+		url: "/system/dept/batchDel/" + deptIds,
+		method: "delete",
+	});
+};

+ 61 - 0
src/api/system/dict/data.ts

@@ -0,0 +1,61 @@
+import request from "@/utils/request";
+
+// 查询字典数据列表
+export const listData = async (query: any) => {
+	return await request({
+		url: "/system/dict/data/list",
+		method: "get",
+		params: query,
+	});
+};
+
+// 查询字典数据详细
+export const getData = async (dictCode: string) => {
+	return await request({
+		url: "/system/dict/data/" + dictCode,
+		method: "get",
+	});
+};
+
+// 根据字典类型查询字典数据信息
+export const getDicts = async (dictType: string) => {
+	return await request({
+		url: "/system/dict/data/type/" + dictType,
+		method: "get",
+	});
+};
+
+// 新增字典数据
+export const addData = async (data: any) => {
+	return await request({
+		url: "/system/dict/data",
+		method: "post",
+		data: data,
+	});
+};
+
+// 修改字典数据
+export const updateData = async (data: any) => {
+	return await request({
+		url: "/system/dict/data",
+		method: "put",
+		data: data,
+	});
+};
+
+// 删除字典数据
+export const delData = async (dictCode: string) => {
+	return await request({
+		url: "/system/dict/data/" + dictCode,
+		method: "delete",
+	});
+};
+
+// 导出字典数据
+export const exportData = async (query: any) => {
+	return await request({
+		url: "/system/dict/data/export",
+		method: "get",
+		params: query,
+	});
+};

+ 83 - 0
src/api/system/dict/type.ts

@@ -0,0 +1,83 @@
+import request from "@/utils/request";
+
+// 查询字典类型列表
+export const listType = async (query?: any) => {
+	return await request({
+		url: "/system/dict/type/list",
+		method: "get",
+		params: query,
+	});
+};
+
+// 查询字典类型详细
+export const getDataType = async (dictId: string) => {
+	return await request({
+		url: "/system/dict/type/" + dictId,
+		method: "get",
+	});
+};
+
+// 新增字典类型
+export const addType = async (data: any) => {
+	return await request({
+		url: "/system/dict/type",
+		method: "post",
+		data: data,
+	});
+};
+
+// 修改字典类型
+export const updateType = async (data: any) => {
+	return await request({
+		url: "/system/dict/type",
+		method: "put",
+		data: data,
+	});
+};
+
+// 删除字典类型
+export const delType = async (dictId: string) => {
+	return await request({
+		url: "/system/dict/type/" + dictId,
+		method: "delete",
+	});
+};
+
+// 清理参数缓存
+export const clearCache = async () => {
+	return await request({
+		url: "/system/dict/type/clearCache",
+		method: "delete",
+	});
+};
+
+// 导出字典类型
+export const exportType = async (query: any) => {
+	return await request({
+		url: "/system/dict/type/export",
+		method: "get",
+		params: query,
+	});
+};
+
+// 获取字典选择框列表
+export const optionselect = async () => {
+	return await request({
+		url: "/system/dict/type/optionselect",
+		method: "get",
+	});
+};
+
+/**
+ * 修改状态
+ * 
+ * @param dictId 
+ * @param status 
+ * @returns 
+ */
+export const updateDictTypeStatus = async (dictId: string, status: string) => {    
+    return await request({
+		url: "/system/dict/type/status/" + dictId + "/" + status,
+		method: "get",
+	});
+};

+ 87 - 0
src/api/system/job.ts

@@ -0,0 +1,87 @@
+import request from "@/utils/request";
+
+/**
+ * 查询定时任务调度列表
+ *
+ * @param {object} param
+ * @returns
+ */
+export const listJob = async (param: any) => {
+    return await request({
+        url: "/monitor/job/list",
+        method: "get",
+        params: param
+    });
+};
+
+/**
+ * 查询定时任务调度详细
+ *
+ * @param {string} jobId
+ * @returns
+ */
+export const getJob = async (jobId: string) => {
+    return await request({
+        url: "/monitor/job/" + jobId,
+        method: "get"
+    });
+};
+
+// 新增定时任务调度
+export const addJob = async (param: any) => {
+    return await request({
+        url: "/monitor/job",
+        method: "post",
+        data: param
+    });
+};
+
+// 修改定时任务调度
+export const updateJob = async (param: any) => {
+    return await request({
+        url: "/monitor/job",
+        method: "put",
+        data: param
+    });
+};
+
+// 删除定时任务调度
+export const delJob = async (jobId: string) => {
+    return await request({
+        url: "/monitor/job/" + jobId,
+        method: "delete"
+    });
+};
+
+// 导出定时任务调度
+export const exportJob = async (param: any) => {
+    return await request({
+        url: "/monitor/job/export",
+        method: "get",
+        params: param
+    });
+};
+
+// 任务状态修改
+export const changeJobStatus = async (jobId: string, status: any) => {
+    return await request({
+        url: "/monitor/job/changeStatus",
+        method: "put",
+        data: {
+            jobId,
+            status
+        }
+    });
+};
+
+// 定时任务立即执行一次
+export const runJob = async (jobId: string, jobGroup: any) => {
+    return await request({
+        url: "/monitor/job/run",
+        method: "put",
+        data: {
+            jobId,
+            jobGroup
+        }
+    });
+};

+ 54 - 0
src/api/system/jobLog.ts

@@ -0,0 +1,54 @@
+import request from "@/utils/request";
+
+/**
+ * 查询调度日志列表
+ * 
+ * @param {object} param 参数Obj
+ * @returns 
+ */
+export const listJobLog = async (param: any) => {
+    return await request({
+        url: "/monitor/jobLog/list",
+        method: "get",
+        params: param
+    });
+};
+
+/**
+ * 删除调度日志
+ * 
+ * @param {string} jobLogId 日志ID
+ * @returns 
+ */
+export const delJobLog = async (jobLogId: string) => {
+    return await request({
+        url: "/monitor/jobLog/" + jobLogId,
+        method: "delete"
+    });
+};
+
+/**
+ * 清空调度日志
+ * 
+ * @returns 
+ */
+export const cleanJobLog = async () => {
+    return await request({
+        url: "/monitor/jobLog/clean",
+        method: "delete"
+    });
+};
+
+/**
+ * 导出调度日志
+ * 
+ * @param {object} query 参数Obj
+ * @returns 
+ */
+export const exportJobLog = async (query: any) => {
+    return await request({
+        url: "/monitor/jobLog/export",
+        method: "get",
+        params: query
+    });
+};

+ 66 - 0
src/api/system/logininfor.ts

@@ -0,0 +1,66 @@
+import request from "@/utils/request";
+
+/**
+ * 查询登录日志列表
+ * 
+ * @param {object} query 
+ * @returns 
+ */
+export const getlist = async (query: any) => {
+     return await request({
+        url: "/monitor/logininfor/list",
+        method: "get",
+        params: query
+    });
+};
+
+/**
+ * 删除登录日志
+ * 
+ * @param {string} infoId 
+ * @returns 
+ */
+export const delLogininfor = async (infoId: string) => {
+    return await request({
+        url: "/monitor/logininfor/" + infoId,
+        method: "delete"
+    });
+};
+
+/**
+ * 清空登录日志
+ * 
+ * @returns 
+ */
+export const cleanLogininfor = () => {
+    return request({
+        url: "/monitor/logininfor/clean",
+        method: "delete"
+    });
+};
+
+/**
+ * 导出登录日志
+ * @param {object} query 
+ * @returns 
+ */
+export const exportLogininfor = (query: any) => {
+    return request({
+        url: "/monitor/logininfor/export",
+        method: "get",
+        params: query
+    });
+};
+
+/**
+ * 解除用户锁定
+ * 
+ * @param {object} query 
+ * @returns 
+ */
+ export const unlockUser = (query: any) => {
+    return request({
+        url: "/monitor/logininfor/unlock?userName=" + query,
+        method: "get",
+    });
+};

+ 133 - 0
src/api/system/menu.ts

@@ -0,0 +1,133 @@
+import request from "@/utils/request";
+
+/**
+ * 查询菜单列表
+ *
+ * @param {any} query 参数
+ * @returns
+ */
+export const listMenu = async (query?: any) => {
+	return await request({
+		url: "/system/menu/list",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 查询菜单分页列表
+ *
+ * @param {any} query 参数
+ * @returns
+ */
+ export const pageList = async (query?: any) => {
+	return await request({
+		url: "/system/menu/page",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 查询菜单详细
+ *
+ * @param {string} menuId 菜单ID
+ * @returns
+ */
+export const getMenu = async (menuId: string) => {
+	return await request({
+		url: "/system/menu/" + menuId,
+		method: "get",
+	});
+};
+
+/**
+ * 查询菜单下拉树结构
+ *
+ * @returns
+ */
+export const treeselect = async () => {
+	return await request({
+		url: "/system/menu/treeselect",
+		method: "get",
+	});
+};
+
+/**
+ * 根据角色ID查询菜单下拉树结构
+ *
+ * @param {string} roleId 角色ID
+ * @returns
+ */
+export const roleMenuTreeSelect = async (roleId: string) => {
+	return await request({
+		url: "/system/menu/roleMenuTreeSelect/" + roleId,
+		method: "get",
+	});
+};
+
+/**
+ * 新增菜单
+ *
+ * @param {object} param 菜单Obj
+ * @returns
+ */
+export const addMenu = async (param: any) => {
+	return await request({
+		url: "/system/menu",
+		method: "post",
+		data: param,
+	});
+};
+
+/**
+ * 修改菜单
+ *
+ * @param {object} param 菜单Obj
+ * @returns
+ */
+export const updateMenu = async (param: any) => {
+	return await request({
+		url: "/system/menu",
+		method: "put",
+		data: param,
+	});
+};
+
+/**
+ * 删除菜单
+ *
+ * @param {string} menuId 菜单ID
+ * @returns
+ */
+export const delMenu = async (menuId: string) => {
+	return await request({
+		url: "/system/menu/" + menuId,
+		method: "delete",
+	});
+};
+
+/**
+ * 批量删除
+ *
+ * @param {string} ids 菜单ID数组
+ * @returns
+ */
+ export const batchDelMenu = async (ids: string) => {
+	return await request({
+		url: "/system/menu/batchDel/" + ids,
+		method: "delete",
+	});
+};
+
+/**
+ * 获取路由
+ *
+ * @returns
+ */
+export const getRouters = async () => {
+	return await request({
+		url: "/getRouters",
+		method: "get",
+	});
+};

+ 69 - 0
src/api/system/notice.ts

@@ -0,0 +1,69 @@
+import request from "@/utils/request";
+
+/**
+ * 查询公告列表
+ *
+ * @param {any} query 参数Obj
+ * @returns
+ */
+export const listNotice = async (query: any) => {
+	return await request({
+		url: "/system/notice/list",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 通过公告ID查询公告
+ *
+ * @param {string} noticeId 公告ID
+ * @returns
+ */
+export const getNotice = async (noticeId: string) => {
+	return await request({
+		url: "/system/notice/" + noticeId,
+		method: "get",
+	});
+};
+
+/**
+ * 新增公告
+ *
+ * @param {object} data 公告Obj
+ * @returns
+ */
+export const addNotice = async (data: any) => {
+	return await request({
+		url: "/system/notice",
+		method: "post",
+		data: data,
+	});
+};
+
+/**
+ * 修改公告
+ *
+ * @param {object} data 公告Obj
+ * @returns
+ */
+export const updateNotice = async (data: any) => {
+	return await request({
+		url: "/system/notice",
+		method: "put",
+		data: data,
+	});
+};
+
+/**
+ * 通过ID删除公告
+ *
+ * @param {string} noticeId 公告ID
+ * @returns
+ */
+export const delNotice = async (noticeId: string) => {
+	return await request({
+		url: "/system/notice/" + noticeId,
+		method: "delete",
+	});
+};

+ 28 - 0
src/api/system/online.ts

@@ -0,0 +1,28 @@
+import request from "@/utils/request";
+
+/**
+ * 查询在线用户列表
+ *
+ * @param {object} query 查询参数
+ * @returns
+ */
+export const list = async (query: any) => {
+	return await request({
+		url: "/monitor/online/list",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 用户强退
+ *
+ * @param {string} tokenId 凭证ID
+ * @returns
+ */
+export const forceLogout = async (tokenId: string) => {
+	return await request({
+		url: "/monitor/online/" + tokenId,
+		method: "delete",
+	});
+};

+ 54 - 0
src/api/system/operlog.ts

@@ -0,0 +1,54 @@
+import request from "@/utils/request";
+
+/**
+ * 查询操作日志列表
+ *
+ * @param {*} query 查询参数
+ * @returns
+ */
+export const getPageList = async (query: any) => {
+	return await request({
+		url: "/monitor/operlog/list",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 删除操作日志
+ *
+ * @param {*} operId 操作日志ID
+ * @returns
+ */
+export const delOperlog = async (operId: string) => {
+	return await request({
+		url: "/monitor/operlog/" + operId,
+		method: "delete",
+	});
+};
+
+/**
+ * 清空操作日志
+ *
+ * @returns
+ */
+export const cleanOperlog = async () => {
+	return await request({
+		url: "/monitor/operlog/clean",
+		method: "delete",
+	});
+};
+
+/**
+ * 导出操作日志
+ *
+ * @param {*} query 导出参数
+ * @returns
+ */
+export const exportOperlog = async (query: any) => {
+	return await request({
+		url: "/monitor/operlog/export",
+		method: "get",
+		params: query,
+	});
+};

+ 83 - 0
src/api/system/post.ts

@@ -0,0 +1,83 @@
+import request from "@/utils/request";
+
+/**
+ * 查询岗位列表
+ *
+ * @param {object} query 查询参数Obj
+ * @returns
+ */
+export const listPost = async (query: any) => {
+	return await request({
+		url: "/system/post/list",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 查询岗位详细
+ *
+ * @param {string} postId 岗位ID
+ * @returns
+ */
+export const getPost = async (postId: string) => {
+	return await request({
+		url: "/system/post/" + postId,
+		method: "get",
+	});
+};
+
+/**
+ * 新增岗位
+ *
+ * @param {object} data 岗位Obj
+ * @returns
+ */
+export const addPost = async (data: any) => {
+	return await request({
+		url: "/system/post",
+		method: "post",
+		data: data,
+	});
+};
+
+/**
+ * 修改岗位
+ *
+ * @param {object} data 岗位Obj
+ * @returns
+ */
+export const updatePost = async (data: any) => {
+	return await request({
+		url: "/system/post",
+		method: "put",
+		data: data,
+	});
+};
+
+/**
+ * 删除岗位
+ *
+ * @param {string} postId 岗位ID
+ * @returns
+ */
+export const delPost = async (postId: string) => {
+	return await request({
+		url: "/system/post/" + postId,
+		method: "delete",
+	});
+};
+
+/**
+ * 导出岗位
+ *
+ * @param {object} query 参数Obj
+ * @returns
+ */
+export const exportPost = async (query: any) => {
+	return await request({
+		url: "/system/post/export",
+		method: "get",
+		params: query,
+	});
+};

+ 179 - 0
src/api/system/role.ts

@@ -0,0 +1,179 @@
+import request from "@/utils/request";
+
+/**
+ * 查询角色列表
+ *
+ * @param {object} query
+ * @returns
+ */
+export const listRole = (query: any) => {
+	return request({
+		url: "/system/role/list",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 查询角色详细
+ *
+ * @param {string} roleId 角色ID
+ * @returns
+ */
+export const getRole = (roleId: string) => {
+	return request({
+		url: "/system/role/" + roleId,
+		method: "get",
+	});
+};
+
+/**
+ * 新增角色
+ *
+ * @param {object} data
+ * @returns
+ */
+export const addRole = (data: any) => {
+	return request({
+		url: "/system/role",
+		method: "post",
+		data: data,
+	});
+};
+
+/**
+ * 修改角色
+ *
+ * @param {object} data
+ * @returns
+ */
+export const updateRole = (data: any) => {
+	return request({
+		url: "/system/role",
+		method: "put",
+		data: data,
+	});
+};
+
+/**
+ * 角色数据权限
+ *
+ * @param {object} data
+ * @returns
+ */
+export const dataScope = (data: any) => {
+	return request({
+		url: "/system/role/dataScope",
+		method: "put",
+		data: data,
+	});
+};
+
+/**
+ * 角色状态修改
+ *
+ * @param {string} roleId 角色ID
+ * @param {string} status 状态值
+ * @returns
+ */
+export const changeRoleStatus = async (roleId: any, status: any) => {
+	const data = {
+		roleId,
+		status,
+	};
+	return await request({
+		url: "/system/role/changeStatus",
+		method: "put",
+		data: data,
+	});
+};
+
+/**
+ * 删除角色
+ *
+ * @param {string} roleId
+ * @returns
+ */
+export const delRole = async (roleId: string) => {
+	return await request({
+		url: "/system/role/" + roleId,
+		method: "delete",
+	});
+};
+
+/**
+ * 导出角色
+ *
+ * @param {object} query
+ * @returns
+ */
+export const exportRole = async (query: any) => {
+	return await request({
+		url: "/system/role/export",
+		method: "post",
+		data: {
+			query,
+		},
+	});
+};
+
+/**
+ * 导出角色
+ *
+ * @param {object} query
+ * @returns
+ */
+export const exportRoleStream = async (query: any) => {
+	return await request({
+		url: "/system/role/exportByStream",
+		method: "post",
+		data: {
+			query,
+		},
+	});
+};
+
+// 查询角色已授权用户列表
+export async function allocatedUserList(query: any) {
+	return await request({
+		url: "/system/role/authUser/allocatedList",
+		method: "get",
+		params: query,
+	});
+}
+
+// 查询角色未授权用户列表
+export async function unallocatedUserList(query: any) {
+	return await request({
+		url: "/system/role/authUser/unallocatedList",
+		method: "get",
+		params: query,
+	});
+}
+
+// 取消用户授权角色
+export async function authUserCancel(data: any) {
+	return await request({
+		url: "/system/role/authUser/cancel",
+		method: "put",
+		data: data,
+	});
+}
+
+// 批量取消用户授权角色
+export async function authUserCancelAll(data: any) {
+	return await request({
+		url: "/system/role/authUser/cancelAll",
+		method: "put",
+		params: data,
+	});
+}
+
+// 授权用户选择
+export async function authUserSelectAll(data: any) {
+	return await request({
+		url: "/system/role/authUser/selectAll",
+		method: "put",
+		params: data,
+	});
+}

+ 13 - 0
src/api/system/server.ts

@@ -0,0 +1,13 @@
+import request from "@/utils/request";
+
+/**
+ * 查询服务器器详细
+ *
+ * @returns
+ */
+export const getServer = async () => {
+	return await request({
+		url: "/monitor/server",
+		method: "get",
+	});
+};

+ 207 - 0
src/api/system/user.ts

@@ -0,0 +1,207 @@
+import request from "@/utils/request";
+import { praseStrEmpty } from "@/utils/ruoyi";
+
+/**
+ * 查询用户列表
+ *
+ * @param {any} query
+ * @returns 用户列表
+ */
+export const listUser = async (query: any) => {
+	return await request({
+		url: "/system/user/list",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 通过用户ID查询用户详细
+ *
+ * @param {string} userId 用户ID
+ * @returns 用户信息
+ */
+export const getUser = async (userId: any) => {
+	return await request({
+		url: "/system/user/" + praseStrEmpty(userId),
+		method: "get",
+	});
+};
+
+/**
+ * 新增用户
+ *
+ * @param {any} data
+ * @returns
+ */
+export const addUser = async (data: any) => {
+	return await request({
+		url: "/system/user",
+		method: "post",
+		data: data,
+	});
+};
+
+/**
+ * 修改用户
+ *
+ * @param {any} data
+ * @returns
+ */
+export const updateUser = async (data: any) => {
+	return await request({
+		url: "/system/user",
+		method: "put",
+		data: data,
+	});
+};
+
+/**
+ * 删除用户
+ *
+ * @param {string} userId 用户ID
+ * @returns
+ */
+export const delUser = async (userId: string) => {
+	return await request({
+		url: "/system/user/" + userId,
+		method: "delete",
+	});
+};
+
+/**
+ * 导出用户
+ *
+ * @param {object} query
+ * @returns
+ */
+export const exportUser = async (query: any) => {
+	return await request({
+		url: "/system/user/export",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 用户密码重置
+ *
+ * @param {string} userId   用户ID
+ * @param {string} password 密码
+ * @returns
+ */
+export const resetUserPwd = async (userId: any, password: any) => {
+	return await request({
+		url: "/system/user/resetPwd",
+		method: "put",
+		data: {
+			userId,
+			password,
+		},
+	});
+};
+
+/**
+ * 用户状态修改
+ *
+ * @param {string} userId 用户ID
+ * @param {string} status 用户状态
+ * @returns
+ */
+export const changeUserStatus = async (userId: string, status: string) => {
+	return await request({
+		url: "/system/user/changeStatus",
+		method: "put",
+		data: {
+			userId,
+			status,
+		},
+	});
+};
+
+/**
+ * 查询用户个人信息
+ *
+ * @returns
+ */
+export const getUserProfile = async () => {
+	return await request({
+		url: "/system/user/profile",
+		method: "get",
+	});
+};
+
+/**
+ * 修改用户个人信息
+ *
+ * @param {object} data
+ * @returns
+ */
+export const updateUserProfile = async (data: any) => {
+	return await request({
+		url: "/system/user/profile",
+		method: "put",
+		data: data,
+	});
+};
+
+/**
+ * 用户密码重置
+ *
+ * @param {string} oldPassword 旧密码
+ * @param {string} newPassword 新密码
+ * @returns
+ */
+export const updateUserPwd = async (oldPassword: any, newPassword: any) => {
+	return await request({
+		url: "/system/user/profile/updatePwd",
+		method: "put",
+		params: {
+			oldPassword,
+			newPassword,
+		},
+	});
+};
+
+/**
+ * 用户头像上传
+ *
+ * @param {Object} data
+ * @returns
+ */
+export const uploadAvatar = async (data: any) => {
+	return await request({
+		url: "/system/user/profile/avatar",
+		method: "post",
+		data: data,
+	});
+};
+
+/**
+ * 下载用户导入模板
+ *
+ * @returns
+ */
+export const importTemplate = async () => {
+	return await request({
+		url: "/system/user/importTemplate",
+		method: "get",
+	});
+};
+
+// 查询授权角色
+export const getAuthRole = async (userId: any) => {
+	return await request({
+		url: "/system/user/authRole/" + userId,
+		method: "get",
+	});
+};
+
+// 保存授权角色
+export const updateAuthRole = async (data: any) => {
+	return await request({
+		url: "/system/user/authRole",
+		method: "put",
+		params: data,
+	});
+};

+ 137 - 0
src/api/tool/gen.ts

@@ -0,0 +1,137 @@
+import request from "@/utils/request";
+
+/**
+ * 查询生成表数据
+ *
+ * @param {object} query
+ * @returns
+ */
+export const listTable = async (query: any) => {
+	return await request({
+		url: "/tool/gen/list",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 查询db数据库列表
+ * @param {object} query
+ * @returns
+ */
+export const listDbTable = async (query: any) => {
+	return await request({
+		url: "/tool/gen/db/list",
+		method: "get",
+		params: query,
+	});
+};
+
+/**
+ * 查询表详细信息
+ *
+ * @param {string} tableId 表ID
+ * @returns
+ */
+export const getGenTable = async (tableId: string) => {
+	return await request({
+		url: "/tool/gen/" + tableId,
+		method: "get",
+	});
+};
+
+/**
+ * 修改代码生成信息
+ *
+ * @param {object} data
+ * @returns
+ */
+export const updateGenTable = async (data: any) => {
+	return await request({
+		url: "/tool/gen/edit",
+		method: "put",
+		data: data,
+	});
+};
+
+/**
+ * 导入表
+ *
+ * @param {object} data
+ * @returns
+ */
+export const importTable = (data: any) => {
+	return request({
+		url: "/tool/gen/importTable",
+		method: "post",
+		params: data,
+	});
+};
+
+/**
+ * 生成代码预览
+ *
+ * @param {string} tableId
+ * @returns
+ */
+export const previewTable = (tableId: string) => {
+	return request({
+		url: "/tool/gen/preview/" + tableId,
+		method: "get",
+	});
+};
+
+/**
+ * 删除表数据
+ *
+ * @param {string} tableId
+ * @returns
+ */
+export const delTable = (tableId: string) => {
+	return request({
+		url: "/tool/gen/" + tableId,
+		method: "delete",
+	});
+};
+
+/**
+ * 生成代码(自定义路径)
+ *
+ * @param {string} tableName
+ * @returns
+ */
+export const genCode = (tableName: string) => {
+	return request({
+		url: "/tool/gen/genCode/" + tableName,
+		method: "get",
+	});
+};
+
+/**
+ * 同步数据库
+ *
+ * @param {string} tableName
+ * @returns
+ */
+export const synchDb = (tableName: string) => {
+	return request({
+		url: "/tool/gen/synchDb/" + tableName,
+		method: "get",
+	});
+};
+
+/**
+ * 修改注释状态或版本
+ * 
+ * @param type 注释或者版本
+ * @param id   主键ID
+ * @param val  状态/版本值
+ * @returns
+ */
+export const updateStausOrVersion = async (type: string, id: string, val: string) => {
+	return await request({
+		url: "/tool/gen/change/" + type + "/" + id+ "/" + val,
+		method: "get",
+	});
+};
+

+ 15 - 0
src/api/ym/equipment.ts

@@ -0,0 +1,15 @@
+import request from "@/utils/request";
+
+/**
+ * 查询参数列表
+ *
+ * @param {object} query 参数Obj
+ * @returns
+ */
+export const listConfig = async (query: any) => {
+	return await request({
+		url: "/system/config/list",
+		method: "notoken",
+		params: query,
+	});
+};

BIN
src/assets/401_images/401.gif


BIN
src/assets/404_images/404.png


BIN
src/assets/404_images/404_cloud.png


+ 1 - 0
src/assets/icons/svg/404.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M121.718 73.272v9.953c3.957-7.584 6.199-16.05 6.199-24.995C127.917 26.079 99.273 0 63.958 0 28.644 0 0 26.079 0 58.23c0 .403.028.806.028 1.21l22.97-25.953h13.34l-19.76 27.187h6.42V53.77l13.728-19.477v49.361H22.998V73.272H2.158c5.951 20.284 23.608 36.208 45.998 41.399-1.44 3.3-5.618 11.263-12.565 12.674-8.607 1.764 23.358.428 46.163-13.178 17.519-4.611 31.938-15.849 39.77-30.513h-13.506V73.272H85.02V59.464l22.998-25.977h13.008l-19.429 27.187h6.421v-7.433l13.727-19.402v39.433h-.027zm-78.24 2.822a10.516 10.516 0 0 1-.996-4.535V44.548c0-1.613.332-3.124.996-4.535a11.66 11.66 0 0 1 2.713-3.68c1.134-1.032 2.49-1.864 4.04-2.468 1.55-.605 3.21-.908 4.982-.908h11.292c1.77 0 3.431.303 4.981.908 1.522.604 2.85 1.41 3.986 2.418l-12.26 16.303v-2.898a1.96 1.96 0 0 0-.665-1.512c-.443-.403-.996-.604-1.66-.604-.665 0-1.218.201-1.661.604a1.96 1.96 0 0 0-.664 1.512v9.071L44.364 77.606a10.556 10.556 0 0 1-.886-1.512zm35.73-4.535c0 1.613-.332 3.124-.997 4.535a11.66 11.66 0 0 1-2.712 3.68c-1.134 1.032-2.49 1.864-4.04 2.469-1.55.604-3.21.907-4.982.907H55.185c-1.77 0-3.431-.303-4.981-.907-1.55-.605-2.906-1.437-4.041-2.47a12.49 12.49 0 0 1-1.384-1.512l13.727-18.217v6.375c0 .605.222 1.109.665 1.512.442.403.996.604 1.66.604.664 0 1.218-.201 1.66-.604a1.96 1.96 0 0 0 .665-1.512V53.87L75.97 36.838c.913.932 1.66 1.99 2.214 3.175.664 1.41.996 2.922.996 4.535v27.011h.028z"/></svg>

+ 1 - 0
src/assets/icons/svg/bug.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M127.88 73.143c0 1.412-.506 2.635-1.518 3.669-1.011 1.033-2.209 1.55-3.592 1.55h-17.887c0 9.296-1.783 17.178-5.35 23.645l16.609 17.044c1.011 1.034 1.517 2.257 1.517 3.67 0 1.412-.506 2.635-1.517 3.668-.958 1.033-2.155 1.55-3.593 1.55-1.438 0-2.635-.517-3.593-1.55l-15.811-16.063a15.49 15.49 0 0 1-1.196 1.06c-.532.434-1.65 1.208-3.353 2.322a50.104 50.104 0 0 1-5.192 2.974c-1.758.87-3.94 1.658-6.546 2.364-2.607.706-5.189 1.06-7.748 1.06V47.044H58.89v73.062c-2.716 0-5.417-.367-8.106-1.102-2.688-.734-5.003-1.631-6.945-2.692a66.769 66.769 0 0 1-5.268-3.179c-1.571-1.057-2.73-1.94-3.476-2.65L33.9 109.34l-14.611 16.877c-1.066 1.14-2.344 1.711-3.833 1.711-1.277 0-2.422-.434-3.434-1.304-1.012-.978-1.557-2.187-1.635-3.627-.079-1.44.333-2.705 1.236-3.794l16.129-18.51c-3.087-6.197-4.63-13.644-4.63-22.342H5.235c-1.383 0-2.58-.517-3.592-1.55S.125 74.545.125 73.132c0-1.412.506-2.635 1.518-3.668 1.012-1.034 2.21-1.55 3.592-1.55h17.887V43.939L9.308 29.833c-1.012-1.033-1.517-2.256-1.517-3.669 0-1.412.505-2.635 1.517-3.668 1.012-1.034 2.21-1.55 3.593-1.55s2.58.516 3.593 1.55l13.813 14.106h67.396l13.814-14.106c1.012-1.034 2.21-1.55 3.592-1.55 1.384 0 2.581.516 3.593 1.55 1.012 1.033 1.518 2.256 1.518 3.668 0 1.413-.506 2.636-1.518 3.67l-13.814 14.105v23.975h17.887c1.383 0 2.58.516 3.593 1.55 1.011 1.033 1.517 2.256 1.517 3.668l-.005.01zM89.552 26.175H38.448c0-7.23 2.489-13.386 7.466-18.469C50.892 2.623 56.92.082 64 .082c7.08 0 13.108 2.541 18.086 7.624 4.977 5.083 7.466 11.24 7.466 18.469z"/></svg>

+ 1 - 0
src/assets/icons/svg/build.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1568899741379" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2054" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M960 591.424V368.96c0-0.288 0.16-0.512 0.16-0.768S960 367.68 960 367.424V192a32 32 0 0 0-32-32H96a32 32 0 0 0-32 32v175.424c0 0.288-0.16 0.512-0.16 0.768s0.16 0.48 0.16 0.768v222.464c0 0.288-0.16 0.512-0.16 0.768s0.16 0.48 0.16 0.768V864a32 32 0 0 0 32 32h832a32 32 0 0 0 32-32v-271.04c0-0.288 0.16-0.512 0.16-0.768S960 591.68 960 591.424z m-560-31.232v-160H608v160h-208z m208 64V832h-208v-207.808H608z m-480-224h208v160H128v-160z m544 0h224v160h-224v-160zM896 224v112.192H128V224h768zM128 624.192h208V832H128v-207.808zM672 832v-207.808h224V832h-224z" p-id="2055"></path></svg>

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików