Browse Source

提交基础版本

main
hulei 1 month ago
commit
f04172c96e
100 changed files with 31475 additions and 0 deletions
  1. 8
    0
      ant-design-pro-vue3/.babelrc
  2. 22
    0
      ant-design-pro-vue3/.env.development
  3. 15
    0
      ant-design-pro-vue3/.eslintrc.cjs
  4. 27
    0
      ant-design-pro-vue3/.eslintrc.js
  5. 3
    0
      ant-design-pro-vue3/.gitattributes
  6. 7
    0
      ant-design-pro-vue3/.gitignore
  7. 8
    0
      ant-design-pro-vue3/.prettierrc.json
  8. 6
    0
      ant-design-pro-vue3/.vscode/extensions.json
  9. 292
    0
      ant-design-pro-vue3/.vscode/settings.json
  10. 340
    0
      ant-design-pro-vue3/.vscode/settings_backup.json
  11. 42
    0
      ant-design-pro-vue3/README.md
  12. 92
    0
      ant-design-pro-vue3/components.d.ts
  13. 35
    0
      ant-design-pro-vue3/config/createModule/backend.ts
  14. 21
    0
      ant-design-pro-vue3/config/createModule/index.ts
  15. 4
    0
      ant-design-pro-vue3/config/createModule/type.ts
  16. 104
    0
      ant-design-pro-vue3/config/createModule/utils.ts
  17. 0
    0
      ant-design-pro-vue3/config/template/helper.ts
  18. 0
    0
      ant-design-pro-vue3/config/template/index.less
  19. 17
    0
      ant-design-pro-vue3/config/template/index.vue
  20. 1
    0
      ant-design-pro-vue3/config/template/lang/cn.ts
  21. 1
    0
      ant-design-pro-vue3/config/template/lang/en.ts
  22. 9
    0
      ant-design-pro-vue3/config/template/service.ts
  23. 0
    0
      ant-design-pro-vue3/config/template/types.ts
  24. 16
    0
      ant-design-pro-vue3/config/tsconfig.json
  25. 1
    0
      ant-design-pro-vue3/env.d.ts
  26. 134
    0
      ant-design-pro-vue3/index.html
  27. 3
    0
      ant-design-pro-vue3/jest.config.js
  28. 41
    0
      ant-design-pro-vue3/mock/account.js
  29. 418
    0
      ant-design-pro-vue3/mock/mockUtils.js
  30. 69
    0
      ant-design-pro-vue3/mock/user.js
  31. 88
    0
      ant-design-pro-vue3/package.json
  32. BIN
      ant-design-pro-vue3/public/account/department.png
  33. BIN
      ant-design-pro-vue3/public/account/levelOneDept.png
  34. BIN
      ant-design-pro-vue3/public/account/levelThreeDept.png
  35. BIN
      ant-design-pro-vue3/public/account/levelTwoDept.png
  36. BIN
      ant-design-pro-vue3/public/avatar2.jpg
  37. BIN
      ant-design-pro-vue3/public/icons/offLine.ico
  38. BIN
      ant-design-pro-vue3/public/icons/onLine.ico
  39. BIN
      ant-design-pro-vue3/public/logo.png
  40. 24898
    0
      ant-design-pro-vue3/public/themes/dark.css
  41. 44
    0
      ant-design-pro-vue3/src/App.vue
  42. 64
    0
      ant-design-pro-vue3/src/api/CurrencyManager.js
  43. 34
    0
      ant-design-pro-vue3/src/api/api.js
  44. 48
    0
      ant-design-pro-vue3/src/api/common.js
  45. 99
    0
      ant-design-pro-vue3/src/api/department.js
  46. 35
    0
      ant-design-pro-vue3/src/api/endYear_manager.js
  47. 17
    0
      ant-design-pro-vue3/src/api/onlineUser.js
  48. 17
    0
      ant-design-pro-vue3/src/api/public/dashbord.js
  49. 291
    0
      ant-design-pro-vue3/src/api/public/fileUpload.js
  50. 375
    0
      ant-design-pro-vue3/src/api/public/flowable.js
  51. 18
    0
      ant-design-pro-vue3/src/api/public/genertorApi.js
  52. 47
    0
      ant-design-pro-vue3/src/api/public/process.js
  53. 71
    0
      ant-design-pro-vue3/src/api/public/sequenceApi.js
  54. 18
    0
      ant-design-pro-vue3/src/api/userLogSearch.js
  55. 69
    0
      ant-design-pro-vue3/src/assets/background.svg
  56. BIN
      ant-design-pro-vue3/src/assets/dhc.gif
  57. 1
    0
      ant-design-pro-vue3/src/assets/icons/battery.svg
  58. 1
    0
      ant-design-pro-vue3/src/assets/icons/batteryCharge.svg
  59. 1
    0
      ant-design-pro-vue3/src/assets/icons/bx-analyse.svg
  60. 29
    0
      ant-design-pro-vue3/src/assets/icons/logo.svg
  61. 174
    0
      ant-design-pro-vue3/src/components/ColorPicker/color.ts
  62. 255
    0
      ant-design-pro-vue3/src/components/ColorPicker/common/Alpha.vue
  63. 85
    0
      ant-design-pro-vue3/src/components/ColorPicker/common/History.vue
  64. 253
    0
      ant-design-pro-vue3/src/components/ColorPicker/common/Hue.vue
  65. 203
    0
      ant-design-pro-vue3/src/components/ColorPicker/common/Saturation.vue
  66. 198
    0
      ant-design-pro-vue3/src/components/ColorPicker/common/VColorInput.vue
  67. 185
    0
      ant-design-pro-vue3/src/components/ColorPicker/index.vue
  68. 153
    0
      ant-design-pro-vue3/src/components/DescriptionList/DescriptionList.vue
  69. 84
    0
      ant-design-pro-vue3/src/components/FastDevelopBall/FastDevelopModal.vue
  70. 0
    0
      ant-design-pro-vue3/src/components/FastDevelopBall/helper.ts
  71. 0
    0
      ant-design-pro-vue3/src/components/FastDevelopBall/index.less
  72. 58
    0
      ant-design-pro-vue3/src/components/FastDevelopBall/index.vue
  73. 1
    0
      ant-design-pro-vue3/src/components/FastDevelopBall/lang/cn.ts
  74. 1
    0
      ant-design-pro-vue3/src/components/FastDevelopBall/lang/en.ts
  75. 13
    0
      ant-design-pro-vue3/src/components/FastDevelopBall/service.ts
  76. 0
    0
      ant-design-pro-vue3/src/components/FastDevelopBall/types.ts
  77. 53
    0
      ant-design-pro-vue3/src/components/FormComponents/DynamicForm.vue
  78. 51
    0
      ant-design-pro-vue3/src/components/GlobalFooter/index.vue
  79. 140
    0
      ant-design-pro-vue3/src/components/GlobalHeader/index.vue
  80. 21
    0
      ant-design-pro-vue3/src/components/HelloWord.tsx
  81. 343
    0
      ant-design-pro-vue3/src/components/LockScreen/index.vue
  82. 7
    0
      ant-design-pro-vue3/src/components/LockScreen/service.ts
  83. 53
    0
      ant-design-pro-vue3/src/components/LogicFlow/basic/customRect.ts
  84. 37
    0
      ant-design-pro-vue3/src/components/LogicFlow/edge/customBezierEdge.ts
  85. 1
    0
      ant-design-pro-vue3/src/components/LogicFlow/icon/rectImg.ts
  86. 147
    0
      ant-design-pro-vue3/src/components/LogicFlow/index.vue
  87. 14
    0
      ant-design-pro-vue3/src/components/LogicFlow/utils/config.ts
  88. 61
    0
      ant-design-pro-vue3/src/components/LogicFlow/utils/getShapeStyleUtil.js
  89. 110
    0
      ant-design-pro-vue3/src/components/Menu/Menu.vue
  90. 60
    0
      ant-design-pro-vue3/src/components/Menu/RenderSubMenu.vue
  91. 59
    0
      ant-design-pro-vue3/src/components/Menu/SideMenu.vue
  92. 25
    0
      ant-design-pro-vue3/src/components/MultiTab/index.less
  93. 203
    0
      ant-design-pro-vue3/src/components/MultiTab/index.vue
  94. 9
    0
      ant-design-pro-vue3/src/components/MultiTab/lang/cn.ts
  95. 9
    0
      ant-design-pro-vue3/src/components/MultiTab/lang/en.ts
  96. 75
    0
      ant-design-pro-vue3/src/components/NProgress/nprogress.less
  97. 86
    0
      ant-design-pro-vue3/src/components/NoticeIcon/index.vue
  98. 48
    0
      ant-design-pro-vue3/src/components/OpenModelButton/index.vue
  99. 199
    0
      ant-design-pro-vue3/src/components/PageHeader/index.vue
  100. 0
    0
      ant-design-pro-vue3/src/components/PageInit/PageInit.vue

+ 8
- 0
ant-design-pro-vue3/.babelrc View File

@@ -0,0 +1,8 @@
1
+{
2
+  "presets": ["@babel/preset-env"],
3
+  "plugins": [
4
+    ["@babel/plugin-transform-react-jsx", {
5
+      "runtime": "automatic"
6
+    }]
7
+  ]
8
+}

+ 22
- 0
ant-design-pro-vue3/.env.development View File

@@ -0,0 +1,22 @@
1
+# Whether to open mock
2
+VITE_USE_MOCK = true
3
+
4
+# public path
5
+VITE_PUBLIC_PATH = /
6
+
7
+# Cross-domain proxy, you can configure multiple
8
+# Please note that no line breaks
9
+VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3300/upload"]]
10
+# VITE_PROXY=[["/api","https://vvbin.cn/test"]]
11
+
12
+# Delete console
13
+VITE_DROP_CONSOLE = false
14
+
15
+# Basic interface address SPA
16
+VITE_GLOB_API_URL=/basic-api
17
+
18
+# File upload address, optional
19
+VITE_GLOB_UPLOAD_URL=/upload
20
+
21
+# Interface prefix
22
+VITE_GLOB_API_URL_PREFIX=

+ 15
- 0
ant-design-pro-vue3/.eslintrc.cjs View File

@@ -0,0 +1,15 @@
1
+/* eslint-env node */
2
+require('@rushstack/eslint-patch/modern-module-resolution')
3
+
4
+module.exports = {
5
+  root: true,
6
+  'extends': [
7
+    'plugin:vue/vue3-essential',
8
+    'eslint:recommended',
9
+    '@vue/eslint-config-typescript',
10
+    '@vue/eslint-config-prettier/skip-formatting'
11
+  ],
12
+  parserOptions: {
13
+    ecmaVersion: 'latest'
14
+  }
15
+}

+ 27
- 0
ant-design-pro-vue3/.eslintrc.js View File

@@ -0,0 +1,27 @@
1
+module.exports = {
2
+  parser: 'vue-eslint-parser',
3
+  parserOptions: {
4
+    parser: '@typescript-eslint/parser', // Specifies the ESLint parser
5
+    ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
6
+    sourceType: 'module', // Allows for the use of imports
7
+    ecmaFeatures: {
8
+      // tsx: true, // Allows for the parsing of JSX
9
+      jsx: true,
10
+    },
11
+  },
12
+  // settings: {
13
+  //   tsx: {
14
+  //     version: "detect" // Tells eslint-plugin-react to automatically detect the version of React to use
15
+  //   }
16
+  // },
17
+  extends: [
18
+    'plugin:vue/vue3-recommended',
19
+    'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
20
+    'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
21
+    'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
22
+  ],
23
+  rules: {
24
+    // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
25
+    // e.g. "@typescript-eslint/explicit-function-return-type": "off",
26
+  },
27
+};

+ 3
- 0
ant-design-pro-vue3/.gitattributes View File

@@ -0,0 +1,3 @@
1
+*.css linguist-language=Vue
2
+*.html linguist-language=Vue
3
+*.js linguist-language=Vue

+ 7
- 0
ant-design-pro-vue3/.gitignore View File

@@ -0,0 +1,7 @@
1
+node_modules
2
+.DS_Store
3
+dist
4
+*.local
5
+package-lock.json
6
+yarn.lock
7
+yarn-error.log

+ 8
- 0
ant-design-pro-vue3/.prettierrc.json View File

@@ -0,0 +1,8 @@
1
+{
2
+  "$schema": "https://json.schemastore.org/prettierrc",
3
+  "semi": false,
4
+  "tabWidth": 2,
5
+  "singleQuote": true,
6
+  "printWidth": 200,
7
+  "trailingComma": "none"
8
+}

+ 6
- 0
ant-design-pro-vue3/.vscode/extensions.json View File

@@ -0,0 +1,6 @@
1
+{
2
+  "recommendations": [
3
+    "aaron-bond.better-comments",
4
+    "fittentech.fitten-code"
5
+  ]
6
+}

+ 292
- 0
ant-design-pro-vue3/.vscode/settings.json View File

@@ -0,0 +1,292 @@
1
+{
2
+  "typescript.tsdk": "./node_modules/typescript/lib",
3
+  "volar.tsPlugin": true,
4
+  "volar.tsPluginStatus": false,
5
+  //===========================================
6
+  //============= Editor ======================
7
+  //===========================================
8
+  "explorer.openEditors.visible": 0,
9
+  "editor.minimap.renderCharacters": false,
10
+  "editor.minimap.maxColumn": 300,
11
+  "editor.minimap.showSlider": "always",
12
+  "editor.smoothScrolling": true,
13
+  "editor.cursorBlinking": "phase",
14
+  "editor.cursorSmoothCaretAnimation": "on",
15
+  "editor.detectIndentation": false,
16
+  "diffEditor.ignoreTrimWhitespace": false,
17
+  "javascript.format.insertSpaceBeforeFunctionParenthesis": true,
18
+  "editor.formatOnPaste": true,
19
+  "editor.formatOnSave": true,
20
+  "editor.suggestSelection": "first",
21
+  "editor.trimAutoWhitespace": true,
22
+  "editor.quickSuggestions": {
23
+    "other": true,
24
+    "comments": true,
25
+    "strings": true
26
+  },
27
+  //===========================================
28
+  //============= Other =======================
29
+  //===========================================
30
+  "breadcrumbs.enabled": true,
31
+  "open-in-browser.default": "chrome",
32
+  //===========================================
33
+  //============= emmet =======================
34
+  //===========================================
35
+  "emmet.triggerExpansionOnTab": true,
36
+  "emmet.showAbbreviationSuggestions": true,
37
+  "emmet.showExpandedAbbreviation": "always",
38
+  "emmet.syntaxProfiles": {
39
+    "vue-html": "html",
40
+    "vue": "html",
41
+    "javascript": "javascriptreact",
42
+    "xml": {
43
+      "attr_quotes": "single"
44
+    }
45
+  },
46
+  "emmet.includeLanguages": {
47
+    "jsx-sublime-babel-tags": "javascriptreact"
48
+  },
49
+  //===========================================
50
+  //============= files =======================
51
+  //===========================================
52
+  "files.trimTrailingWhitespace": false,
53
+  "files.insertFinalNewline": true,
54
+  "files.trimFinalNewlines": true,
55
+  "files.eol": "\n",
56
+  "search.exclude": {
57
+    "**/node_modules": true,
58
+    "**/*.log": true,
59
+    "**/*.log*": true,
60
+    "**/bower_components": true,
61
+    "**/dist": true,
62
+    "**/elehukouben": true,
63
+    "**/.git": true,
64
+    "**/.gitignore": true,
65
+    "**/.svn": true,
66
+    "**/.DS_Store": true,
67
+    "**/.idea": true,
68
+    "**/.vscode": false,
69
+    "**/yarn.lock": true,
70
+    "**/tmp": true,
71
+    "out": true,
72
+    "dist": true,
73
+    "node_modules": true,
74
+    "CHANGELOG.md": true,
75
+    "examples": true,
76
+    "res": true,
77
+    "screenshots": true
78
+  },
79
+  "files.exclude": {
80
+    "**/bower_components": true,
81
+    "**/.idea": true,
82
+    "**/yarn.lock": true,
83
+    "**/tmp": true,
84
+    "**/.git": true,
85
+    "**/.svn": true,
86
+    "**/.hg": true,
87
+    "**/CVS": true,
88
+    "**/.DS_Store": true
89
+  },
90
+  "files.watcherExclude": {
91
+    // 文件监视排除
92
+    "**/.git/objects/**": true,
93
+    "**/.git/subtree-cache/**": true,
94
+    "**/.vscode/**": true,
95
+    "**/node_modules/**": true,
96
+    "**/tmp/**": true,
97
+    "**/bower_components/**": true,
98
+    "**/dist/**": true,
99
+    "**/yarn.lock": true
100
+  },
101
+  "files.associations": {
102
+    "*.vue": "vue",
103
+    "*.wxss": "css"
104
+},
105
+  "stylelint.enable": true,
106
+  "stylelint.packageManager": "yarn",
107
+  "css.validate": true,
108
+  "less.validate": true,
109
+  "scss.validate": true,
110
+  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
111
+  // ===========================================
112
+  // ================ Eslint ===================
113
+  // ===========================================
114
+  // "eslint.enable": true,
115
+  "eslint.alwaysShowStatus": true,
116
+  "eslint.options": {
117
+    // 配置
118
+    "plugins": [
119
+      "html",
120
+      "vue",
121
+      "javascript",
122
+      "jsx",
123
+      "typescript"
124
+    ],
125
+    "extensions": [
126
+      ".js",
127
+      ".jsx",
128
+      ".ts",
129
+      ".tsx",
130
+      ".vue"
131
+    ]
132
+  },
133
+  "eslint.validate": [
134
+    "javascript",
135
+    "typescript",
136
+    "reacttypescript",
137
+    "reactjavascript",
138
+    "html",
139
+    "vue"
140
+  ],
141
+  // "eslint.autoFixOnSave": true,
142
+  // ===========================================
143
+  // ================ Vetur ====================
144
+  // ===========================================
145
+  "vetur.experimental.templateInterpolationService": true,
146
+  "vetur.format.options.tabSize": 2,
147
+  "vetur.format.defaultFormatter.html": "prettyhtml",
148
+  "vetur.format.defaultFormatter.scss": "prettier",
149
+  "vetur.format.defaultFormatter.css": "prettier",
150
+  "vetur.format.defaultFormatter.ts": "prettier-tslint",
151
+  "vetur.format.defaultFormatter.js": "prettier",
152
+  "vetur.languageFeatures.codeActions": false,
153
+  "vetur.format.defaultFormatterOptions": {
154
+    // "js-beautify-html": {
155
+    //   // [auto|force|force-aligned|force-expand-multiline]
156
+    //   "wrap_attributes":"force-expand-multiline",
157
+    //   "wrap_line_length": 200,
158
+    // },
159
+    "prettier": {
160
+      "eslintIntegration": true,
161
+      "arrowParens": "always",
162
+      // 去掉末尾空格
163
+      "semi": false,
164
+      "singleQuote": true,
165
+      "trailingComma": "none"
166
+    }
167
+  },
168
+  "javascript.updateImportsOnFileMove.enabled": "never",
169
+  "liveServer.settings.donotShowInfoMsg": true,
170
+  "terminal.integrated.rendererType": "dom",
171
+  "telemetry.enableCrashReporter": false,
172
+  "telemetry.enableTelemetry": false,
173
+  "workbench.settings.enableNaturalLanguageSearch": false,
174
+  "path-intellisense.mappings": {
175
+    "@/": "${workspaceRoot}/src"
176
+  },
177
+  "prettier.requireConfig": true,
178
+  "typescript.updateImportsOnFileMove.enabled": "always",
179
+  "workbench.sideBar.location": "left",
180
+  "[javascriptreact]": {
181
+    "editor.defaultFormatter": "vscode.typescript-language-features"
182
+  },
183
+  "[typescript]": {
184
+    "editor.defaultFormatter": "vscode.typescript-language-features"
185
+  },
186
+  "[typescriptreact]": {
187
+    "editor.defaultFormatter": "vscode.typescript-language-features"
188
+  },
189
+  "[html]": {
190
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
191
+  },
192
+  "[css]": {
193
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
194
+  },
195
+  "[less]": {
196
+    "editor.defaultFormatter": "michelemelluso.code-beautifier"
197
+  },
198
+  "[scss]": {
199
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
200
+  },
201
+  "[markdown]": {
202
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
203
+  },
204
+  "editor.codeActionsOnSave": {
205
+    "source.fixAll.eslint": "explicit"
206
+},
207
+  "i18n-ally.localesPaths": [
208
+    "src/locales/lang"
209
+  ],
210
+  "i18n-ally.keystyle": "nested",
211
+  "i18n-ally.sortKeys": true,
212
+  "i18n-ally.namespace": true,
213
+  "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
214
+  "i18n-ally.enabledParsers": [
215
+    "ts"
216
+  ],
217
+  "i18n-ally.sourceLanguage": "zh",
218
+  "i18n-ally.enabledFrameworks": [
219
+    "vue",
220
+    "react"
221
+  ],
222
+  "better-comments.tags": [
223
+    {
224
+      "tag": "todo",
225
+      "color": "#FF8C00",
226
+      "strikethrough": false,
227
+      "underline": false,
228
+      "backgroundColor": "transparent",
229
+      "bold": false,
230
+      "italic": false
231
+    },
232
+    {
233
+      "tag": "bug",
234
+      "color": "#FF2D00",
235
+      "strikethrough": false,
236
+      "underline": false,
237
+      "backgroundColor": "transparent",
238
+      "bold": false,
239
+      "italic": false
240
+    },
241
+    {
242
+      "tag": "warn",
243
+      "color": "#3498DB",
244
+      "strikethrough": false,
245
+      "underline": false,
246
+      "backgroundColor": "transparent",
247
+      "bold": false,
248
+      "italic": false
249
+    },
250
+    {
251
+      "tag": "//",
252
+      "color": "#474747",
253
+      "strikethrough": true,
254
+      "underline": false,
255
+      "backgroundColor": "transparent",
256
+      "bold": false,
257
+      "italic": false
258
+    },
259
+    {
260
+      "tag": "*",
261
+      "color": "#98C379",
262
+      "strikethrough": false,
263
+      "underline": false,
264
+      "backgroundColor": "transparent",
265
+      "bold": false,
266
+      "italic": false
267
+    },
268
+    {
269
+      "tag": "info",
270
+      "color": "#35A0FF",
271
+      "strikethrough": false,
272
+      "underline": false,
273
+      "backgroundColor": "transparent",
274
+      "bold": false,
275
+      "italic": false
276
+    },
277
+    {
278
+      "tag": "ques",
279
+      "color": "#FF5400",
280
+      "strikethrough": false,
281
+      "underline": false,
282
+      "backgroundColor": "transparent",
283
+      "bold": false,
284
+      "italic": false
285
+    },
286
+  ],
287
+  "editor.defaultFormatter": "octref.vetur",
288
+  "[vue]": {
289
+    "editor.defaultFormatter": "Vue.volar"
290
+  },
291
+  // "better-comments.highlightPlainText": true
292
+}

+ 340
- 0
ant-design-pro-vue3/.vscode/settings_backup.json View File

@@ -0,0 +1,340 @@
1
+{
2
+  "typescript.tsdk": "./node_modules/typescript/lib",
3
+  "volar.tsPlugin": true,
4
+  "volar.tsPluginStatus": false,
5
+  //===========================================
6
+  //============= Editor ======================
7
+  //===========================================
8
+  "explorer.openEditors.visible": 0,
9
+  "editor.minimap.renderCharacters": false,
10
+  "editor.minimap.maxColumn": 300,
11
+  "editor.minimap.showSlider": "always",
12
+  "editor.smoothScrolling": true,
13
+  "editor.cursorBlinking": "phase",
14
+  "editor.cursorSmoothCaretAnimation": "on",
15
+  "editor.detectIndentation": false,
16
+  "diffEditor.ignoreTrimWhitespace": false,
17
+  "javascript.format.insertSpaceBeforeFunctionParenthesis": true,
18
+  "editor.formatOnPaste": true,
19
+  "editor.suggestSelection": "first",
20
+  "editor.trimAutoWhitespace": true,
21
+  "editor.quickSuggestions": {
22
+    "other": true,
23
+    "comments": true,
24
+    "strings": true
25
+  },
26
+  //===========================================
27
+  //============= Other =======================
28
+  //===========================================
29
+  "breadcrumbs.enabled": true,
30
+  "open-in-browser.default": "chrome",
31
+  //===========================================
32
+  //============= emmet =======================
33
+  //===========================================
34
+  "emmet.triggerExpansionOnTab": true,
35
+  "emmet.showAbbreviationSuggestions": true,
36
+  "emmet.showExpandedAbbreviation": "always",
37
+  "emmet.syntaxProfiles": {
38
+    "vue-html": "html",
39
+    "vue": "html",
40
+    "javascript": "javascriptreact",
41
+    "xml": {
42
+      "attr_quotes": "single"
43
+    }
44
+  },
45
+  "emmet.includeLanguages": {
46
+    "jsx-sublime-babel-tags": "javascriptreact"
47
+  },
48
+  //===========================================
49
+  //============= files =======================
50
+  //===========================================
51
+  "files.trimTrailingWhitespace": false,
52
+  "files.insertFinalNewline": true,
53
+  "files.trimFinalNewlines": true,
54
+  "search.exclude": {
55
+    "**/node_modules": true,
56
+    "**/*.log": true,
57
+    "**/*.log*": true,
58
+    "**/bower_components": true,
59
+    "**/dist": true,
60
+    "**/elehukouben": true,
61
+    "**/.git": true,
62
+    "**/.gitignore": true,
63
+    "**/.svn": true,
64
+    "**/.DS_Store": true,
65
+    "**/.idea": true,
66
+    "**/.vscode": false,
67
+    "**/yarn.lock": true,
68
+    "**/tmp": true,
69
+    "out": true,
70
+    "dist": true,
71
+    "node_modules": true,
72
+    "CHANGELOG.md": true,
73
+    "examples": true,
74
+    "res": true,
75
+    "screenshots": true
76
+  },
77
+  "files.exclude": {
78
+    "**/bower_components": true,
79
+    "**/.idea": true,
80
+    "**/yarn.lock": true,
81
+    "**/tmp": true,
82
+    "**/.git": true,
83
+    "**/.svn": true,
84
+    "**/.hg": true,
85
+    "**/CVS": true,
86
+    "**/.DS_Store": true
87
+  },
88
+  "files.watcherExclude": {
89
+    // 文件监视排除
90
+    "**/.git/objects/**": true,
91
+    "**/.git/subtree-cache/**": true,
92
+    "**/.vscode/**": true,
93
+    "**/node_modules/**": true,
94
+    "**/tmp/**": true,
95
+    "**/bower_components/**": true,
96
+    "**/dist/**": true,
97
+    "**/yarn.lock": true
98
+  },
99
+  "files.associations": {
100
+    "*.vue": "vue",
101
+    "*.wxss": "css"
102
+  },
103
+  "stylelint.enable": true,
104
+  "stylelint.packageManager": "yarn",
105
+  "css.validate": true,
106
+  "less.validate": true,
107
+  "scss.validate": true,
108
+  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
109
+  // ===========================================
110
+  // ================ Eslint ===================
111
+  // ===========================================
112
+  // "eslint.enable": true,
113
+  "eslint.options": {
114
+    // 配置
115
+    "plugins": [
116
+      "html",
117
+      "vue",
118
+      "javascript",
119
+      "jsx",
120
+      "typescript"
121
+    ],
122
+    "extensions": [
123
+      ".js",
124
+      ".jsx",
125
+      ".ts",
126
+      ".tsx",
127
+      ".vue"
128
+    ]
129
+  },
130
+  // "eslint.autoFixOnSave": true,
131
+  // ===========================================
132
+  // ================ Vetur ====================
133
+  // ===========================================
134
+  "vetur.experimental.templateInterpolationService": true,
135
+  "vetur.format.options.tabSize": 2,
136
+  "vetur.format.defaultFormatter.html": "prettyhtml",
137
+  "vetur.format.defaultFormatter.scss": "prettier",
138
+  "vetur.format.defaultFormatter.css": "prettier",
139
+  "vetur.format.defaultFormatter.ts": "prettier-tslint",
140
+  "vetur.format.defaultFormatter.js": "prettier",
141
+  "vetur.languageFeatures.codeActions": false,
142
+  "vetur.format.defaultFormatterOptions": {
143
+    "js-beautify-html": {
144
+      // [auto|force|force-aligned|force-expand-multiline]
145
+      "wrap_attributes": "force",
146
+      "wrap_line_length": 100,
147
+    },
148
+    // "prettier": {
149
+    //   "eslintIntegration": true,
150
+    //   "arrowParens": "always",
151
+    //   // 去掉末尾空格
152
+    //   "semi": false,
153
+    //   "singleQuote": true,
154
+    //   "trailingComma": "none"
155
+    // }
156
+  },
157
+  "javascript.updateImportsOnFileMove.enabled": "never",
158
+  "terminal.integrated.rendererType": "dom",
159
+  "telemetry.enableCrashReporter": false,
160
+  "telemetry.enableTelemetry": false,
161
+  "workbench.settings.enableNaturalLanguageSearch": false,
162
+  "path-intellisense.mappings": {
163
+    "@/": "${workspaceRoot}/src"
164
+  },
165
+  "prettier.requireConfig": true,
166
+  "typescript.updateImportsOnFileMove.enabled": "always",
167
+  "workbench.sideBar.location": "left",
168
+  "[javascriptreact]": {
169
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
170
+  },
171
+  "[typescript]": {
172
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
173
+  },
174
+  "[typescriptreact]": {
175
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
176
+  },
177
+  "[html]": {
178
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
179
+  },
180
+  "[css]": {
181
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
182
+  },
183
+  "[less]": {
184
+    "editor.defaultFormatter": "vscode.css-language-features"
185
+  },
186
+  "[scss]": {
187
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
188
+  },
189
+  "[markdown]": {
190
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
191
+  },
192
+  "editor.codeActionsOnSave": {
193
+    "source.fixAll.eslint": true
194
+  },
195
+  "i18n-ally.localesPaths": [
196
+    "src/locales/lang"
197
+  ],
198
+  "i18n-ally.keystyle": "nested",
199
+  "i18n-ally.sortKeys": true,
200
+  "i18n-ally.namespace": true,
201
+  "i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
202
+  "i18n-ally.enabledParsers": [
203
+    "ts"
204
+  ],
205
+  "i18n-ally.sourceLanguage": "zh",
206
+  "i18n-ally.enabledFrameworks": [
207
+    "vue",
208
+    "react"
209
+  ],
210
+  "better-comments.tags": [
211
+    {
212
+      "tag": "todo",
213
+      "color": "#FF8C00",
214
+      "strikethrough": false,
215
+      "underline": false,
216
+      "backgroundColor": "transparent",
217
+      "bold": false,
218
+      "italic": false
219
+    },
220
+    {
221
+      "tag": "bug",
222
+      "color": "#FF2D00",
223
+      "strikethrough": false,
224
+      "underline": false,
225
+      "backgroundColor": "transparent",
226
+      "bold": false,
227
+      "italic": false
228
+    },
229
+    {
230
+      "tag": "warn",
231
+      "color": "#3498DB",
232
+      "strikethrough": false,
233
+      "underline": false,
234
+      "backgroundColor": "transparent",
235
+      "bold": false,
236
+      "italic": false
237
+    },
238
+    {
239
+      "tag": "//",
240
+      "color": "#474747",
241
+      "strikethrough": true,
242
+      "underline": false,
243
+      "backgroundColor": "transparent",
244
+      "bold": false,
245
+      "italic": false
246
+    },
247
+    {
248
+      "tag": "*",
249
+      "color": "#98C379",
250
+      "strikethrough": false,
251
+      "underline": false,
252
+      "backgroundColor": "transparent",
253
+      "bold": false,
254
+      "italic": false
255
+    },
256
+    {
257
+      "tag": "info",
258
+      "color": "#35A0FF",
259
+      "strikethrough": false,
260
+      "underline": false,
261
+      "backgroundColor": "transparent",
262
+      "bold": false,
263
+      "italic": false
264
+    },
265
+    {
266
+      "tag": "ques",
267
+      "color": "#FF5400",
268
+      "strikethrough": false,
269
+      "underline": false,
270
+      "backgroundColor": "transparent",
271
+      "bold": false,
272
+      "italic": false
273
+    },
274
+  ],
275
+  "editor.defaultFormatter": "esbenp.prettier-vscode",
276
+  "[vue]": {
277
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
278
+  },
279
+  "volar.format.initialIndent": {
280
+    "html": true
281
+  },
282
+  "editor.tabSize": 2,
283
+  "vue.codeActions.enabled": true,
284
+  "prettier.eslintIntegration": true,
285
+  // "better-comments.highlightPlainText": true
286
+
287
+  // 新增内容
288
+  "liveServer.settings.donotShowInfoMsg": true,
289
+  "git.openRepositoryInParentFolders": "always",
290
+  "editor.fontSize": 16,
291
+  "eslint.alwaysShowStatus": true,
292
+  "eslint.validate": [
293
+    "javascript",
294
+    "javascriptreact",
295
+    "typescriptreact",
296
+    "html",
297
+    "vue",
298
+    "typescript"
299
+  ],
300
+  "files.eol": "\n",
301
+  "[javascript]": {
302
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
303
+  },
304
+  "vetur.completion.scaffoldSnippetSources": {
305
+    "workspace": "💼",
306
+    "user": "🗒️",
307
+    "vetur": "✌"
308
+  },
309
+  "vetur.format.defaultFormatter.js": "vscode-typescript",
310
+  "vetur.format.defaultFormatter.less": "none",
311
+  "vetur.format.defaultFormatter.ts": "vscode-typescript",
312
+  "vetur.format.defaultFormatter.html": "prettyhtml",
313
+  "vetur.format.defaultFormatterOptions": {
314
+    // "js-beautify-html": {
315
+    //     "wrap_attributes": "force"
316
+    // },
317
+    "prettyhtml": {
318
+      "printWidth": 100,
319
+      "singleQuote": false,
320
+      "wrapAttributes": false,
321
+      "sortAttributes": false
322
+    }
323
+  },
324
+  "[jsonc]": {
325
+    "editor.defaultFormatter": "vscode.json-language-features"
326
+  },
327
+  "editor.wordWrap": "on",
328
+  "[html]": {
329
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
330
+  },
331
+  "files.autoSave": "afterDelay",
332
+  "search.followSymlinks": false,
333
+  "npm.autoDetect": "off",
334
+  "npm.packageManager": "pnpm",
335
+  "debug.javascript.codelens.npmScripts": "never",
336
+  "npm.scriptHover": false,
337
+  "editor.formatOnSave": true,
338
+  "workbench.colorTheme": "Default Dark+",
339
+  "editor.defaultFormatter": "esbenp.prettier-vscode"
340
+}

+ 42
- 0
ant-design-pro-vue3/README.md View File

@@ -0,0 +1,42 @@
1
+# 启动
2
+
3
+```
4
+下载依赖
5
+
6
+yarn isntall
7
+
8
+启动服务
9
+
10
+npm run dev
11
+
12
+```
13
+# 注意事项
14
+- 进入新转换的页面,页面卡住,点什么都没反应时,说明页面报错了,请查看控制台的错误信息;
15
+
16
+# 代码工具生成的代码需要手动进行以下处理  
17
+
18
+## react -> vue
19
+1. 表单查询按钮回调中的tableRef要改成对应表格的ref
20
+2. 表单保存按钮回调中的formRef要改成对应表单的ref
21
+3. 遇到setFieldState时需要手动转换,目前只对默认仅改变表单值时进行了转换,当出现修改其他属性时,未做处理  
22
+    除此之外,遇到原react表单框架特有函数getFieldState、getFieldValue、setFieldValue等也需要手动转换  
23
+    例如:  
24
+    ```
25
+      setFieldState('name', state => { state.value = value; state.disabled = true; })    
26
+      上面的代码用于给表单的name字段设置value和disabled属性,需要手动转换为vue的写法:
27
+    ```
28
+
29
+## jsp -> vue
30
+1. 查看表单项父组件是否有pro-form,没有手动添加,并设置model参数
31
+2. 打开其他页面按钮,需要手动修改成OpenModelButton组件
32
+3. 表格列中使用formatter方法进行渲染时,需要手动根据函数内容进行修改
33
+
34
+
35
+## 其他
36
+1. 表格数据源中的key字段在antdVue中是保留字,需要改成其他字段,并给表格设置rowKey属性
37
+3. 为解决同一页面有多个相同组件,定义组件参数变量时使用组件id或name作为变量名,如需要可自行对变量名进行修改
38
+
39
+
40
+# 需要优化的地方
41
+1. 下拉树组件没有角色树、菜单树,对应的type为roleTree、menuTree
42
+2. vue下拉树目前没有"leafOlny[只能选中叶子节点]"功能

+ 92
- 0
ant-design-pro-vue3/components.d.ts View File

@@ -0,0 +1,92 @@
1
+/* eslint-disable */
2
+/* prettier-ignore */
3
+// @ts-nocheck
4
+// Generated by unplugin-vue-components
5
+// Read more: https://github.com/vuejs/core/pull/3399
6
+import '@vue/runtime-core'
7
+
8
+export {}
9
+
10
+declare module '@vue/runtime-core' {
11
+  export interface GlobalComponents {
12
+    AAlert: typeof import('ant-design-vue/es')['Alert']
13
+    AAvatar: typeof import('ant-design-vue/es')['Avatar']
14
+    ABadge: typeof import('ant-design-vue/es')['Badge']
15
+    AButton: typeof import('ant-design-vue/es')['Button']
16
+    ACard: typeof import('ant-design-vue/es')['Card']
17
+    ACheckableTag: typeof import('ant-design-vue/es')['CheckableTag']
18
+    ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
19
+    ACol: typeof import('ant-design-vue/es')['Col']
20
+    AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider']
21
+    ADivider: typeof import('ant-design-vue/es')['Divider']
22
+    ADrawer: typeof import('ant-design-vue/es')['Drawer']
23
+    ADropdown: typeof import('ant-design-vue/es')['Dropdown']
24
+    AForm: typeof import('ant-design-vue/es')['Form']
25
+    AFormItem: typeof import('ant-design-vue/es')['FormItem']
26
+    AInput: typeof import('ant-design-vue/es')['Input']
27
+    AInputPassword: typeof import('ant-design-vue/es')['InputPassword']
28
+    AInputSearch: typeof import('ant-design-vue/es')['InputSearch']
29
+    ALayout: typeof import('ant-design-vue/es')['Layout']
30
+    ALayoutContent: typeof import('ant-design-vue/es')['LayoutContent']
31
+    ALayoutFooter: typeof import('ant-design-vue/es')['LayoutFooter']
32
+    ALayoutHeader: typeof import('ant-design-vue/es')['LayoutHeader']
33
+    ALayoutSider: typeof import('ant-design-vue/es')['LayoutSider']
34
+    AList: typeof import('ant-design-vue/es')['List']
35
+    AListItem: typeof import('ant-design-vue/es')['ListItem']
36
+    AListItemMeta: typeof import('ant-design-vue/es')['ListItemMeta']
37
+    Alpha: typeof import('./src/components/ColorPicker/common/Alpha.vue')['default']
38
+    AMenu: typeof import('ant-design-vue/es')['Menu']
39
+    AMenuDivider: typeof import('ant-design-vue/es')['MenuDivider']
40
+    AMenuItem: typeof import('ant-design-vue/es')['MenuItem']
41
+    AModal: typeof import('ant-design-vue/es')['Modal']
42
+    APopover: typeof import('ant-design-vue/es')['Popover']
43
+    ARadioButton: typeof import('ant-design-vue/es')['RadioButton']
44
+    ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
45
+    ARangePicker: typeof import('ant-design-vue/es')['RangePicker']
46
+    ARow: typeof import('ant-design-vue/es')['Row']
47
+    ASelect: typeof import('ant-design-vue/es')['Select']
48
+    ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
49
+    ASpace: typeof import('ant-design-vue/es')['Space']
50
+    ASpin: typeof import('ant-design-vue/es')['Spin']
51
+    ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
52
+    ASwitch: typeof import('ant-design-vue/es')['Switch']
53
+    ATable: typeof import('ant-design-vue/es')['Table']
54
+    ATabPane: typeof import('ant-design-vue/es')['TabPane']
55
+    ATabs: typeof import('ant-design-vue/es')['Tabs']
56
+    ATag: typeof import('ant-design-vue/es')['Tag']
57
+    ATooltip: typeof import('ant-design-vue/es')['Tooltip']
58
+    AUpload: typeof import('ant-design-vue/es')['Upload']
59
+    Breadcrumb: typeof import('./src/components/tools/Breadcrumb.vue')['default']
60
+    ColorPicker: typeof import('./src/components/ColorPicker/index.vue')['default']
61
+    DescriptionList: typeof import('./src/components/DescriptionList/DescriptionList.vue')['default']
62
+    FastDevelopBall: typeof import('./src/components/FastDevelopBall/index.vue')['default']
63
+    FastDevelopModal: typeof import('./src/components/FastDevelopBall/FastDevelopModal.vue')['default']
64
+    GlobalFooter: typeof import('./src/components/GlobalFooter/index.vue')['default']
65
+    GlobalHeader: typeof import('./src/components/GlobalHeader/index.vue')['default']
66
+    GlobalStyle: typeof import('./src/components/SettingDrawer/components/GlobalStyle.vue')['default']
67
+    History: typeof import('./src/components/ColorPicker/common/History.vue')['default']
68
+    Hue: typeof import('./src/components/ColorPicker/common/Hue.vue')['default']
69
+    LayoutSettings: typeof import('./src/components/SettingDrawer/components/LayoutSettings.vue')['default']
70
+    LockScreen: typeof import('./src/components/LockScreen/index.vue')['default']
71
+    Logo: typeof import('./src/components/tools/Logo.vue')['default']
72
+    Manual: typeof import('./src/components/SvgIcon/manual.vue')['default']
73
+    Menu: typeof import('./src/components/Menu/Menu.vue')['default']
74
+    MultiTab: typeof import('./src/components/MultiTab/index.vue')['default']
75
+    NavigationMode: typeof import('./src/components/SettingDrawer/components/NavigationMode.vue')['default']
76
+    NoticeIcon: typeof import('./src/components/NoticeIcon/index.vue')['default']
77
+    OtherSettings: typeof import('./src/components/SettingDrawer/components/OtherSettings.vue')['default']
78
+    PageHeader: typeof import('./src/components/PageHeader/index.vue')['default']
79
+    RenderSubMenu: typeof import('./src/components/Menu/RenderSubMenu.vue')['default']
80
+    RouterLink: typeof import('vue-router')['RouterLink']
81
+    RouterView: typeof import('vue-router')['RouterView']
82
+    Saturation: typeof import('./src/components/ColorPicker/common/Saturation.vue')['default']
83
+    SettingDrawer: typeof import('./src/components/SettingDrawer/index.vue')['default']
84
+    SettingItem: typeof import('./src/components/SettingDrawer/components/SettingItem.vue')['default']
85
+    SideMenu: typeof import('./src/components/Menu/SideMenu.vue')['default']
86
+    SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
87
+    ThemeColor: typeof import('./src/components/SettingDrawer/components/ThemeColor.vue')['default']
88
+    TwoStepCaptcha: typeof import('./src/components/tools/TwoStepCaptcha.vue')['default']
89
+    UserMenu: typeof import('./src/components/tools/UserMenu/index.vue')['default']
90
+    VColorInput: typeof import('./src/components/ColorPicker/common/VColorInput.vue')['default']
91
+  }
92
+}

+ 35
- 0
ant-design-pro-vue3/config/createModule/backend.ts View File

@@ -0,0 +1,35 @@
1
+const express = require('express');
2
+const shelljs = require('shelljs');
3
+const server = express();
4
+const rootPath = process.cwd()
5
+
6
+server.all('*', (req, res, next) => {
7
+  res.header("Access-Control-Allow-Origin", "*");
8
+  res.header("Access-Control-Allow-Headers", "X-Requested-With,username,token");
9
+  res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
10
+  res.header("X-Powered-By", ' 3.2.1')
11
+  res.header("Content-Type", "application/json;charset=utf-8");
12
+  next();
13
+});
14
+
15
+server.get('/createModule/addView', (req, res) => {
16
+  doCopy(`yarn v --moduleName=${req.query.name}`, res)
17
+});
18
+
19
+server.get('/createModule/addComponent', (req, res) => {
20
+  doCopy(`yarn c --moduleName=${req.query.name}`, res)
21
+});
22
+
23
+function doCopy(cmd, res) {
24
+  shelljs.cd(rootPath);
25
+  const shellRes = shelljs.exec(cmd)
26
+  if (shellRes) {
27
+    return res.status(200).send({ error: 0, msg: '创建成功' });
28
+  }
29
+  // 只有创建失败时才会有返回值,因为vite检测到创建文件后会自动刷新页面
30
+  res.status(500).send({ error: 1, msg: '创建失败,具体问题请看控制台' });
31
+}
32
+
33
+server.listen(3006);
34
+
35
+console.log('commander-ui已启动到3006端口')

+ 21
- 0
ant-design-pro-vue3/config/createModule/index.ts View File

@@ -0,0 +1,21 @@
1
+import { moduleTypes } from './type'
2
+import { copyFolder, log, templatePath, disPath, deleteFolder, modifyIndexVue, firstLetterUpperCase } from './utils'
3
+
4
+function run() {
5
+  const argv = require('minimist')(process.argv.slice(2));
6
+  const { type, moduleName } = argv
7
+  if (!moduleName) {
8
+    log.error('请输入组件/页面名称!')
9
+    return false
10
+  }
11
+  copyFolder(templatePath, disPath(type + '/' + firstLetterUpperCase(moduleName)))
12
+  // 修改index.vue的class名称为组件名称
13
+  setTimeout(() => modifyIndexVue(type, moduleName), 300)
14
+  if (type === moduleTypes.component) {
15
+    // components文件夹不需要再复制components文件夹了
16
+    setTimeout(() => deleteFolder(disPath('components/' + moduleName + '/components')), 300)
17
+  }
18
+  log.success('复制完成!')
19
+}
20
+
21
+run()

+ 4
- 0
ant-design-pro-vue3/config/createModule/type.ts View File

@@ -0,0 +1,4 @@
1
+export enum moduleTypes {
2
+  component ='components',
3
+  view ='views'
4
+}

+ 104
- 0
ant-design-pro-vue3/config/createModule/utils.ts View File

@@ -0,0 +1,104 @@
1
+const fs = require('fs')
2
+const path = require('path')
3
+const colors = require('colors-console');
4
+
5
+export function copyFolder(from, to) {
6
+  const fromPath = path.resolve(from)
7
+  const toPath = path.resolve(to)
8
+  fs.access(toPath, function (err) {
9
+    if (err) {
10
+      fs.mkdirSync(toPath)
11
+    }
12
+  })
13
+  fs.readdir(fromPath, function (err, paths) {
14
+    if (err) {
15
+      console.log(err)
16
+      return
17
+    }
18
+    paths.forEach(function (item) {
19
+      const newFromPath = fromPath + '/' + item
20
+      const newToPath = path.resolve(toPath + '/' + item)
21
+
22
+      fs.stat(newFromPath, function (err, stat) {
23
+        if (err) return
24
+        if (stat.isFile()) {
25
+          copyFile(newFromPath, newToPath)
26
+        }
27
+        if (stat.isDirectory()) {
28
+          copyFolder(newFromPath, newToPath)
29
+        }
30
+      })
31
+    })
32
+  })
33
+}
34
+
35
+export function copyFile(from, to) {
36
+  fs.copyFileSync(from, to)
37
+}
38
+
39
+export const pathResolve = (pathStr: string) => {
40
+  return path.resolve(__dirname, pathStr);
41
+};
42
+
43
+
44
+export const log = {
45
+  error: (txt) => console.error(colors('red', txt)),
46
+  warning: (txt) => console.error(colors('yellow', txt)),
47
+  info: (txt) => console.error(colors('cyan', txt)),
48
+  default: (txt) => console.error(colors('bright', txt)),
49
+  success: (txt) => console.error(colors('green', txt)),
50
+}
51
+
52
+export const templatePath = pathResolve('../template')
53
+export const disPath = (moduleName) => pathResolve('../../src/' + moduleName)
54
+
55
+export function deleteFolder(url) {
56
+  let files = [];
57
+  /**
58
+   * 判断给定的路径是否存在
59
+   */
60
+  if (fs.existsSync(url)) {
61
+    /**
62
+     * 返回文件和子目录的数组
63
+     */
64
+    files = fs.readdirSync(url);
65
+    files.forEach(function (file, index) {
66
+
67
+      const curPath = path.join(url, file);
68
+      log.error(curPath);
69
+      /**
70
+       * fs.statSync同步读取文件夹文件,如果是文件夹,在重复触发函数
71
+       */
72
+      if (fs.statSync(curPath).isDirectory()) { // recurse
73
+        deleteFolder(curPath);
74
+
75
+      } else {
76
+        fs.unlinkSync(curPath);
77
+      }
78
+    });
79
+    /**
80
+     * 清除文件夹
81
+     */
82
+    fs.rmdirSync(url);
83
+
84
+  } else {
85
+    log.error("要删除的路径不存在,请给出正确的路径!");
86
+  }
87
+}
88
+
89
+export const firstLetterUpperCase = (str) => {
90
+  str = str.toString()
91
+  return str.replace(str[0], str[0].toUpperCase());
92
+}
93
+
94
+export function modifyIndexVue(type, moduleName) {
95
+  const filePath = disPath(type + '/' + moduleName + '/index.vue')
96
+  fs.readFile(filePath, 'utf8', function (err, data) {
97
+    if (err) throw err;
98
+    data = data.replace(/\${class}/g, firstLetterUpperCase(moduleName))
99
+    fs.writeFileSync(filePath, data, 'utf8', (err) => {
100
+      if (err) throw err;
101
+      console.log('success done');
102
+    });
103
+  });
104
+}

+ 0
- 0
ant-design-pro-vue3/config/template/helper.ts View File


+ 0
- 0
ant-design-pro-vue3/config/template/index.less View File


+ 17
- 0
ant-design-pro-vue3/config/template/index.vue View File

@@ -0,0 +1,17 @@
1
+<template>
2
+  <section class="${class}">
3
+
4
+  </section>
5
+</template>
6
+
7
+<script lang="ts" name="${class}">
8
+import { ref, reactive } from 'vue'
9
+import * as api from './service'
10
+
11
+</script>
12
+
13
+<style lang="less" scoped>
14
+.${class}{
15
+
16
+}
17
+</style>

+ 1
- 0
ant-design-pro-vue3/config/template/lang/cn.ts View File

@@ -0,0 +1 @@
1
+export default {}

+ 1
- 0
ant-design-pro-vue3/config/template/lang/en.ts View File

@@ -0,0 +1 @@
1
+export default {}

+ 9
- 0
ant-design-pro-vue3/config/template/service.ts View File

@@ -0,0 +1,9 @@
1
+// import baseService from '@/utils/http/axios'
2
+// import { baseURL } from '@/utils/util'
3
+
4
+// export const test = data => {
5
+//   const api = baseURL + `test`
6
+//   return baseService.post(api, data)
7
+// }
8
+export interface temp {
9
+}

+ 0
- 0
ant-design-pro-vue3/config/template/types.ts View File


+ 16
- 0
ant-design-pro-vue3/config/tsconfig.json View File

@@ -0,0 +1,16 @@
1
+{
2
+  "include": [
3
+    "config/**/*.ts",
4
+  ],
5
+  "compilerOptions": {
6
+    "target": "esnext",
7
+    "module": "commonjs",
8
+    "sourceMap": true,
9
+    "resolveJsonModule": true,
10
+    "strict": false,
11
+    "noUnusedLocals": false,
12
+    "noImplicitReturns": false,
13
+    "esModuleInterop": true,
14
+    "noImplicitAny": false,
15
+  }
16
+}

+ 1
- 0
ant-design-pro-vue3/env.d.ts View File

@@ -0,0 +1 @@
1
+/// <reference types="vite/client" />

+ 134
- 0
ant-design-pro-vue3/index.html View File

@@ -0,0 +1,134 @@
1
+<!DOCTYPE html>
2
+<html lang="en" id="html">
3
+  <head>
4
+    <meta charset="UTF-8" />
5
+    <link rel="icon" href="/src/assets/dhc.gif" />
6
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+    <title>总账管理系统</title>
8
+    <style>
9
+      .first-loading-wrp {
10
+        display: flex;
11
+        justify-content: center;
12
+        align-items: center;
13
+        flex-direction: column;
14
+        min-height: 420px;
15
+        height: 100%;
16
+      }
17
+      .first-loading-wrp > h1 {
18
+        font-size: 128px;
19
+      }
20
+      .first-loading-wrp .loading-wrp {
21
+        padding: 98px;
22
+        display: flex;
23
+        justify-content: center;
24
+        align-items: center;
25
+      }
26
+      .dot {
27
+        animation: antRotate 1.2s infinite linear;
28
+        transform: rotate(45deg);
29
+        position: relative;
30
+        display: inline-block;
31
+        font-size: 32px;
32
+        width: 32px;
33
+        height: 32px;
34
+        box-sizing: border-box;
35
+      }
36
+      .dot i {
37
+        width: 14px;
38
+        height: 14px;
39
+        position: absolute;
40
+        display: block;
41
+        background-color: #1890ff;
42
+        border-radius: 100%;
43
+        transform: scale(0.75);
44
+        transform-origin: 50% 50%;
45
+        opacity: 0.3;
46
+        animation: antSpinMove 1s infinite linear alternate;
47
+      }
48
+      .dot i:nth-child(1) {
49
+        top: 0;
50
+        left: 0;
51
+      }
52
+      .dot i:nth-child(2) {
53
+        top: 0;
54
+        right: 0;
55
+        -webkit-animation-delay: 0.4s;
56
+        animation-delay: 0.4s;
57
+      }
58
+      .dot i:nth-child(3) {
59
+        right: 0;
60
+        bottom: 0;
61
+        -webkit-animation-delay: 0.8s;
62
+        animation-delay: 0.8s;
63
+      }
64
+      .dot i:nth-child(4) {
65
+        bottom: 0;
66
+        left: 0;
67
+        -webkit-animation-delay: 1.2s;
68
+        animation-delay: 1.2s;
69
+      }
70
+      @keyframes antRotate {
71
+        to {
72
+          -webkit-transform: rotate(405deg);
73
+          transform: rotate(405deg);
74
+        }
75
+      }
76
+      @-webkit-keyframes antRotate {
77
+        to {
78
+          -webkit-transform: rotate(405deg);
79
+          transform: rotate(405deg);
80
+        }
81
+      }
82
+      @keyframes antSpinMove {
83
+        to {
84
+          opacity: 1;
85
+        }
86
+      }
87
+      @-webkit-keyframes antSpinMove {
88
+        to {
89
+          opacity: 1;
90
+        }
91
+      }
92
+
93
+      .colorfulTitle {
94
+        display: block;
95
+        background: linear-gradient(120deg, #6559ae, #ff7159, #6559ae);
96
+        background-size: 400% 400%;
97
+        -webkit-background-clip: text;
98
+        -webkit-text-fill-color: transparent;
99
+        animation: gradient 1.5s ease-in-out infinite;
100
+        margin-bottom: 0;
101
+        font-size: 100px;
102
+        text-align: center;
103
+        font-weight: 450;
104
+        margin-top: 100px;
105
+      }
106
+
107
+      @keyframes gradient {
108
+        0% {
109
+          background-position: 14% 0%;
110
+        }
111
+
112
+        50% {
113
+          background-position: 87% 100%;
114
+        }
115
+
116
+        100% {
117
+          background-position: 14% 0%;
118
+        }
119
+      }
120
+    </style>
121
+  </head>
122
+  <body>
123
+    <div id="app">
124
+      <div class="first-loading-wrp">
125
+        <h1 class="colorfulTitle" style="text-align: center">DHC</h1>
126
+        <div class="loading-wrp">
127
+          <span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
128
+        </div>
129
+      </div>
130
+    </div>
131
+    <script type="module" src="/src/main.ts"></script>
132
+    <link rel="stylesheet" type="text/css" id="themeCss" />
133
+  </body>
134
+</html>

+ 3
- 0
ant-design-pro-vue3/jest.config.js View File

@@ -0,0 +1,3 @@
1
+module.exports = {
2
+  preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel',
3
+};

+ 41
- 0
ant-design-pro-vue3/mock/account.js View File

@@ -0,0 +1,41 @@
1
+const { api, delay, mock, resp } = require("apite");
2
+
3
+api.get("/member/user/personDetail", {
4
+  id: 22,
5
+  employeeId: '11111111',
6
+  adAccount: 'JACK.LI1',
7
+  email: 'Jack.Li1@home.cn',
8
+  nickname: null,
9
+  bio: null,
10
+  avatar: '/account/levelThreeDept.png',
11
+  skills: 'Java;C#;English;Html',
12
+  mySkills: null,
13
+  interest: '吃饭;睡觉;打豆豆;学习',
14
+  myInterest: '写代码',
15
+  chineseName: '小李',
16
+  englishName: 'Jack Li',
17
+  empPosition: 'IT Software Engineer',
18
+  levelOneDept: 'IT',
19
+  levelTwoDept: 'IT TMP',
20
+  levelThreeDept: 'IT2IT-Shared Services'
21
+})
22
+
23
+api.get("/member/label/findAll", [
24
+  {
25
+    id: '60530b2e12b2d557ccaf8e34',
26
+    skill: 'Java;C#;English;Html',
27
+    hobby: '吃饭;睡觉;打豆豆;学习',
28
+    creator: 'abel.yu',
29
+    editor: 'jack.li1',
30
+    insertDate: '2021-03-18T16:11:26.682',
31
+    cdate: '2021-03-18T16:11:26.682',
32
+    edate: '2021-03-23T13:33:31.883'
33
+  }
34
+])
35
+
36
+api.post('/member/user/updatePersonDetail', {
37
+  status: 200,
38
+  enMsg: 'OK',
39
+  zhMsg: '成功',
40
+  data: 'update person detail success'
41
+})

+ 418
- 0
ant-design-pro-vue3/mock/mockUtils.js View File

@@ -0,0 +1,418 @@
1
+const responseBody = {
2
+  message: '',
3
+  timestamp: 0,
4
+  result: null,
5
+  code: 0,
6
+  _status: 0,
7
+  _headers: {}
8
+}
9
+
10
+
11
+module.exports = {
12
+  builder: (data, message, code = 0, headers = {}) => {
13
+    responseBody.result = data
14
+    if (message !== undefined && message !== null) {
15
+      responseBody.message = message
16
+    }
17
+    if (code !== undefined && code !== 0) {
18
+      responseBody.code = code
19
+      responseBody._status = code
20
+    }
21
+    if (headers !== null && typeof headers === 'object' && Object.keys(headers).length > 0) {
22
+      responseBody._headers = headers
23
+    }
24
+    responseBody.timestamp = new Date().getTime()
25
+    return responseBody
26
+  },
27
+  userNav: [
28
+    // dashboard
29
+    {
30
+      'name': 'dashboard',
31
+      'parentId': 0,
32
+      'id': 1,
33
+      'meta': {
34
+        'icon': 'bx-analyse',
35
+        'title': '仪表盘',
36
+        'show': true,
37
+      },
38
+      'component': 'RouteView',
39
+      'redirect': '/dashboard/workplace'
40
+    },
41
+    {
42
+      'name': 'workplace',
43
+      'parentId': 1,
44
+      'id': 7,
45
+      'meta': {
46
+        'title': '工作台',
47
+        'show': true
48
+      },
49
+      'component': 'Workplace'
50
+    },
51
+    {
52
+      'name': 'monitor',
53
+      'path': 'monitor',
54
+      'parentId': 1,
55
+      'id': 3,
56
+      'meta': {
57
+        'title': '监控页(外部)',
58
+        'show': true,
59
+        'target': 'http://www.baidu.com',
60
+        'blank': true
61
+      }
62
+    },
63
+    {
64
+      'name': 'Analysis',
65
+      'parentId': 1,
66
+      'id': 2,
67
+      'meta': {
68
+        'title': '分析页',
69
+        'show': true
70
+      },
71
+      'component': 'Home',
72
+      'path': '/dashboard/analysis'
73
+    },
74
+    {
75
+      'name': 'tests',
76
+      'parentId': 1,
77
+      'id': 8,
78
+      'meta': {
79
+        'title': '测试功能',
80
+        'show': true
81
+      },
82
+      'component': 'TestWork'
83
+    },
84
+
85
+    // form
86
+    {
87
+      'name': 'form',
88
+      'parentId': 0,
89
+      'id': 10,
90
+      'meta': {
91
+        'icon': 'form',
92
+        'title': '表单页'
93
+      },
94
+      'redirect': '/form/base-form',
95
+      'component': 'PageView'
96
+    },
97
+    {
98
+      'name': 'basic-form',
99
+      'parentId': 10,
100
+      'id': 6,
101
+      'meta': {
102
+        'title': '基础表单'
103
+      },
104
+      'component': 'BasicForm'
105
+    },
106
+    {
107
+      'name': 'step-form',
108
+      'parentId': 10,
109
+      'id': 5,
110
+      'meta': {
111
+        'title': '分步表单'
112
+      },
113
+      'component': 'StepForm'
114
+    },
115
+    {
116
+      'name': 'advanced-form',
117
+      'parentId': 10,
118
+      'id': 4,
119
+      'meta': {
120
+        'title': '高级表单'
121
+      },
122
+      'component': 'AdvanceForm'
123
+    },
124
+
125
+    // list
126
+    {
127
+      'name': 'list',
128
+      'parentId': 0,
129
+      'id': 10010,
130
+      'meta': {
131
+        'icon': 'table',
132
+        'title': '列表页',
133
+        'show': true
134
+      },
135
+      'redirect': '/list/table-list',
136
+      'component': 'PageView'
137
+    },
138
+    {
139
+      'name': 'table-list',
140
+      'parentId': 10010,
141
+      'id': 10011,
142
+      'path': '/list/table-list/:pageNo([1-9]\\d*)?',
143
+      'meta': {
144
+        'title': '查询表格',
145
+        'show': true
146
+      },
147
+      'component': 'TableList'
148
+    },
149
+    {
150
+      'name': 'basic-list',
151
+      'parentId': 10010,
152
+      'id': 10012,
153
+      'meta': {
154
+        'title': '标准列表',
155
+        'show': true
156
+      },
157
+      'component': 'StandardList'
158
+    },
159
+    {
160
+      'name': 'card',
161
+      'parentId': 10010,
162
+      'id': 10013,
163
+      'meta': {
164
+        'title': '卡片列表',
165
+        'show': true
166
+      },
167
+      'component': 'CardList'
168
+    },
169
+    {
170
+      'name': 'search',
171
+      'parentId': 10010,
172
+      'id': 10014,
173
+      'meta': {
174
+        'title': '搜索列表',
175
+        'show': true
176
+      },
177
+      'redirect': '/list/search/article',
178
+      'component': 'SearchLayout'
179
+    },
180
+    {
181
+      'name': 'article',
182
+      'parentId': 10014,
183
+      'id': 10015,
184
+      'meta': {
185
+        'title': '搜索列表(文章)',
186
+        'show': true
187
+      },
188
+      'component': 'SearchArticles'
189
+    },
190
+    {
191
+      'name': 'project',
192
+      'parentId': 10014,
193
+      'id': 10016,
194
+      'meta': {
195
+        'title': '搜索列表(项目)',
196
+        'show': true
197
+      },
198
+      'component': 'SearchProjects'
199
+    },
200
+    {
201
+      'name': 'application',
202
+      'parentId': 10014,
203
+      'id': 10017,
204
+      'meta': {
205
+        'title': '搜索列表(应用)',
206
+        'show': true
207
+      },
208
+      'component': 'SearchApplications'
209
+    },
210
+
211
+    // profile
212
+    {
213
+      'name': 'profile',
214
+      'parentId': 0,
215
+      'id': 10018,
216
+      'meta': {
217
+        'title': '详情页',
218
+        'icon': 'profile',
219
+        'show': true
220
+      },
221
+      'redirect': '/profile/basic',
222
+      'component': 'RouteView'
223
+    },
224
+    {
225
+      'name': 'basic',
226
+      'parentId': 10018,
227
+      'id': 10019,
228
+      'meta': {
229
+        'title': '基础详情页',
230
+        'show': true
231
+      },
232
+      'component': 'ProfileBasic'
233
+    },
234
+    {
235
+      'name': 'advanced',
236
+      'parentId': 10018,
237
+      'id': 10020,
238
+      'meta': {
239
+        'title': '高级详情页',
240
+        'show': true
241
+      },
242
+      'component': 'ProfileAdvanced'
243
+    },
244
+
245
+    // result
246
+    {
247
+      'name': 'result',
248
+      'parentId': 0,
249
+      'id': 10021,
250
+      'meta': {
251
+        'title': '结果页',
252
+        'icon': 'check-circle-o',
253
+        'show': true
254
+      },
255
+      'redirect': '/result/success',
256
+      'component': 'PageView'
257
+    },
258
+    {
259
+      'name': 'success',
260
+      'parentId': 10021,
261
+      'id': 10022,
262
+      'meta': {
263
+        'title': '成功',
264
+        'hiddenHeaderContent': true,
265
+        'show': true
266
+      },
267
+      'component': 'ResultSuccess'
268
+    },
269
+    {
270
+      'name': 'fail',
271
+      'parentId': 10021,
272
+      'id': 10023,
273
+      'meta': {
274
+        'title': '失败',
275
+        'hiddenHeaderContent': true,
276
+        'show': true
277
+      },
278
+      'component': 'ResultFail'
279
+    },
280
+
281
+    // Exception
282
+    {
283
+      'name': 'exception',
284
+      'parentId': 0,
285
+      'id': 10024,
286
+      'meta': {
287
+        'title': '异常页',
288
+        'icon': 'warning',
289
+        'show': true
290
+      },
291
+      'redirect': '/exception/403',
292
+      'component': 'RouteView'
293
+    },
294
+    {
295
+      'name': '403',
296
+      'parentId': 10024,
297
+      'id': 10025,
298
+      'meta': {
299
+        'title': '403',
300
+        'show': true
301
+      },
302
+      'component': 'Exception403'
303
+    },
304
+    {
305
+      'name': '404',
306
+      'parentId': 10024,
307
+      'id': 10026,
308
+      'meta': {
309
+        'title': '404',
310
+        'show': true
311
+      },
312
+      'component': 'Exception404'
313
+    },
314
+    {
315
+      'name': '500',
316
+      'parentId': 10024,
317
+      'id': 10027,
318
+      'meta': {
319
+        'title': '500',
320
+        'show': true
321
+      },
322
+      'component': 'Exception500'
323
+    },
324
+
325
+    // account
326
+    {
327
+      'name': 'account',
328
+      'parentId': 0,
329
+      'id': 10028,
330
+      'meta': {
331
+        'title': '个人页',
332
+        'icon': 'user',
333
+        'show': true
334
+      },
335
+      'redirect': '/account/center',
336
+      'component': 'RouteView'
337
+    },
338
+    {
339
+      'name': 'center',
340
+      'parentId': 10028,
341
+      'id': 10029,
342
+      'meta': {
343
+        'title': '个人中心',
344
+        'show': true
345
+      },
346
+      'component': 'AccountCenter'
347
+    },
348
+    // 特殊三级菜单
349
+    {
350
+      'name': 'settings',
351
+      'parentId': 10028,
352
+      'id': 10030,
353
+      'meta': {
354
+        'title': '个人设置',
355
+        'hideHeader': true,
356
+        'hideChildren': true,
357
+        'show': true
358
+      },
359
+      'redirect': '/account/settings/base',
360
+      'component': 'AccountSettings'
361
+    },
362
+    {
363
+      'name': 'BaseSettings',
364
+      'path': '/account/settings/base',
365
+      'parentId': 10030,
366
+      'id': 10031,
367
+      'meta': {
368
+        'title': '基本设置',
369
+        'show': false
370
+      },
371
+      'component': 'BaseSettings'
372
+    },
373
+    {
374
+      'name': 'SecuritySettings',
375
+      'path': '/account/settings/security',
376
+      'parentId': 10030,
377
+      'id': 10032,
378
+      'meta': {
379
+        'title': '安全设置',
380
+        'show': false
381
+      },
382
+      'component': 'SecuritySettings'
383
+    },
384
+    {
385
+      'name': 'CustomSettings',
386
+      'path': '/account/settings/custom',
387
+      'parentId': 10030,
388
+      'id': 10033,
389
+      'meta': {
390
+        'title': '个性化设置',
391
+        'show': false
392
+      },
393
+      'component': 'CustomSettings'
394
+    },
395
+    {
396
+      'name': 'BindingSettings',
397
+      'path': '/account/settings/binding',
398
+      'parentId': 10030,
399
+      'id': 10034,
400
+      'meta': {
401
+        'title': '账户绑定',
402
+        'show': false
403
+      },
404
+      'component': 'BindingSettings'
405
+    },
406
+    {
407
+      'name': 'NotificationSettings',
408
+      'path': '/account/settings/notification',
409
+      'parentId': 10030,
410
+      'id': 10034,
411
+      'meta': {
412
+        'title': '新消息通知',
413
+        'show': false
414
+      },
415
+      'component': 'NotificationSettings'
416
+    }
417
+  ]
418
+}

+ 69
- 0
ant-design-pro-vue3/mock/user.js View File

@@ -0,0 +1,69 @@
1
+// import Mock from 'mockjs'
2
+const { builder, userNav } = require('./mockUtils')
3
+const { api, delay, mock, resp } = require("apite");
4
+
5
+// id: "@id",
6
+// number: "@int(5,9)",
7
+// name: "@name",
8
+// cname: "@cname",
9
+// date: "@dateTime",
10
+// reg: /\w{10}/,
11
+
12
+const userApi = {
13
+  Logout: '/auth/logout',
14
+  ForgePassword: '/auth/forge-password',
15
+  Register: '/auth/register',
16
+  SendSmsErr: '/account/sms_err',
17
+  // get my info
18
+  UserInfo: '/user/info',
19
+  UserMenu: '/user/nav'
20
+}
21
+
22
+api.get("/json", {
23
+  msg: "json2",
24
+});
25
+
26
+api.post("/auth/login", (ctx) => {
27
+  let permission = ''
28
+  if (ctx.post.username === 'admin') {
29
+    permission = 'admin'
30
+  } else if (ctx.post.username === 'ant.design') {
31
+    permission = 'user'
32
+  } else {
33
+    return resp.fail('用户名错误,只有admin和ant.design', 403)
34
+  }
35
+  return {
36
+    id: '4291d7da9005377ec9aec4a71ea837f',
37
+    name: permission,
38
+    username: 'Ones@github',
39
+    password: '',
40
+    avatar: '/avatar2.jpg',
41
+    status: 1,
42
+    telephone: '',
43
+    lastLoginIp: '27.154.74.117',
44
+    lastLoginTime: 1534837621348,
45
+    creatorId: 'admin',
46
+    createTime: 1497160610259,
47
+    merchantCode: 'TLif2btpzg079h15bk',
48
+    deleted: 0,
49
+    permission: [permission],
50
+    token: '12312312',
51
+    menu: userNav,
52
+  }
53
+});
54
+
55
+api.get("/auth/2step-code", (ctx) => {
56
+  return mock(builder({ stepCode: '@int(0, 1)' }))
57
+});
58
+
59
+api.post("/account/sms", (ctx) => {
60
+  return mock(builder({ captcha: '@int(10000, 99999)' }))
61
+});
62
+
63
+api.get("/auth/logout", (ctx) => {
64
+  return builder({}, '[测试接口] 注销成功1')
65
+});
66
+
67
+api.post("/auth/unlock", (ctx) => {
68
+  return mock({ unlocked: true })
69
+});

+ 88
- 0
ant-design-pro-vue3/package.json View File

@@ -0,0 +1,88 @@
1
+{
2
+  "name": "Ant_Design_Pro_Vue_3",
3
+  "version": "0.1.3",
4
+  "private": true,
5
+  "scripts": {
6
+    "dev": "cross-env vite --mode localhost",
7
+    "debug-vite": "cross-env vite --mode localhost --debug",
8
+    "build": "vite build",
9
+    "build-check": "run-p type-check build-only",
10
+    "preview": "vite preview",
11
+    "test:unit": "vitest",
12
+    "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
13
+    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
14
+    "format": "prettier --write src/",
15
+    "dev-ui": "concurrently \"vite -m UseFastDevelopBall\" \"npm run create-module-be\" ",
16
+    "clean-dev": "vite --force",
17
+    "v": "ts-node --project config/tsconfig.json config/createModule/index.ts --type=views",
18
+    "c": "ts-node --project config/tsconfig.json config/createModule/index.ts --type=components",
19
+    "create-module-be": "ts-node --project config/tsconfig.json config/createModule/backend.ts",
20
+    "report": "rimraf dist && cross-env vite build"
21
+  },
22
+  "dependencies": {
23
+    "@aesoper/normal-utils": "^0.1.5",
24
+    "@ant-design/icons-vue": "^6.1.0",
25
+    "@antv/g2plot": "^2.4.26",
26
+    "@logicflow/core": "^1.2.1",
27
+    "@logicflow/extension": "^1.2.1",
28
+    "@tinymce/tinymce-vue": "^6.0.1",
29
+    "@types/uuid": "^9.0.8",
30
+    "@vueuse/core": "^9.13.0",
31
+    "ant-design-vue": "~3.1.0",
32
+    "axios": "^1.3.4",
33
+    "crypto-js": "^4.1.1",
34
+    "echarts": "^5.4.2",
35
+    "less": "^4.1.3",
36
+    "less-loader": "^11.1.0",
37
+    "lodash.clonedeep": "^4.5.0",
38
+    "lodash.debounce": "^4.0.8",
39
+    "lodash.pull": "^4.1.0",
40
+    "mitt": "^3.0.0",
41
+    "moment": "^2.30.1",
42
+    "nprogress": "^0.2.0",
43
+    "sass": "^1.59.3",
44
+    "throttle-debounce": "^5.0.0",
45
+    "tinycolor2": "^1.6.0",
46
+    "tinymce": "^7.2.1",
47
+    "uuid": "^9.0.1",
48
+    "vue": "^3.2.0",
49
+    "vue-clipboard3": "^2.0.0",
50
+    "vue-i18n": "^9.2.2",
51
+    "vue-router": "4.1.3",
52
+    "vuedraggable": "^4.1.0",
53
+    "vuex": "^4.1.0"
54
+  },
55
+  "devDependencies": {
56
+    "@rushstack/eslint-patch": "^1.2.0",
57
+    "@types/jsdom": "^21.1.0",
58
+    "@types/node": "^18.15.3",
59
+    "@vitejs/plugin-vue": "^5.0.4",
60
+    "@vitejs/plugin-vue-jsx": "^3.0.0",
61
+    "@vue/eslint-config-prettier": "^7.1.0",
62
+    "@vue/eslint-config-typescript": "^11.0.2",
63
+    "@vue/test-utils": "^2.3.0",
64
+    "@vue/tsconfig": "^0.1.3",
65
+    "apite": "^1.4.2",
66
+    "colors-console": "^1.0.3",
67
+    "concurrently": "^8.2.0",
68
+    "cross-env": "^7.0.3",
69
+    "eslint": "^8.34.0",
70
+    "eslint-plugin-vue": "^9.9.0",
71
+    "express": "^4.18.2",
72
+    "jsdom": "^21.1.0",
73
+    "npm-run-all": "^4.1.5",
74
+    "prettier": "^2.8.4",
75
+    "rollup-plugin-visualizer": "^5.9.0",
76
+    "shelljs": "^0.8.5",
77
+    "ts-node": "^10.9.1",
78
+    "typescript": "~4.8.4",
79
+    "unplugin-vue-components": "^0.24.1",
80
+    "vite": "^4.1.4",
81
+    "vite-plugin-optimize-persist": "^0.1.2",
82
+    "vite-plugin-package-config": "^0.1.1",
83
+    "vite-plugin-svg-icons": "^2.0.1",
84
+    "vite-plugin-vue-setup-extend": "^0.4.0",
85
+    "vitest": "^0.29.1",
86
+    "vue-tsc": "^1.2.0"
87
+  }
88
+}

BIN
ant-design-pro-vue3/public/account/department.png View File


BIN
ant-design-pro-vue3/public/account/levelOneDept.png View File


BIN
ant-design-pro-vue3/public/account/levelThreeDept.png View File


BIN
ant-design-pro-vue3/public/account/levelTwoDept.png View File


BIN
ant-design-pro-vue3/public/avatar2.jpg View File


BIN
ant-design-pro-vue3/public/icons/offLine.ico View File


BIN
ant-design-pro-vue3/public/icons/onLine.ico View File


BIN
ant-design-pro-vue3/public/logo.png View File


+ 24898
- 0
ant-design-pro-vue3/public/themes/dark.css
File diff suppressed because it is too large
View File


+ 44
- 0
ant-design-pro-vue3/src/App.vue View File

@@ -0,0 +1,44 @@
1
+<template>
2
+    <a-config-provider :locale="lang[proxy.$i18n.locale]">
3
+        <router-view />
4
+    </a-config-provider>
5
+    <LockScreen />
6
+</template>
7
+
8
+<script lang="ts" setup name="App">
9
+import { getCurrentInstance, onErrorCaptured, h } from 'vue'
10
+import zh_CN from 'ant-design-vue/es/locale/zh_CN'
11
+import en_US from 'ant-design-vue/lib/locale-provider/en_US'
12
+import { setDeviceType } from '@/utils/device'
13
+import LockScreen from '@/components/LockScreen/index.vue'
14
+import emitter from '@/utils/eventBus'
15
+import { useRouter } from 'vue-router'
16
+import { Modal } from 'ant-design-vue'
17
+
18
+const { proxy } = getCurrentInstance()
19
+const lang = { 'en-US': en_US, 'zh-CN': zh_CN }
20
+
21
+window.onresize = setDeviceType
22
+setDeviceType()
23
+
24
+const router = useRouter()
25
+emitter.once('axios_goto_login', () => {
26
+    router.push({ name: 'login' })
27
+})
28
+
29
+//全局错误处理
30
+onErrorCaptured((err, instance, info) => {
31
+    if (window.env !== 'localhost') {
32
+        // debugger
33
+        console.log(err, instance, info)
34
+        Modal.error({
35
+            title: 'System Error',
36
+            content: h('pre', err.stack),
37
+            class: 'errorCapturedModal',
38
+            width: '60%'
39
+        })
40
+    }
41
+})
42
+</script>
43
+
44
+<style></style>

+ 64
- 0
ant-design-pro-vue3/src/api/CurrencyManager.js View File

@@ -0,0 +1,64 @@
1
+import settings from '@/settings'
2
+import request from '@/utils/request'
3
+const systemPrefix = settings.systemPrefix
4
+
5
+// 币种查询查询
6
+  export function queryCurrency(param) {
7
+    return request(`${systemPrefix}/im/dhc/zz/automake/zzmanage/currency_manager/CurrencyManagerController.do`, {
8
+      method: 'post',
9
+      data: param,
10
+      requestType: 'form'
11
+    });
12
+  }
13
+
14
+  export function getTabKeyRule(param) {
15
+    return request(`${systemPrefix}/system/select/options/getTabKeyRule.do`, {
16
+      method: 'post',
17
+      data: param,
18
+      requestType: 'form'
19
+    });
20
+  }
21
+  export function CurrencyConversionController(param) {
22
+    return request(`${systemPrefix}/im/dhc/zz/automake/zzmanage/currency_manager/CurrencyConversionController.do`, {
23
+      method: 'post',
24
+      data: param,
25
+      requestType: 'form'
26
+    });
27
+  }
28
+  export function validateRecord(param) {
29
+    return request(`${systemPrefix}/financemanage/validateRecord.do`, {
30
+      method: 'post',
31
+      data: param,
32
+      requestType: 'form'
33
+    });
34
+  }
35
+  export function CurrencyModifyController(param) {
36
+    return request(`${systemPrefix}/im/dhc/zz/automake/zzmanage/currency_manager/CurrencyModifyController.do`, {
37
+      method: 'post',
38
+      data: param,
39
+      requestType: 'form',
40
+      headers: {
41
+        "X-Requested-With": "XMLHttpRequest"
42
+      }
43
+    });
44
+  }
45
+  export function CurrencyInsertController(param) {
46
+    return request(`${systemPrefix}/im/dhc/zz/automake/zzmanage/currency_manager/CurrencyInsertController.do`, {
47
+      method: 'post',
48
+      data: param,
49
+      requestType: 'form',
50
+      headers: {
51
+        "X-Requested-With": "XMLHttpRequest"
52
+      }
53
+    });
54
+  }
55
+  export function searchCurrency(param) {
56
+    return request(`${systemPrefix}/im/dhc/currencymanager/searchCurrency.do`, {
57
+      method: 'post',
58
+      data: param,
59
+      requestType: 'form',
60
+      headers: {
61
+        "X-Requested-With": "XMLHttpRequest"
62
+      }
63
+    });
64
+  }

+ 34
- 0
ant-design-pro-vue3/src/api/api.js View File

@@ -0,0 +1,34 @@
1
+import settings from '@/settings'
2
+import request from '@/utils/request'
3
+const systemPrefix = settings.systemPrefix
4
+
5
+export  function getRole(params) {
6
+  return request({
7
+    url: `${systemPrefix}/automake/controller/system/login/SelectRoleNameController?userno=${params}`,
8
+    method:'post'
9
+  });
10
+}
11
+
12
+export function login(params) {
13
+    let datas = {userno:params.username, pwd:params.password, login_role:params.login_role,loginPage:1}
14
+    return request({
15
+        url: `${systemPrefix}/automake/controller/system/login/LoginAction`,
16
+        method: 'post',
17
+        data:datas
18
+    })
19
+}
20
+
21
+export function getMenuDataService(params){
22
+    return request({
23
+        url: `${systemPrefix}/workflow/category/list/Auth`,
24
+        method: 'post',
25
+        data:params
26
+    })
27
+}
28
+
29
+export function getRoutes(){
30
+    return request({
31
+        url: `/__umiDev/routes`,
32
+        method: 'get',
33
+    })
34
+}

+ 48
- 0
ant-design-pro-vue3/src/api/common.js View File

@@ -0,0 +1,48 @@
1
+import settings from '@/settings'
2
+import request from '@/utils/request'
3
+const systemPrefix = settings.systemPrefix
4
+/**
5
+ * 获取下拉数据
6
+ * 1.根据字段名、表名获取下拉数据
7
+ * 2.自定义url,获取下拉数据
8
+ * @param url  请求地址
9
+ * @param data 请求参数
10
+ */
11
+export function getOptions(url,data) {
12
+  return request({
13
+    url: `${systemPrefix}${url}`,
14
+    method: 'post',
15
+    data
16
+  })
17
+}
18
+export function getDepartmentTree(url,data) {
19
+  return request({
20
+    url: `${systemPrefix}${url}`,
21
+    method: 'post',
22
+    requestType: 'json',
23
+    data
24
+  })
25
+}
26
+export function queryIPageRoles(url,data) {
27
+  return request({
28
+    url: `${systemPrefix}${url}`,
29
+    method: 'post',
30
+    requestType: 'json',
31
+    data
32
+  })
33
+}
34
+
35
+/**
36
+ * 导出方法
37
+ * @param url       请求地址
38
+ * @param headers   请求头
39
+ * @param data      请求参数
40
+ */
41
+export function executeExport(url,headers,rquestConfig) {
42
+  return request({
43
+    ...rquestConfig,
44
+    url: `${systemPrefix}${url}`,
45
+    responseType: 'blob',
46
+    headers,
47
+  })
48
+}

+ 99
- 0
ant-design-pro-vue3/src/api/department.js View File

@@ -0,0 +1,99 @@
1
+import settings from '@/settings'
2
+import request from '@/utils/request'
3
+const systemPrefix = settings.systemPrefix
4
+
5
+/**
6
+ * 获取机构树
7
+ * @param data 请求参数
8
+ */
9
+export function getDepartmentTree(data) {
10
+  return request({
11
+    url: `${systemPrefix}/sys/deparment/getDepartmentTree`,
12
+    method: 'post',
13
+    requestType: 'json',
14
+    data,
15
+  })
16
+}
17
+export function ComDepartSobTreeController(param){
18
+    return request({
19
+        url: `${systemPrefix}/im/dhc/zz/automake/zzmanage/accounting_manager/generalAccount_manager/ComDepartSobTreeController.do`,
20
+        data:{
21
+            tree_type:param,
22
+            isParentType:"&&",
23
+            isAsync:"true",
24
+            isUseSts:"false",
25
+            searchFlag:"02",
26
+            optType:'modify'
27
+        },
28
+        method:'post',
29
+    })
30
+}
31
+
32
+/**
33
+ * 查询下级机构
34
+ * @param data 请求参数
35
+ */
36
+export function querySubDepartments(data) {
37
+  return request({
38
+    url: `${systemPrefix}/sys/deparment/queryLowerDepartments`,
39
+    method: 'post',
40
+    requestType: 'json',
41
+    data,
42
+  })
43
+}
44
+/**机构新增*/
45
+export function addDepartment(data) {
46
+  return request({
47
+    url: `${systemPrefix}/sys/deparment/addDepartment`,
48
+    method: 'post',
49
+    requestType: 'json',
50
+    data,
51
+  })
52
+}
53
+/**
54
+ * 机构修改
55
+ * @param data
56
+ * @returns
57
+ */
58
+export function updateDepartment(data) {
59
+  return request({
60
+    url: `${systemPrefix}/sys/deparment/updateDepartment`,
61
+    method: 'post',
62
+    requestType: 'json',
63
+    data,
64
+  })
65
+}
66
+/**机构删除,同时会将该机构下所有正常状态的用户一并删除 */
67
+export function deleteDepAndUser(data) {
68
+  return request({
69
+    url: `${systemPrefix}/sys/deparment/deleteDepAndUser`,
70
+    method: 'post',
71
+    requestType: 'json',
72
+    params:data,
73
+  })
74
+}
75
+/**通过机构编号获取部门信息 */
76
+export function getDepartmentByNo(data) {
77
+  return request({
78
+    url: `${systemPrefix}/sys/deparment/getDepartmentByNo`,
79
+    method: 'post',
80
+    data,
81
+  })
82
+}
83
+/**机构启用停用 */
84
+export function changeUseSts(data) {
85
+  return request({
86
+    url: `${systemPrefix}/sys/deparment/changeUseSts`,
87
+    method: 'post',
88
+    data,
89
+  })
90
+}
91
+
92
+/**机构恢复*/
93
+export function restoreDep(params) {
94
+  return request({
95
+    url: `${systemPrefix}/sys/deparment/restoreDep`,
96
+    method: 'post',
97
+    params,
98
+  })
99
+}

+ 35
- 0
ant-design-pro-vue3/src/api/endYear_manager.js View File

@@ -0,0 +1,35 @@
1
+import settings from '@/settings'
2
+import request from '@/utils/request'
3
+const systemPrefix = settings.systemPrefix
4
+
5
+export function getFoundationsController() {
6
+  return request({
7
+    url: `${systemPrefix}/im/dhc/zz/automake/zzmanage/comitem_manager/GetFoundationsController.do`,
8
+    method: 'post',
9
+    data:{type:'com_item'},
10
+  })
11
+}
12
+export function userDataLevelQueryController() {
13
+  return request({
14
+    url: `${systemPrefix}/im/dhc/sys/automake/system/user_manager/UserDataLevelQueryController.do`,
15
+    method: 'POST',
16
+  })
17
+}
18
+export function getRecursionSqlResultPublicMethod(paramMap) {
19
+  return request({
20
+    url: `${systemPrefix}/im/dhc/zz/automake/zzmanage/accounting_manager/generalAccount_manager/GetRecursionSqlResultPublicMethod.do`,
21
+    method: 'post',
22
+    data: {
23
+        str: paramMap.str,
24
+        extralSql1: new Buffer(String).toString(paramMap.extralSql1),
25
+        extralSql2: new Buffer(String).toString(paramMap.extralSql2),
26
+        iniNodeAttr: paramMap.iniNodeAttr,
27
+        tableName: paramMap.tableName,
28
+        whereSql: paramMap.whereSql,
29
+        beforeWhere: paramMap.beforeWhere,
30
+        afterWhere: paramMap.afterWhere,
31
+        idColumn: paramMap.idColumn,
32
+        pidColumn: paramMap.pidColumn
33
+  }
34
+})
35
+}

+ 17
- 0
ant-design-pro-vue3/src/api/onlineUser.js View File

@@ -0,0 +1,17 @@
1
+import settings from '@/settings'
2
+import request from '@/utils/request'
3
+const systemPrefix = settings.systemPrefix
4
+  export function query(params) {
5
+    return request(`${systemPrefix}/im/dhc/sys/automake/system/user_manager/onlineUserList.do`, {
6
+      method: 'POST',
7
+      data: params,
8
+      requestType: 'form'
9
+    });
10
+  }
11
+  export function changeOline(params) {
12
+    return request(`${systemPrefix}/im/dhc/sys/automake/system/user_manager/setOffOnline.do`, {
13
+      method: 'POST',
14
+      data: params,
15
+      requestType: 'form'
16
+    });
17
+  }

+ 17
- 0
ant-design-pro-vue3/src/api/public/dashbord.js View File

@@ -0,0 +1,17 @@
1
+import request from '@/utils/request'
2
+
3
+const DASHBORD = "/dashbord"
4
+
5
+/**
6
+ * 获取组件信息
7
+ * @returns 
8
+ */
9
+export function queryComponseInfo(){
10
+  return request({
11
+    url:`${DASHBORD}/com/system/designHandler/queryComponseInfo`,
12
+    method: 'post',
13
+    headers: {
14
+      'Content-Type': 'application/json;charset=UTF-8'
15
+    }
16
+  })
17
+}

+ 291
- 0
ant-design-pro-vue3/src/api/public/fileUpload.js View File

@@ -0,0 +1,291 @@
1
+import request from '@/utils/request'
2
+import settings from '@/settings'
3
+const { systemPrefix } = settings
4
+/**
5
+ * 文件初始化加载查询
6
+ * @param {*} data
7
+ * @returns
8
+ */
9
+export function queryFileQuery(data) {
10
+  data.systemNo = systemPrefix
11
+  return request({
12
+    url: `${systemPrefix}/com/system/fileHandler/queryFileQuery`,
13
+    method: 'post',
14
+    data: data,
15
+    headers: {
16
+      'Content-Type': 'application/json;charset=UTF-8'
17
+    }
18
+  })
19
+}
20
+
21
+/**
22
+ * 文件下载
23
+ * @param {*} data
24
+ */
25
+export function fileDownLoadHandler(data) {
26
+  return request({
27
+    url: `${systemPrefix}/com/system/fileHandler/downFile`,
28
+    method: 'post',
29
+    data: data,
30
+    responseType: 'blob',
31
+  })
32
+}
33
+
34
+/**
35
+ * 文件删除操作
36
+ * @param {} data
37
+ */
38
+export function fileRemoveHandler(data) {
39
+  return request({
40
+    url: `${systemPrefix}/com/system/fileHandler/deleteFile`,
41
+    method: 'post',
42
+    data: data,
43
+  })
44
+}
45
+
46
+/**
47
+ * 交易关联文件删除
48
+ * @param {*} data
49
+ */
50
+export function traceRelFileRemoveHanlder(data) {
51
+  return request({
52
+    url: `${systemPrefix}/com/system/fileHandler/deleteYwFile`,
53
+    method: 'post',
54
+    data: data,
55
+    headers: {
56
+      'Content-Type': 'multipart/form-data'
57
+    },
58
+  })
59
+}
60
+
61
+/**
62
+ * 删除文件片段信息
63
+ * @param {*} data
64
+ */
65
+export function fileSplitFragment(data) {
66
+  return request({
67
+    url: `${systemPrefix}/com/system/fileHandler/removeFileFragement`,
68
+    method: 'post',
69
+    data: data
70
+  })
71
+}
72
+
73
+/**
74
+ * 文件预览转换处理
75
+ * @param {*} data
76
+ * @returns
77
+ */
78
+export function filePreviewHandler(data, uploaded) {
79
+  return request({
80
+    url: `${systemPrefix}/com/system/fileHandler/filePreview`,
81
+    method: 'post',
82
+    data: data,
83
+    headers: {
84
+      'Content-Type': uploaded ? 'application/x-www-form-urlencoded' : 'multipart/form-data'
85
+    },
86
+  })
87
+}
88
+
89
+/**
90
+ * 加载缩略图
91
+ * @param {*} data
92
+ * @returns
93
+ */
94
+export function queryThumbUrl(data) {
95
+  return new Promise((resolve, reject) => {
96
+    request({
97
+      url: `${systemPrefix}/com/system/fileHandler/getPreThumbUrl`,
98
+      method: 'post',
99
+      data: data,
100
+      headers: {
101
+        'Content-Type': "application/x-www-form-urlencoded"
102
+      },
103
+    }).then(function (resp) {
104
+      resolve({ ...resp, paramter: data })
105
+    }).catch(function (error) {
106
+      reject({ ...error, paramter: data });
107
+    })
108
+  })
109
+}
110
+
111
+
112
+/***
113
+ * 文件上传操作
114
+ */
115
+export function uploadFile(dataObj) {
116
+  const { formData, fileInfo } = dataObj
117
+  return new Promise((resolve, reject) => {
118
+    request({
119
+      url: `${systemPrefix}/com/system/fileHandler/multipleFileUpload`,
120
+      method: 'post',
121
+      data: formData,
122
+      headers: {
123
+        'Content-Type': 'multipart/form-data'
124
+      },
125
+    }).then(function (resp) {
126
+      resolve({ ...resp, paramter: fileInfo })
127
+    }).catch(function (error) {
128
+      console.error('error uploadFile uploadFile  : ', error)
129
+      reject({ ...error, paramter: fileInfo });
130
+    })
131
+  })
132
+}
133
+/**
134
+ * 文件打包下载
135
+ * @param {*} data
136
+ */
137
+export function multipleFileDown(data) {
138
+  return new Promise((resolve, reject) => {
139
+    request({
140
+      url: `${systemPrefix}/com/system/fileHandler/downMultipleFile`,
141
+      method: 'post',
142
+      data: data,
143
+      requestType: 'json',
144
+      responseType: 'blob',
145
+    }).then(resp => {
146
+      resolve(resp)
147
+    }).catch(err => {
148
+      reject(err)
149
+    })
150
+  })
151
+}
152
+
153
+
154
+export function queryAllPartition(data) {
155
+  return request({
156
+    url: `${systemPrefix}/com/system/fileHandler/partition/trade/relationship`,
157
+    method: 'post',
158
+    data: data
159
+  })
160
+}
161
+
162
+/**
163
+ * 文件分区查询
164
+ * @param {*} data
165
+ * @returns
166
+ */
167
+export function queryPartition(data) {
168
+  return request({
169
+    url: `${systemPrefix}/com/system/fileHandler/partition/listwithpage`,
170
+    method: 'post',
171
+    data: data
172
+  })
173
+}
174
+
175
+/**
176
+ * 文件分区存储
177
+ * @param {*} data
178
+ * @returns
179
+ */
180
+export function insertPartition(data) {
181
+  return request({
182
+    url: `${systemPrefix}/com/system/fileHandler/partition/save`,
183
+    method: 'post',
184
+    data: data
185
+  })
186
+}
187
+
188
+/**
189
+ * 修改文件分区
190
+ * @param {*} data
191
+ * @returns
192
+ */
193
+export function updatePartition(data) {
194
+  return request({
195
+    url: `${systemPrefix}/com/system/fileHandler/partition/modify`,
196
+    method: 'post',
197
+    data: data
198
+  })
199
+}
200
+
201
+/**
202
+ * 文件分区删除
203
+ * @param {*} data
204
+ * @returns
205
+ */
206
+export function deletePartition(data) {
207
+  return request({
208
+    url: `${systemPrefix}/com/system/fileHandler/partition/delete`,
209
+    method: 'post',
210
+    data: { partitionNo: data.join() }
211
+  })
212
+}
213
+/**
214
+ *
215
+ * @param {*} data
216
+ * @returns
217
+ */
218
+export function savePartitionRel(data) {
219
+  return request({
220
+    url: `${systemPrefix}/com/system/fileHandler/partition/trade/addOrModify`,
221
+    method: 'post',
222
+    data: data,
223
+    requestType: 'json'
224
+  })
225
+}
226
+
227
+/**
228
+ * 删除关联信息
229
+ * @param {*} data
230
+ * @returns
231
+ */
232
+export function deletePartitionRelApi(data) {
233
+  return request({
234
+    url: `${systemPrefix}/com/system/fileHandler/partition/trade/delete`,
235
+    method: 'post',
236
+    data: data,
237
+    requestType: 'json'
238
+  })
239
+}
240
+
241
+/**
242
+ *
243
+ * @param {*} data
244
+ * @returns
245
+ */
246
+export function queryPartitionOrDefault(data) {
247
+  return request({
248
+    url: `${systemPrefix}/com/system/fileHandler/partition/queryPartitionOrDefault`,
249
+    method: 'post',
250
+    data: data,
251
+    requestType: 'json'
252
+  })
253
+}
254
+/**
255
+ * 获取文件最大上传个数限制
256
+ * @returns
257
+ */
258
+export function queryMaxFileSize() {
259
+  return request({
260
+    url: `${systemPrefix}/com/system/fileHandler/partition/queryMaxFileSize`,
261
+    method: 'post',
262
+    requestType: 'json'
263
+  })
264
+}
265
+
266
+/**
267
+ * pdf 文件下载
268
+ * @param {} param
269
+ */
270
+export function downPdf(data) {
271
+  return request({
272
+    url: `${systemPrefix}/com/system/fileHandler/downPdf`,
273
+    method: 'post',
274
+    data: data,
275
+    responseType: 'blob',
276
+  })
277
+}
278
+
279
+/**
280
+ * 查询附件个数
281
+ * @param {*} data
282
+ * @returns
283
+ */
284
+export function queryFileCount(data) {
285
+  return request({
286
+    url: `${systemPrefix}/com/system/fileHandler/queryFileCount`,
287
+    method: 'post',
288
+    data: data,
289
+    requestType: 'json'
290
+  })
291
+}

+ 375
- 0
ant-design-pro-vue3/src/api/public/flowable.js View File

@@ -0,0 +1,375 @@
1
+import request from '@/utils/request'
2
+import settings from '@/settings'
3
+const { flowablePrefix } = settings
4
+
5
+/**
6
+ * 代办任务查询
7
+ * @param {*} data
8
+ * @returns
9
+ */
10
+export function queryTaskApi (data) {
11
+  return request({
12
+    url: `${flowablePrefix}/V1/flowTaskManagement/queryPage`,
13
+    method: 'post',
14
+    data: data,
15
+    requestType: 'json',
16
+  })
17
+}
18
+
19
+/**
20
+ * 查询流程类型
21
+ * @param {*} data
22
+ * @returns
23
+ */
24
+export function queryCategoryType (data) {
25
+  return request({
26
+    url: `${flowablePrefix}/V1/flowBusinessInteraction/queryType`,
27
+    method: 'post',
28
+    data: data,
29
+    requestType: 'json',
30
+  })
31
+}
32
+
33
+/**
34
+ * 任务取消
35
+ * @param {*} data
36
+ * @returns
37
+ */
38
+export function taskCancelApi (data) {
39
+  return request({
40
+    url: `${flowablePrefix}/V1/flowTaskManagement/handlerHumanTask`,
41
+    method: 'post',
42
+    data: data,
43
+    requestType: 'json',
44
+  })
45
+}
46
+
47
+/**
48
+ * 任务撤回
49
+ * @param {*} data
50
+ * @returns
51
+ */
52
+export function taskWithDrawApi (data) {
53
+  return request({
54
+    url: `${flowablePrefix}/V1/flowTaskManagement/handlerHumanTask`,
55
+    method: 'post',
56
+    data: data,
57
+    requestType: 'json',
58
+  })
59
+}
60
+
61
+/**
62
+ * 任务查看
63
+ * @param {*} data
64
+ * @returns
65
+ */
66
+export function taskViewApi (data) {
67
+  return request({
68
+    url: `${flowablePrefix}/V1/flowTaskManagement/gettaskstartInfo`,
69
+    method: 'post',
70
+    data: data,
71
+    requestType: 'json',
72
+  })
73
+}
74
+
75
+/**
76
+ * 任务追踪
77
+ * @param {*} data
78
+ * @returns
79
+ */
80
+export function taskTraceApi (data) {
81
+  return request({
82
+    url: `${flowablePrefix}/V1/flowTaskManagement/getTaskSvg`,
83
+    method: 'post',
84
+    data: data,
85
+    requestType: 'json',
86
+  })
87
+}
88
+
89
+/**
90
+ * 任务提交
91
+ * @param {*} data
92
+ * @returns
93
+ */
94
+export function taskSubmitApi (data) {
95
+  return request({
96
+    url: `${flowablePrefix}/V1/flowTaskManagement/submit`,
97
+    method: 'post',
98
+    data: data,
99
+    requestType: 'json',
100
+  })
101
+}
102
+
103
+/**
104
+ * 查询信息
105
+ * @param {*} data
106
+ * @returns
107
+ */
108
+export function taskAssigneeApi (data) {
109
+  return request({
110
+    url: `${flowablePrefix}/V1/flowBusinessInteraction/userQuery`,
111
+    method: 'post',
112
+    data: data,
113
+    requestType: 'json',
114
+  })
115
+}
116
+
117
+/**
118
+ * 查询岗位信息
119
+ * @param {*} data
120
+ * @returns
121
+ */
122
+export function taskRoleApi (data) {
123
+  return request({
124
+    url: `${flowablePrefix}/V1/flowBusinessInteraction/roleQuery`,
125
+    method: 'post',
126
+    data: data,
127
+    requestType: 'json',
128
+  })
129
+}
130
+
131
+/**
132
+ * 指派保存
133
+ * @returns
134
+ */
135
+export function taskAssigneeSumitApi (data) {
136
+  return request({
137
+    url: `${flowablePrefix}/V1/flowTaskManagement/handleTaskWithAssignList`,
138
+    method: 'post',
139
+    data: data,
140
+    requestType: 'json',
141
+  })
142
+}
143
+
144
+/**
145
+ * 获取子流程流程实例 信息
146
+ * @param {*} params
147
+ * @returns
148
+ */
149
+export function getChildFlowInstance (params) {
150
+  return request({
151
+    url: `${flowablePrefix}/V1/flowTaskManagement/getChildFlowInstance`,
152
+    method: 'post',
153
+    params,
154
+  })
155
+}
156
+
157
+/**
158
+ * 流程模型查询
159
+ * @param {*} data
160
+ * @returns
161
+ */
162
+export function queryProcModelApi (data) {
163
+  return request({
164
+    url: `${flowablePrefix}/V1//flowDefinitionManagement/query`,
165
+    method: 'post',
166
+    requestType: 'json',
167
+    data: data
168
+  })
169
+}
170
+
171
+/**
172
+ * 通过流程模型id 查询xml
173
+ * @param {*} data
174
+ * @returns
175
+ */
176
+export function queryProcModelByIdApi (data) {
177
+  return request({
178
+    url: `${flowablePrefix}/V1/flowDefinitionManagement/design`,
179
+    method: 'post',
180
+    requestType: 'json',
181
+    data: data
182
+  })
183
+}
184
+
185
+/**
186
+ * 查询关联页面查询信息
187
+ * @param {} data
188
+ */
189
+export function queryRefPageApi (data) {
190
+  return request({
191
+    url: `${flowablePrefix}/V1/flowBusinessInteraction/getAssociatePageQuery`,
192
+    method: 'post',
193
+    requestType: 'json',
194
+    data: data
195
+  })
196
+}
197
+
198
+
199
+/**
200
+ *
201
+ * @param {*} data
202
+ * @returns
203
+ */
204
+export function queryBusinessData (data) {
205
+  return request({
206
+    url: `${flowablePrefix}/V1/flowBusinessInteraction/queryBusinessData`,
207
+    method: 'post',
208
+    requestType: 'json',
209
+    data: data
210
+  })
211
+}
212
+
213
+/**
214
+ * 流程模型保存草稿
215
+ */
216
+export function saveModelApi (data) {
217
+  return request({
218
+    url: `${flowablePrefix}/V1/flowDefinitionManagement/insert`,
219
+    method: 'post',
220
+    requestType: 'json',
221
+    data: data
222
+  })
223
+}
224
+
225
+/**
226
+ * 流程模型删除
227
+ * @param {*} data
228
+ * @returns
229
+ */
230
+export function deleteModelApi (data) {
231
+  return request({
232
+    url: `${flowablePrefix}/V1/flowDefinitionManagement/deleteModel`,
233
+    method: 'post',
234
+    requestType: 'json',
235
+    data: data
236
+  })
237
+}
238
+
239
+/**
240
+ * 查询流程模型是否存在
241
+ * @param {*} data
242
+ * @returns
243
+ */
244
+export function queryProcessModelApi (data) {
245
+  return request({
246
+    url: `${flowablePrefix}/V1/flowDefinitionManagement/findCategoryModel?category=${data.category}`,
247
+    method: 'get',
248
+    // data: data
249
+  })
250
+}
251
+
252
+/**
253
+ * 流程模型部署
254
+ * @param {*} data
255
+ * @returns
256
+ */
257
+export function processModelDeployApi (data) {
258
+  return request({
259
+    url: `${flowablePrefix}/V1//flowDefinitionManagement/publish`,
260
+    method: 'post',
261
+    requestType: 'json',
262
+    data: data
263
+  })
264
+}
265
+
266
+/**
267
+ * 导出
268
+ * @param {*} data
269
+ * @returns
270
+ */
271
+export function exportModelApi (data) {
272
+  return request({
273
+    url: `${flowablePrefix}/V1/flowDefinitionManagement/designList`,
274
+    method: 'post',
275
+    requestType: 'json',
276
+    data: data
277
+  })
278
+}
279
+
280
+/**
281
+ * 导入
282
+ * @param {*} data
283
+ * @returns
284
+ */
285
+export function importModelApi (data) {
286
+  return request({
287
+    url: `${flowablePrefix}/V1/flowDefinitionManagement/saveDisigenBach`,
288
+    method: 'post',
289
+    requestType: 'json',
290
+    data: data
291
+  })
292
+}
293
+
294
+
295
+/**
296
+ * 流程版本管理
297
+ * @param {*} data
298
+ * @returns
299
+ */
300
+export function versionCtlModelApi (data) {
301
+  return request({
302
+    url: `${flowablePrefix}/V1/flowDefinitionManagement/getModelHistListById`,
303
+    method: 'post',
304
+    requestType: 'json',
305
+    data: data
306
+  })
307
+}
308
+
309
+/**
310
+ * 删除历史流程模型
311
+ * @param {*} data
312
+ */
313
+export function deleteHiModelApi (data) {
314
+  return request({
315
+    url: `${flowablePrefix}/V1/flowDefinitionManagement/deleteModelInHis`,
316
+    method: 'post',
317
+    requestType: 'json',
318
+    data: data
319
+  })
320
+}
321
+
322
+/**
323
+ * 历史流程模型部署
324
+ * @param {*} data
325
+ * @returns
326
+ */
327
+export function deployHiModelApi (data) {
328
+  return request({
329
+    url: `${flowablePrefix}/V1/flowDefinitionManagement/publishInHistory`,
330
+    method: 'post',
331
+    requestType: 'json',
332
+    data: data
333
+  })
334
+}
335
+
336
+/**
337
+ * 查询子流程信息
338
+ * @param {*} data
339
+ * @returns
340
+ */
341
+export function queryCallActivityApi (data) {
342
+  return request({
343
+    url: `${flowablePrefix}/V1/flowDefinitionManagement/processDefQuery`,
344
+    method: 'post',
345
+    requestType: 'json',
346
+    data: data
347
+  })
348
+}
349
+
350
+/**
351
+ * 查询流程条件参数
352
+ * @param {*} data
353
+ * @returns
354
+ */
355
+export function queryBusinessParamApi (data) {
356
+  return request({
357
+    url: `${flowablePrefix}/V1/flowBusinessInteraction/getBusinessParamQuery`,
358
+    method: 'post',
359
+    requestType: 'json',
360
+    data: data
361
+  })
362
+}
363
+
364
+/**
365
+ * 判断流程模型编号是否存在
366
+ * @param {*} data
367
+ */
368
+export function procModelExistApi (data) {
369
+  return request({
370
+    url: `${flowablePrefix}/V1/flowDefinitionManagement/hasModel`,
371
+    method: 'post',
372
+    requestType: 'json',
373
+    data: data
374
+  })
375
+}

+ 18
- 0
ant-design-pro-vue3/src/api/public/genertorApi.js View File

@@ -0,0 +1,18 @@
1
+import request from '@/utils/request'
2
+import { systemPrefix } from '@/settings'
3
+
4
+/**
5
+ * 查询sql 结果集
6
+ * @param {*} data 
7
+ * @returns 
8
+ */
9
+export function querySqlResult(data){
10
+  return request({
11
+    url:`${systemPrefix}/system/generator/json/querySqlResult`,
12
+    method: 'post',
13
+    data: data,
14
+    headers: {
15
+      'Content-Type': 'application/json;charset=UTF-8'
16
+    }
17
+  })
18
+}

+ 47
- 0
ant-design-pro-vue3/src/api/public/process.js View File

@@ -0,0 +1,47 @@
1
+import request from '@/utils/request'
2
+import { flowablePrefix } from '@/settings'
3
+
4
+//查询已部署流程数据
5
+export function deployedQuery (data) {
6
+    return request({
7
+        url: `${flowablePrefix}/V1/flowDefinitionManagement/deployedQuery`,
8
+        method: 'post',
9
+        data: data,
10
+        requestType: 'json',
11
+    })
12
+}
13
+
14
+//流程定义启用
15
+export function processDefStart (data) {
16
+    return request({
17
+        url: `${flowablePrefix}/V1/flowDefinitionManagement/startusing`,
18
+        method: 'post',
19
+        data: data,
20
+        requestType: 'json',
21
+    })
22
+}
23
+
24
+//流程定义挂起
25
+export function processDefStop (data) {
26
+    return request({
27
+        url: `${flowablePrefix}/V1/flowDefinitionManagement/stopusing`,
28
+        method: 'post',
29
+        data: data,
30
+        requestType: 'json',
31
+    })
32
+}
33
+
34
+
35
+
36
+/**
37
+ * 流程实例查询
38
+ * @param {*} data 
39
+ */
40
+export function queryInstanceApi (data) {
41
+    return request({
42
+        url: `${flowablePrefix}/V1/flowInstancesManagement/query`,
43
+        method: 'post',
44
+        data: data,
45
+        requestType: 'json'
46
+    })
47
+}

+ 71
- 0
ant-design-pro-vue3/src/api/public/sequenceApi.js View File

@@ -0,0 +1,71 @@
1
+import request from '@/utils/request'
2
+import { systemPrefix } from '@/settings'
3
+
4
+/**
5
+ * 分页查询
6
+ * @param {*} data 
7
+ * @returns 
8
+ */
9
+export function queryPage (data) {
10
+
11
+  return request({
12
+    url: `${systemPrefix}/sys/ruledef/queryPageList`,
13
+    method: 'post',
14
+    data: data,
15
+    requestType: 'json',
16
+  })
17
+}
18
+
19
+/**
20
+ * 根据no 查询规则信息
21
+ * @param {} data 
22
+ * @returns 
23
+ */
24
+export function queryRuleByNo (data) {
25
+  return request({
26
+    url: `${systemPrefix}/sys/ruledef/queryRuleByNo`,
27
+    method: 'post',
28
+    data: data
29
+  })
30
+}
31
+
32
+/**
33
+ * 规则删除处理
34
+ * @param {*} data 
35
+ */
36
+export function removeRule (data) {
37
+
38
+  return request({
39
+    url: `${systemPrefix}/sys/ruledef/deleteByNo`,
40
+    method: 'post',
41
+    data: data
42
+  })
43
+}
44
+
45
+/**
46
+ * 更新规则信息
47
+ * @param {*} data 
48
+ */
49
+export function updateRuleDef (data) {
50
+
51
+  return request({
52
+    url: `${systemPrefix}/sys/ruledef/update`,
53
+    method: 'post',
54
+    data: data,
55
+    requestType: 'json',
56
+  })
57
+}
58
+
59
+/**
60
+ * 添加规则信息
61
+ * @param {*} data 
62
+ */
63
+export function addRuleDef (data) {
64
+
65
+  return request({
66
+    url: `${systemPrefix}/sys/ruledef/insert`,
67
+    method: 'post',
68
+    data: data,
69
+    requestType: 'json',
70
+  })
71
+}

+ 18
- 0
ant-design-pro-vue3/src/api/userLogSearch.js View File

@@ -0,0 +1,18 @@
1
+import settings from '@/settings'
2
+import request from '@/utils/request'
3
+const systemPrefix = settings.systemPrefix
4
+
5
+export function getUserOptionList(params) {
6
+  return request({
7
+    url: `${systemPrefix}/im/dhc/sys/automake/system/UserOptionListController.do`,
8
+    method:'post',
9
+    data:params
10
+  });
11
+}
12
+export function list(param) {
13
+  return request({
14
+    url: `${systemPrefix}/im/dhc/zz/automake/zzmanage/comitem_manager/ComItemListController.do`,
15
+    method:'post',
16
+    data:param
17
+  });
18
+}

+ 69
- 0
ant-design-pro-vue3/src/assets/background.svg View File

@@ -0,0 +1,69 @@
1
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+<svg width="1361px" height="609px" viewBox="0 0 1361 609" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+    <!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
4
+    <title>Group 21</title>
5
+    <desc>Created with Sketch.</desc>
6
+    <defs></defs>
7
+    <g id="Ant-Design-Pro-3.0" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
8
+        <g id="账户密码登录-校验" transform="translate(-79.000000, -82.000000)">
9
+            <g id="Group-21" transform="translate(77.000000, 73.000000)">
10
+                <g id="Group-18" opacity="0.8" transform="translate(74.901416, 569.699158) rotate(-7.000000) translate(-74.901416, -569.699158) translate(4.901416, 525.199158)">
11
+                    <ellipse id="Oval-11" fill="#CFDAE6" opacity="0.25" cx="63.5748792" cy="32.468367" rx="21.7830479" ry="21.766008"></ellipse>
12
+                    <ellipse id="Oval-3" fill="#CFDAE6" opacity="0.599999964" cx="5.98746479" cy="13.8668601" rx="5.2173913" ry="5.21330997"></ellipse>
13
+                    <path d="M38.1354514,88.3520215 C43.8984227,88.3520215 48.570234,83.6838647 48.570234,77.9254015 C48.570234,72.1669383 43.8984227,67.4987816 38.1354514,67.4987816 C32.3724801,67.4987816 27.7006688,72.1669383 27.7006688,77.9254015 C27.7006688,83.6838647 32.3724801,88.3520215 38.1354514,88.3520215 Z" id="Oval-3-Copy" fill="#CFDAE6" opacity="0.45"></path>
14
+                    <path d="M64.2775582,33.1704963 L119.185836,16.5654915" id="Path-12" stroke="#CFDAE6" stroke-width="1.73913043" stroke-linecap="round" stroke-linejoin="round"></path>
15
+                    <path d="M42.1431708,26.5002681 L7.71190162,14.5640702" id="Path-16" stroke="#E0B4B7" stroke-width="0.702678964" opacity="0.7" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="1.405357899873153,2.108036953469981"></path>
16
+                    <path d="M63.9262187,33.521561 L43.6721326,69.3250951" id="Path-15" stroke="#BACAD9" stroke-width="0.702678964" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="1.405357899873153,2.108036953469981"></path>
17
+                    <g id="Group-17" transform="translate(126.850922, 13.543654) rotate(30.000000) translate(-126.850922, -13.543654) translate(117.285705, 4.381889)" fill="#CFDAE6">
18
+                        <ellipse id="Oval-4" opacity="0.45" cx="9.13482653" cy="9.12768076" rx="9.13482653" ry="9.12768076"></ellipse>
19
+                        <path d="M18.2696531,18.2553615 C18.2696531,13.2142826 14.1798519,9.12768076 9.13482653,9.12768076 C4.08980114,9.12768076 0,13.2142826 0,18.2553615 L18.2696531,18.2553615 Z" id="Oval-4" transform="translate(9.134827, 13.691521) scale(-1, -1) translate(-9.134827, -13.691521) "></path>
20
+                    </g>
21
+                </g>
22
+                <g id="Group-14" transform="translate(216.294700, 123.725600) rotate(-5.000000) translate(-216.294700, -123.725600) translate(106.294700, 35.225600)">
23
+                    <ellipse id="Oval-2" fill="#CFDAE6" opacity="0.25" cx="29.1176471" cy="29.1402439" rx="29.1176471" ry="29.1402439"></ellipse>
24
+                    <ellipse id="Oval-2" fill="#CFDAE6" opacity="0.3" cx="29.1176471" cy="29.1402439" rx="21.5686275" ry="21.5853659"></ellipse>
25
+                    <ellipse id="Oval-2-Copy" stroke="#CFDAE6" opacity="0.4" cx="179.019608" cy="138.146341" rx="23.7254902" ry="23.7439024"></ellipse>
26
+                    <ellipse id="Oval-2" fill="#BACAD9" opacity="0.5" cx="29.1176471" cy="29.1402439" rx="10.7843137" ry="10.7926829"></ellipse>
27
+                    <path d="M29.1176471,39.9329268 L29.1176471,18.347561 C23.1616351,18.347561 18.3333333,23.1796097 18.3333333,29.1402439 C18.3333333,35.1008781 23.1616351,39.9329268 29.1176471,39.9329268 Z" id="Oval-2" fill="#BACAD9"></path>
28
+                    <g id="Group-9" opacity="0.45" transform="translate(172.000000, 131.000000)" fill="#E6A1A6">
29
+                        <ellipse id="Oval-2-Copy-2" cx="7.01960784" cy="7.14634146" rx="6.47058824" ry="6.47560976"></ellipse>
30
+                        <path d="M0.549019608,13.6219512 C4.12262681,13.6219512 7.01960784,10.722722 7.01960784,7.14634146 C7.01960784,3.56996095 4.12262681,0.670731707 0.549019608,0.670731707 L0.549019608,13.6219512 Z" id="Oval-2-Copy-2" transform="translate(3.784314, 7.146341) scale(-1, 1) translate(-3.784314, -7.146341) "></path>
31
+                    </g>
32
+                    <ellipse id="Oval-10" fill="#CFDAE6" cx="218.382353" cy="138.685976" rx="1.61764706" ry="1.61890244"></ellipse>
33
+                    <ellipse id="Oval-10-Copy-2" fill="#E0B4B7" opacity="0.35" cx="179.558824" cy="175.381098" rx="1.61764706" ry="1.61890244"></ellipse>
34
+                    <ellipse id="Oval-10-Copy" fill="#E0B4B7" opacity="0.35" cx="180.098039" cy="102.530488" rx="2.15686275" ry="2.15853659"></ellipse>
35
+                    <path d="M28.9985381,29.9671598 L171.151018,132.876024" id="Path-11" stroke="#CFDAE6" opacity="0.8"></path>
36
+                </g>
37
+                <g id="Group-10" opacity="0.799999952" transform="translate(1054.100635, 36.659317) rotate(-11.000000) translate(-1054.100635, -36.659317) translate(1026.600635, 4.659317)">
38
+                    <ellipse id="Oval-7" stroke="#CFDAE6" stroke-width="0.941176471" cx="43.8135593" cy="32" rx="11.1864407" ry="11.2941176"></ellipse>
39
+                    <g id="Group-12" transform="translate(34.596774, 23.111111)" fill="#BACAD9">
40
+                        <ellipse id="Oval-7" opacity="0.45" cx="9.18534718" cy="8.88888889" rx="8.47457627" ry="8.55614973"></ellipse>
41
+                        <path d="M9.18534718,17.4450386 C13.8657264,17.4450386 17.6599235,13.6143199 17.6599235,8.88888889 C17.6599235,4.16345787 13.8657264,0.332739156 9.18534718,0.332739156 L9.18534718,17.4450386 Z" id="Oval-7"></path>
42
+                    </g>
43
+                    <path d="M34.6597385,24.809694 L5.71666084,4.76878945" id="Path-2" stroke="#CFDAE6" stroke-width="0.941176471"></path>
44
+                    <ellipse id="Oval" stroke="#CFDAE6" stroke-width="0.941176471" cx="3.26271186" cy="3.29411765" rx="3.26271186" ry="3.29411765"></ellipse>
45
+                    <ellipse id="Oval-Copy" fill="#F7E1AD" cx="2.79661017" cy="61.1764706" rx="2.79661017" ry="2.82352941"></ellipse>
46
+                    <path d="M34.6312443,39.2922712 L5.06366663,59.785082" id="Path-10" stroke="#CFDAE6" stroke-width="0.941176471"></path>
47
+                </g>
48
+                <g id="Group-19" opacity="0.33" transform="translate(1282.537219, 446.502867) rotate(-10.000000) translate(-1282.537219, -446.502867) translate(1142.537219, 327.502867)">
49
+                    <g id="Group-17" transform="translate(141.333539, 104.502742) rotate(275.000000) translate(-141.333539, -104.502742) translate(129.333539, 92.502742)" fill="#BACAD9">
50
+                        <circle id="Oval-4" opacity="0.45" cx="11.6666667" cy="11.6666667" r="11.6666667"></circle>
51
+                        <path d="M23.3333333,23.3333333 C23.3333333,16.8900113 18.1099887,11.6666667 11.6666667,11.6666667 C5.22334459,11.6666667 0,16.8900113 0,23.3333333 L23.3333333,23.3333333 Z" id="Oval-4" transform="translate(11.666667, 17.500000) scale(-1, -1) translate(-11.666667, -17.500000) "></path>
52
+                    </g>
53
+                    <circle id="Oval-5-Copy-6" fill="#CFDAE6" cx="201.833333" cy="87.5" r="5.83333333"></circle>
54
+                    <path d="M143.5,88.8126685 L155.070501,17.6038544" id="Path-17" stroke="#BACAD9" stroke-width="1.16666667"></path>
55
+                    <path d="M17.5,37.3333333 L127.466252,97.6449735" id="Path-18" stroke="#BACAD9" stroke-width="1.16666667"></path>
56
+                    <polyline id="Path-19" stroke="#CFDAE6" stroke-width="1.16666667" points="143.902597 120.302281 174.935455 231.571342 38.5 147.510847 126.366941 110.833333"></polyline>
57
+                    <path d="M159.833333,99.7453842 L195.416667,89.25" id="Path-20" stroke="#E0B4B7" stroke-width="1.16666667" opacity="0.6"></path>
58
+                    <path d="M205.333333,82.1372105 L238.719406,36.1666667" id="Path-24" stroke="#BACAD9" stroke-width="1.16666667"></path>
59
+                    <path d="M266.723424,132.231988 L207.083333,90.4166667" id="Path-25" stroke="#CFDAE6" stroke-width="1.16666667"></path>
60
+                    <circle id="Oval-5" fill="#C1D1E0" cx="156.916667" cy="8.75" r="8.75"></circle>
61
+                    <circle id="Oval-5-Copy-3" fill="#C1D1E0" cx="39.0833333" cy="148.75" r="5.25"></circle>
62
+                    <circle id="Oval-5-Copy-2" fill-opacity="0.6" fill="#D1DEED" cx="8.75" cy="33.25" r="8.75"></circle>
63
+                    <circle id="Oval-5-Copy-4" fill-opacity="0.6" fill="#D1DEED" cx="243.833333" cy="30.3333333" r="5.83333333"></circle>
64
+                    <circle id="Oval-5-Copy-5" fill="#E0B4B7" cx="175.583333" cy="232.75" r="5.25"></circle>
65
+                </g>
66
+            </g>
67
+        </g>
68
+    </g>
69
+</svg>

BIN
ant-design-pro-vue3/src/assets/dhc.gif View File


+ 1
- 0
ant-design-pro-vue3/src/assets/icons/battery.svg View File

@@ -0,0 +1 @@
1
+<svg  fill="currentColor" t="1641369435663" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14593" data-darkreader-inline-fill="" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M173.037714 768h573.897143c55.405714 0 102.070857-5.174857 135.131429-38.235429 33.060571-33.060571 37.595429-79.067429 37.595428-134.491428v-166.217143c0-55.424-4.534857-101.76-37.595428-134.491429C848.694857 261.485714 802.340571 256 746.934857 256H172.068571c-54.436571 0-101.101714 5.504-134.162285 38.564571C4.864 327.606857 0 373.632 0 428.068571v167.204572c0 55.405714 4.864 101.76 37.906286 134.491428C70.966857 762.825143 117.632 768 173.037714 768z m-9.069714-52.169143c-33.371429 0-68.388571-4.534857-87.808-23.972571-19.785143-19.785143-23.990857-54.125714-23.990857-87.497143V420.937143c0-34.029714 4.205714-69.028571 23.661714-88.484572 19.748571-19.748571 55.094857-24.301714 89.106286-24.301714h591.067428c33.060571 0 68.388571 4.864 87.826286 24.32 19.748571 19.748571 23.661714 54.107429 23.661714 87.478857v184.393143c0 33.371429-4.224 67.712-23.661714 87.497143-19.437714 19.748571-54.765714 23.954286-87.826286 23.954286z m-6.473143-44.068571h605.001143c23.972571 0 37.266286-3.254857 47.634286-13.293715 10.368-10.368 13.275429-23.972571 13.275428-47.634285V413.494857c0-23.990857-3.236571-37.266286-13.275428-47.634286-10.368-10.368-23.661714-13.293714-47.634286-13.293714H157.494857c-23.990857 0-37.266286 2.925714-47.634286 13.293714-10.368 10.368-13.293714 23.643429-13.293714 47.634286v197.339429c0 23.661714 2.925714 37.266286 13.293714 47.634285 10.368 10.057143 23.643429 13.293714 47.634286 13.293715z m806.564572-77.787429c25.6-1.609143 59.940571-34.340571 59.940571-83.931428 0-49.243429-34.358857-81.974857-59.940571-83.602286z" p-id="14594"></path></svg>

+ 1
- 0
ant-design-pro-vue3/src/assets/icons/batteryCharge.svg View File

@@ -0,0 +1 @@
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  fill="currentColor" t="1641369582138" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19418" data-darkreader-inline-fill="" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M458.666667 256H725.333333a128 128 0 0 1 127.786667 120.490667L853.333333 384v42.666667l42.666667 0.768a42.666667 42.666667 0 0 1 42.368 37.504l0.341333 5.12v85.333333a42.666667 42.666667 0 0 1-36.949333 42.325333l-5.717333 0.384L853.333333 597.333333v42.666667a128 128 0 0 1-120.490666 127.786667L725.333333 768H341.12a32 32 0 0 1-31.701333-27.648l-0.298667-4.352v-192a32 32 0 0 1 27.690667-31.701333L341.12 512h26.794667c30.549333 0 55.637333-23.296 58.453333-53.12l0.298667-5.632V288a32 32 0 0 1 27.648-31.701333L458.666667 256H725.333333h-266.666666zM283.52 170.965333L287.872 170.666667a32 32 0 0 1 31.701333 27.648l0.298667 4.352L319.829333 256h32.341334a32 32 0 0 1 32 32v106.624a74.666667 74.666667 0 0 1-74.666667 74.666667l-42.794667-0.042667v266.453333a32 32 0 0 1-27.605333 31.701334l-4.352 0.298666a32 32 0 0 1-31.701333-27.648l-0.298667-4.352v-266.453333H160A74.666667 74.666667 0 0 1 85.333333 394.624V288A32 32 0 0 1 117.333333 256h32.042667V202.666667a32 32 0 0 1 27.648-31.701334L181.376 170.666667a32 32 0 0 1 31.701333 27.648l0.298667 4.352V256h42.453333V202.666667a32 32 0 0 1 27.733334-31.701334l4.266666-0.298666-4.266666 0.298666z" p-id="19419"></path></svg>

+ 1
- 0
ant-design-pro-vue3/src/assets/icons/bx-analyse.svg View File

@@ -0,0 +1 @@
1
+<svg  fill="currentColor" t="1551058675966" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7872" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M85.333333 512h85.333334a340.736 340.736 0 0 1 99.712-241.621333 337.493333 337.493333 0 0 1 108.458666-72.96 346.453333 346.453333 0 0 1 261.546667-1.749334A106.154667 106.154667 0 0 0 746.666667 298.666667C805.802667 298.666667 853.333333 251.136 853.333333 192S805.802667 85.333333 746.666667 85.333333c-29.397333 0-55.978667 11.776-75.221334 30.933334-103.722667-41.514667-222.848-40.874667-325.76 2.517333a423.594667 423.594667 0 0 0-135.68 91.264 423.253333 423.253333 0 0 0-91.306666 135.637333A426.88 426.88 0 0 0 85.333333 512z m741.248 133.205333c-17.109333 40.618667-41.685333 77.141333-72.96 108.416s-67.797333 55.850667-108.458666 72.96a346.453333 346.453333 0 0 1-261.546667 1.749334A106.154667 106.154667 0 0 0 277.333333 725.333333C218.197333 725.333333 170.666667 772.864 170.666667 832S218.197333 938.666667 277.333333 938.666667c29.397333 0 55.978667-11.776 75.221334-30.933334A425.173333 425.173333 0 0 0 512 938.666667a425.941333 425.941333 0 0 0 393.258667-260.352A426.325333 426.325333 0 0 0 938.666667 512h-85.333334a341.034667 341.034667 0 0 1-26.752 133.205333z" p-id="7873"></path><path d="M512 318.378667c-106.752 0-193.621333 86.869333-193.621333 193.621333S405.248 705.621333 512 705.621333s193.621333-86.869333 193.621333-193.621333S618.752 318.378667 512 318.378667z m0 301.909333c-59.690667 0-108.288-48.597333-108.288-108.288S452.309333 403.712 512 403.712s108.288 48.597333 108.288 108.288-48.597333 108.288-108.288 108.288z" p-id="7874"></path></svg>

+ 29
- 0
ant-design-pro-vue3/src/assets/icons/logo.svg View File

@@ -0,0 +1,29 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<svg viewBox="0 0 128 128" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+  <!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->
4
+  <title>Vue</title>
5
+  <desc>Created with Sketch.</desc>
6
+  <defs>
7
+    <linearGradient x1="69.644116%" y1="0%" x2="69.644116%" y2="100%" id="linearGradient-1">
8
+      <stop stop-color="#29CDFF" offset="0%"></stop>
9
+      <stop stop-color="#148EFF" offset="37.8600687%"></stop>
10
+      <stop stop-color="#0A60FF" offset="100%"></stop>
11
+    </linearGradient>
12
+    <linearGradient x1="-19.8191553%" y1="-36.7931464%" x2="138.57919%" y2="157.637507%" id="linearGradient-2">
13
+      <stop stop-color="#29CDFF" offset="0%"></stop>
14
+      <stop stop-color="#0F78FF" offset="100%"></stop>
15
+    </linearGradient>
16
+    <linearGradient x1="68.1279872%" y1="-35.6905737%" x2="30.4400914%" y2="114.942679%" id="linearGradient-3">
17
+      <stop stop-color="#FA8E7D" offset="0%"></stop>
18
+      <stop stop-color="#F74A5C" offset="51.2635191%"></stop>
19
+      <stop stop-color="#F51D2C" offset="100%"></stop>
20
+    </linearGradient>
21
+  </defs>
22
+  <g id="Vue" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
23
+    <g id="Group" transform="translate(19.000000, 9.000000)">
24
+      <path d="M89.96,90.48 C78.58,93.48 68.33,83.36 67.62,82.48 L46.6604487,62.2292258 C45.5023849,61.1103236 44.8426845,59.5728835 44.8296987,57.9626396 L44.5035564,17.5209948 C44.4948861,16.4458744 44.0537714,15.4195095 43.2796864,14.6733517 L29.6459999,1.53153737 C28.055475,-0.00160504005 25.5232423,0.0449126588 23.9900999,1.63543756 C23.2715121,2.38092066 22.87,3.37600834 22.87,4.41143746 L22.87,64.3864751 C22.87,67.0807891 23.9572233,69.6611067 25.885409,71.5429748 L63.6004615,108.352061 C65.9466323,110.641873 69.6963584,110.624605 72.0213403,108.313281" id="Path-Copy" fill="url(#linearGradient-1)" fill-rule="nonzero" transform="translate(56.415000, 54.831157) scale(-1, 1) translate(-56.415000, -54.831157) "></path>
25
+      <path d="M68,90.1163122 C56.62,93.1163122 45.46,83.36 44.75,82.48 L23.7904487,62.2292258 C22.6323849,61.1103236 21.9726845,59.5728835 21.9596987,57.9626396 L21.6335564,17.5209948 C21.6248861,16.4458744 21.1837714,15.4195095 20.4096864,14.6733517 L6.7759999,1.53153737 C5.185475,-0.00160504005 2.65324232,0.0449126588 1.12009991,1.63543756 C0.401512125,2.38092066 3.90211878e-13,3.37600834 3.90798505e-13,4.41143746 L3.94351218e-13,64.3864751 C3.94681177e-13,67.0807891 1.08722326,69.6611067 3.01540903,71.5429748 L40.7807092,108.401101 C43.1069304,110.671444 46.8180151,110.676525 49.1504445,108.412561" id="Path" fill="url(#linearGradient-2)" fill-rule="nonzero"></path>
26
+      <path d="M43.2983488,19.0991931 L27.5566079,3.88246244 C26.7624281,3.11476967 26.7409561,1.84862177 27.5086488,1.05444194 C27.8854826,0.664606611 28.4044438,0.444472651 28.9466386,0.444472651 L60.3925021,0.444472651 C61.4970716,0.444472651 62.3925021,1.33990315 62.3925021,2.44447265 C62.3925021,2.9858375 62.1730396,3.50407742 61.7842512,3.88079942 L46.0801285,19.0975301 C45.3051579,19.8484488 44.0742167,19.8491847 43.2983488,19.0991931 Z" id="Path" fill="url(#linearGradient-3)"></path>
27
+    </g>
28
+  </g>
29
+</svg>

+ 174
- 0
ant-design-pro-vue3/src/components/ColorPicker/color.ts View File

@@ -0,0 +1,174 @@
1
+import tinycolor, { Instance } from "tinycolor2";
2
+import { isDef, isNull } from "@aesoper/normal-utils";
3
+import debounce from "lodash.debounce";
4
+
5
+export interface Alpha {
6
+  a: number;
7
+}
8
+
9
+export interface PRGB {
10
+  r: string;
11
+  g: string;
12
+  b: string;
13
+}
14
+
15
+export interface PRGBA extends PRGB, Alpha {}
16
+
17
+export interface RGB {
18
+  r: number;
19
+  g: number;
20
+  b: number;
21
+}
22
+
23
+export interface RGBA extends RGB, Alpha {}
24
+
25
+export interface HSL {
26
+  h: number;
27
+  s: number;
28
+  l: number;
29
+}
30
+
31
+export interface HSLA extends HSL, Alpha {}
32
+
33
+export interface HSV {
34
+  h: number;
35
+  s: number;
36
+  v: number;
37
+}
38
+
39
+export interface HSVA extends HSV {
40
+  a: number;
41
+}
42
+
43
+export interface ColorInstance {
44
+  hex?: string;
45
+  hex8?: string;
46
+  hsl?: HSLA;
47
+  hsv?: HSVA;
48
+  rgb?: RGBA;
49
+  alpha?: number;
50
+  source?: string;
51
+  oldHue?: number;
52
+}
53
+
54
+export interface ColorAttrs {
55
+  hex: string;
56
+  hex8: string;
57
+  hsl: HSLA;
58
+  hsv: HSVA;
59
+  rgb: RGBA;
60
+  alpha: number;
61
+  source: string;
62
+  oldHue: number;
63
+}
64
+
65
+type ColorInputWithoutInstance =
66
+  | string
67
+  | PRGB
68
+  | PRGBA
69
+  | RGB
70
+  | RGBA
71
+  | HSL
72
+  | HSLA
73
+  | HSV
74
+  | HSVA;
75
+
76
+export type ColorInput = ColorInstance | ColorInputWithoutInstance;
77
+
78
+export type ColorFormat =
79
+  | "rgb"
80
+  | "prgb"
81
+  | "hex"
82
+  | "hex6"
83
+  | "hex3"
84
+  | "hex4"
85
+  | "hex8"
86
+  | "name"
87
+  | "hsl"
88
+  | "hsv";
89
+
90
+export class Color {
91
+  protected instance: Instance = tinycolor("#000000");
92
+
93
+  parseColor(data: any, oldHue?: number): ColorAttrs {
94
+    if (isDef(data) || isNull(data)) {
95
+      data = "#000000";
96
+    }
97
+
98
+    if (data && data.hsl) {
99
+      this.instance = tinycolor(data.hsl);
100
+    } else if (data && data.hex && data.hex.length > 0) {
101
+      this.instance = tinycolor(data.hex);
102
+    } else if (data && data.hex8 && data.hex8.length > 0) {
103
+      this.instance = tinycolor(data.hex8);
104
+    } else if (data && data.hsv) {
105
+      this.instance = tinycolor(data.hsv);
106
+    } else if (data && data.rgba) {
107
+      this.instance = tinycolor(data.rgba);
108
+    } else if (data && data.rgb) {
109
+      this.instance = tinycolor(data.rgb);
110
+    } else {
111
+      this.instance = tinycolor(data);
112
+    }
113
+
114
+    const hsl = this.instance.toHsl();
115
+    const hsv = this.instance.toHsv();
116
+    const rgb = this.instance.toRgb();
117
+
118
+    if (hsl.s === 0) {
119
+      hsv.h = hsl.h = data.h || (data.hsl && data.hsl.h) || oldHue || 0;
120
+    }
121
+
122
+    if (hsv.h === 0 || hsl.h === 0) {
123
+      hsv.h = hsl.h = data.h || oldHue || data.oldHue || 0;
124
+    }
125
+
126
+    if (hsv.v === 0) {
127
+      hsv.s = (data.s && data.s) || (data.hsv && data.hsv.s) || 0;
128
+    }
129
+
130
+    return {
131
+      hsl: {
132
+        h: Math.round(hsl.h),
133
+        s: Number(Math.round(hsl.s * 100).toFixed(2)) / 100,
134
+        l: Number(Math.round(hsl.l * 100).toFixed(2)) / 100,
135
+        a: Math.round(hsl.a * 100) / 100
136
+      },
137
+      hex: this.instance.toHexString().toUpperCase(),
138
+      hex8: this.instance.toHex8String().toUpperCase(),
139
+      rgb: {
140
+        r: Math.round(rgb.r),
141
+        g: Math.round(rgb.g),
142
+        b: Math.round(rgb.b),
143
+        a: Math.round(rgb.a * 100) / 100
144
+      },
145
+      hsv: {
146
+        h: Math.round(hsv.h),
147
+        s: Math.round(hsv.s * 100) / 100,
148
+        v: Math.round(hsv.v * 100) / 100,
149
+        a: Math.round(hsl.a * 100) / 100
150
+      },
151
+      oldHue: Math.round(data.h || oldHue || hsl.h),
152
+      source: data.source,
153
+      alpha: Math.round((data.a || this.instance.getAlpha()) * 100) / 100
154
+    };
155
+  }
156
+
157
+  format(format: ColorFormat): string {
158
+    return this.instance.toString(format);
159
+  }
160
+}
161
+
162
+export const debounceFn = debounce(
163
+  (fn: Function) => {
164
+    fn();
165
+  },
166
+  200,
167
+  {
168
+    leading: true,
169
+    trailing: false
170
+  }
171
+);
172
+
173
+export const MAX_STORAGE_LENGTH = 8;
174
+export const STORAGE_COLOR_KEY = "colorList";

+ 255
- 0
ant-design-pro-vue3/src/components/ColorPicker/common/Alpha.vue View File

@@ -0,0 +1,255 @@
1
+<template>
2
+  <div class="bee-alpha-slider transparent" :class="{
3
+    'is-vertical': vertical,
4
+    'small-alpha-slider': size === 'small' && !vertical
5
+  }">
6
+    <div class="bee-alpha-slider__bar" ref="barEle" :style="gradientColor" @click="onSliderClick">
7
+      <div class="bee-alpha-slider__bar-pointer" :class="{ 'small-bar': size === 'small' && !vertical }" ref="cursorEle"
8
+        :style="{
9
+          left: cursorLeft + 'px',
10
+          top: cursorTop + 'px'
11
+        }">
12
+        <div class="bee-alpha-slider__bar-handle" :class="{ vertical: vertical }"></div>
13
+      </div>
14
+    </div>
15
+  </div>
16
+</template>
17
+
18
+<script lang="ts" setup name="Alpha">
19
+import {
20
+  ref,
21
+  computed,
22
+  watch,
23
+  onMounted,
24
+  nextTick
25
+} from "vue";
26
+import { DOMUtils, DragEventOptions } from "@aesoper/normal-utils";
27
+import tinycolor from "tinycolor2";
28
+
29
+const props = defineProps({
30
+  color: {
31
+    type: String,
32
+    default: "#000000"
33
+  },
34
+  vertical: {
35
+    type: Boolean,
36
+    default: false
37
+  },
38
+  size: {
39
+    type: String,
40
+    default: "default"
41
+  },
42
+  alpha: {
43
+    type: Number,
44
+    default: 1,
45
+    validator: (value: number) => {
46
+      return value >= 0 && value <= 1;
47
+    }
48
+  }
49
+})
50
+const emit = defineEmits(["update:alpha", "change"])
51
+const barEle = ref<HTMLElement | null>(null);
52
+const cursorEle = ref<HTMLElement | null>(null);
53
+
54
+const cursorLeft = ref(0);
55
+const cursorTop = ref(0);
56
+
57
+const currentAlpha = ref(props.alpha);
58
+
59
+const gradientColor = computed(() => {
60
+  const rgb = tinycolor(props.color)
61
+    .setAlpha(1)
62
+    .toRgbString();
63
+  const alphaGgb = tinycolor(props.color)
64
+    .setAlpha(0)
65
+    .toRgbString();
66
+
67
+  let deg = "right";
68
+  if (props.vertical) {
69
+    deg = "bottom";
70
+  }
71
+  return {
72
+    background: `linear-gradient(to ${deg}, ${alphaGgb}, ${rgb}`
73
+  };
74
+});
75
+
76
+const getCursorLeft = () => {
77
+  if (props.vertical) return 0;
78
+  if (barEle.value && cursorEle.value) {
79
+    const alpha = currentAlpha.value;
80
+    const rect = barEle.value?.getBoundingClientRect();
81
+
82
+    return Math.round(
83
+      alpha * (rect.width - cursorEle.value?.offsetWidth) +
84
+      cursorEle.value?.offsetWidth / 2
85
+    );
86
+  }
87
+
88
+  return 0;
89
+};
90
+
91
+const getCursorTop = () => {
92
+  if (!props.vertical) return 0;
93
+  if (barEle.value && cursorEle.value) {
94
+    const alpha = currentAlpha.value;
95
+    const rect = barEle.value?.getBoundingClientRect();
96
+
97
+    return Math.round(
98
+      alpha * (rect.height - cursorEle.value.offsetHeight) +
99
+      cursorEle.value.offsetHeight / 2
100
+    );
101
+  }
102
+  return 0;
103
+};
104
+
105
+const updatePosition = () => {
106
+  cursorLeft.value = getCursorLeft();
107
+  cursorTop.value = getCursorTop();
108
+};
109
+
110
+const onDragSlider = (event: MouseEvent) => {
111
+  event.stopPropagation();
112
+  if (barEle.value && cursorEle.value) {
113
+    const rect = barEle.value?.getBoundingClientRect();
114
+
115
+    if (!props.vertical) {
116
+      let left = event.clientX - rect.left;
117
+      left = Math.max(cursorEle.value.offsetWidth / 2, left);
118
+      left = Math.min(left, rect.width - cursorEle.value.offsetWidth / 2);
119
+
120
+      currentAlpha.value =
121
+        Math.round(
122
+          ((left - cursorEle.value.offsetWidth / 2) /
123
+            (rect.width - cursorEle.value.offsetWidth)) *
124
+          100
125
+        ) / 100;
126
+    } else {
127
+      let top = event.clientY - rect.top;
128
+      top = Math.max(cursorEle.value.offsetHeight / 2, top);
129
+      top = Math.min(top, rect.height - cursorEle.value.offsetHeight / 2);
130
+
131
+      currentAlpha.value =
132
+        1 -
133
+        Math.round(
134
+          ((top - cursorEle.value.offsetHeight / 2) /
135
+            (rect.height - cursorEle.value.offsetHeight)) *
136
+          100
137
+        ) /
138
+        100;
139
+    }
140
+
141
+    emit("update:alpha", currentAlpha.value);
142
+    emit("change", currentAlpha.value);
143
+  }
144
+};
145
+
146
+const onSliderClick = (event: MouseEvent) => {
147
+  const target = event.target;
148
+
149
+  if (target !== barEle.value) {
150
+    onDragSlider(event);
151
+  }
152
+};
153
+
154
+watch(
155
+  () => props.alpha,
156
+  () => {
157
+    currentAlpha.value = props.alpha;
158
+  }
159
+);
160
+
161
+watch(
162
+  () => currentAlpha.value,
163
+  () => {
164
+    updatePosition();
165
+  }
166
+);
167
+
168
+onMounted(() => {
169
+  nextTick(() => {
170
+    const dragConfig: DragEventOptions = {
171
+      drag: (event: Event) => {
172
+        onDragSlider(event as MouseEvent);
173
+      },
174
+      end: (event: Event) => {
175
+        onDragSlider(event as MouseEvent);
176
+      }
177
+    };
178
+
179
+    if (barEle.value && cursorEle.value) {
180
+      DOMUtils.triggerDragEvent(barEle.value, dragConfig);
181
+      DOMUtils.triggerDragEvent(barEle.value, dragConfig);
182
+    }
183
+  });
184
+  updatePosition();
185
+});
186
+</script>
187
+
188
+<style lang="scss" scoped>
189
+.small-alpha-slider {
190
+  height: 10px !important;
191
+
192
+  .small-bar {
193
+    height: 10px !important;
194
+    width: 10px !important;
195
+
196
+    div {
197
+      width: 12px !important;
198
+      height: 12px !important;
199
+      border-radius: 5px !important;
200
+      transform: translate(-6px, -2px);
201
+      margin-top: 1px !important;
202
+    }
203
+  }
204
+}
205
+
206
+.bee-alpha-slider {
207
+  position: relative;
208
+  margin-bottom: 15px;
209
+  width: 100%;
210
+  height: 14px;
211
+  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.08);
212
+  border-radius: 15px;
213
+
214
+  &.is-vertical {
215
+    width: 14px;
216
+    height: 100%;
217
+    display: inline-block;
218
+    transform: rotate(180deg);
219
+  }
220
+
221
+  &.transparent {
222
+    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
223
+    background-repeat: repeat;
224
+  }
225
+
226
+  &__bar {
227
+    position: relative;
228
+    width: 100%;
229
+    height: 100%;
230
+    border-radius: 15px;
231
+
232
+    &-pointer {
233
+      position: absolute;
234
+      width: 14px;
235
+      height: 14px;
236
+    }
237
+
238
+    &-handle {
239
+      width: 14px;
240
+      height: 14px;
241
+      border-radius: 6px;
242
+      transform: translate(-7px, -2px);
243
+      background-color: #f8f8f8;
244
+      margin-top: 2px;
245
+      box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37);
246
+      cursor: pointer;
247
+
248
+      &.vertical {
249
+        transform: translate(0px, -7px);
250
+        margin-top: 0;
251
+      }
252
+    }
253
+  }
254
+}
255
+</style>

+ 85
- 0
ant-design-pro-vue3/src/components/ColorPicker/common/History.vue View File

@@ -0,0 +1,85 @@
1
+<template>
2
+  <div class="bee-colorPicker__record">
3
+    <div class="color-list">
4
+      <div class="color-item transparent" :class="{ 'color-item__round': round }" v-for="(v, i) in colorList" :key="i"
5
+        @click="onClickRecord(v)">
6
+        <div class="color-item__display" :style="{ backgroundColor: v }"></div>
7
+      </div>
8
+    </div>
9
+  </div>
10
+</template>
11
+
12
+<script lang="ts" setup name="History">
13
+import { PropType } from "vue";
14
+const props = defineProps({
15
+  colorList: {
16
+    type: Array as PropType<string[]>,
17
+    default: () => {
18
+      return [];
19
+    }
20
+  },
21
+  round: {
22
+    type: Boolean,
23
+    default: true
24
+  }
25
+})
26
+const emit = defineEmits(["change"])
27
+const onClickRecord = (color: string) => {
28
+  emit("change", color);
29
+};
30
+</script>
31
+
32
+<style lang="scss" scoped>
33
+.bee-colorPicker__record {
34
+  display: flex;
35
+  align-items: center;
36
+  margin-top: 20px;
37
+
38
+  .text {
39
+    width: 48px;
40
+    margin-right: 10px;
41
+    text-align: right;
42
+    font-size: 12px;
43
+    color: #666;
44
+  }
45
+
46
+  .color-list {
47
+    width: auto;
48
+    display: flex;
49
+    position: relative;
50
+    margin: 0;
51
+
52
+    .color-item {
53
+      position: relative;
54
+      width: 25px;
55
+      height: 25px;
56
+      cursor: pointer;
57
+      overflow: hidden;
58
+      display: inline-block;
59
+      vertical-align: middle;
60
+      margin-right: 1px;
61
+      box-shadow: 3px 0 5px rgba(0, 0, 0, 0.08);
62
+
63
+      &__round {
64
+        border-radius: 50%;
65
+      }
66
+
67
+      &.transparent {
68
+        background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
69
+        background-repeat: repeat;
70
+      }
71
+
72
+      &:hover {
73
+        transform: scale(1.2);
74
+        z-index: 299;
75
+        transition: transform 0.2s;
76
+      }
77
+
78
+      &__display {
79
+        width: 100%;
80
+        height: 100%;
81
+      }
82
+    }
83
+  }
84
+}
85
+</style>

+ 253
- 0
ant-design-pro-vue3/src/components/ColorPicker/common/Hue.vue View File

@@ -0,0 +1,253 @@
1
+<template>
2
+  <div class="bee-hue-colorPicker transparent" :class="{
3
+    'is-vertical': vertical,
4
+    'small-hue-slider': size === 'small' && !vertical
5
+  }">
6
+    <div class="bee-hue-colorPicker__inner" ref="bar" :style="linearGradient">
7
+      <div class="bee-hue-colorPicker__inner-pointer" :class="{ 'small-bar': size === 'small' && !vertical }"
8
+        ref="barHandle" :style="{
9
+          left: handleLeft + 'px',
10
+          top: handleTop + 'px'
11
+        }">
12
+        <div class="bee-hue-colorPicker__inner-handle" :class="{ vertical: vertical }"></div>
13
+      </div>
14
+    </div>
15
+  </div>
16
+</template>
17
+
18
+<script lang="ts" setup name="Hue">
19
+import {
20
+  computed,
21
+  nextTick,
22
+  onMounted,
23
+  ref,
24
+  watch
25
+} from "vue";
26
+
27
+import { DOMUtils, DragEventOptions } from "@aesoper/normal-utils";
28
+
29
+const bg =
30
+  "-webkit-linear-gradient(left, rgb(255, 0, 0) 0%, rgb(255, 255, 0) 16.66%, rgb(0, 255, 0) 33.33%, rgb(0, 255, 255) 50%, rgb(0, 0, 255) 66.66%, rgb(255, 0, 255) 83.33%, rgb(255, 0, 0) 100%)";
31
+const verticalBg =
32
+  "-webkit-linear-gradient(bottom, rgb(255, 0, 0) 0%, rgb(255, 255, 0) 16.66%, rgb(0, 255, 0) 33.33%, rgb(0, 255, 255) 50%, rgb(0, 0, 255) 66.66%, rgb(255, 0, 255) 83.33%, rgb(255, 0, 0) 100%)";
33
+
34
+const props = defineProps({
35
+  vertical: {
36
+    type: Boolean,
37
+    default: false
38
+  },
39
+  size: {
40
+    type: String,
41
+    default: "default"
42
+  },
43
+  hue: {
44
+    type: Number,
45
+    default: 0,
46
+    validator: (value: number) => {
47
+      return value >= 0 && value <= 360;
48
+    }
49
+  }
50
+})
51
+
52
+const emit = defineEmits(["update:hue", "change"])
53
+const bar = ref<HTMLElement | null>(null);
54
+const barHandle = ref<HTMLElement | null>(null);
55
+
56
+const handleLeft = ref(0);
57
+const handleTop = ref(0);
58
+
59
+const currentHue = ref(props.hue);
60
+
61
+const linearGradient = computed(() => {
62
+  return {
63
+    background: props.vertical ? verticalBg : bg
64
+  };
65
+});
66
+
67
+const getBarLeftPosition = () => {
68
+  if (props.vertical) return 0;
69
+  if (bar.value && barHandle.value) {
70
+    const rect = bar.value?.getBoundingClientRect();
71
+
72
+    if (currentHue.value === 360) {
73
+      return rect.width - barHandle.value.offsetWidth / 2;
74
+    }
75
+    return (
76
+      ((currentHue.value % 360) *
77
+        (rect.width - barHandle.value.offsetWidth)) /
78
+      360 +
79
+      barHandle.value.offsetWidth / 2
80
+    );
81
+  }
82
+
83
+  return 0;
84
+};
85
+
86
+const getBarTopPosition = () => {
87
+  if (!props.vertical) return 0;
88
+  if (bar.value && barHandle.value) {
89
+    const rect = bar.value?.getBoundingClientRect();
90
+
91
+    if (currentHue.value === 360) {
92
+      return barHandle.value?.offsetHeight / 2;
93
+    }
94
+    return (
95
+      ((360 - (currentHue.value % 360)) *
96
+        (rect.height - barHandle.value.offsetHeight)) /
97
+      360 +
98
+      barHandle.value.offsetHeight / 2
99
+    );
100
+  }
101
+
102
+  return 0;
103
+};
104
+
105
+const updatePosition = () => {
106
+  handleLeft.value = getBarLeftPosition();
107
+  handleTop.value = getBarTopPosition();
108
+};
109
+
110
+const handleDrag = (event: MouseEvent) => {
111
+  if (bar.value && barHandle.value) {
112
+    const rect = bar.value?.getBoundingClientRect();
113
+
114
+    if (!props.vertical) {
115
+      let left = event.clientX - rect.left;
116
+      left = Math.min(left, rect.width - barHandle.value.offsetWidth / 2);
117
+      left = Math.max(barHandle.value.offsetWidth / 2, left);
118
+
119
+      currentHue.value = Math.round(
120
+        ((left - barHandle.value.offsetWidth / 2) /
121
+          (rect.width - barHandle.value.offsetWidth)) *
122
+        360
123
+      );
124
+    } else {
125
+      let top = event.clientY - rect.top;
126
+      top = Math.min(top, rect.height - barHandle.value?.offsetHeight / 2);
127
+      top = Math.max(barHandle.value.offsetHeight / 2, top);
128
+
129
+      currentHue.value = Math.round(
130
+        ((top - barHandle.value.offsetHeight / 2) /
131
+          (rect.height - barHandle.value.offsetHeight)) *
132
+        360
133
+      );
134
+    }
135
+
136
+    emit("update:hue", currentHue.value);
137
+    emit("change", currentHue.value);
138
+  }
139
+};
140
+
141
+const handleClick = (event: MouseEvent) => {
142
+  const target = event.target;
143
+
144
+  if (target !== barHandle.value) {
145
+    handleDrag(event);
146
+  }
147
+};
148
+
149
+watch(
150
+  () => props.hue,
151
+  (hue: number) => {
152
+    currentHue.value = hue;
153
+  }
154
+);
155
+
156
+watch(
157
+  () => currentHue.value,
158
+  () => {
159
+    updatePosition();
160
+  }
161
+);
162
+
163
+onMounted(() => {
164
+  nextTick(() => {
165
+    const dragConfig: DragEventOptions = {
166
+      drag: (event: Event) => {
167
+        handleDrag(event as MouseEvent);
168
+      },
169
+      end: (event: Event) => {
170
+        handleDrag(event as MouseEvent);
171
+      }
172
+    };
173
+
174
+    if (bar.value && barHandle.value) {
175
+      DOMUtils.triggerDragEvent(bar.value, dragConfig);
176
+      DOMUtils.triggerDragEvent(barHandle.value, dragConfig);
177
+    }
178
+    updatePosition();
179
+  });
180
+});
181
+</script>
182
+
183
+<style lang="scss" scoped>
184
+.small-hue-slider {
185
+  height: 10px !important;
186
+
187
+  .small-bar {
188
+    height: 10px !important;
189
+    width: 10px !important;
190
+
191
+    div {
192
+      width: 12px !important;
193
+      height: 12px !important;
194
+      border-radius: 5px !important;
195
+      transform: translate(-6px, -2px);
196
+      margin-top: 1px !important;
197
+    }
198
+  }
199
+}
200
+
201
+.bee-hue-colorPicker {
202
+  position: relative;
203
+  margin-bottom: 15px;
204
+  width: 100%;
205
+  height: 14px;
206
+  box-shadow: 2px 0 8px rgba(0, 0, 0, 0.08);
207
+  border-radius: 15px;
208
+
209
+  &.is-vertical {
210
+    width: 14px;
211
+    height: 100%;
212
+    display: inline-block;
213
+    transform: rotate(180deg);
214
+  }
215
+
216
+  &.transparent {
217
+    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
218
+    background-repeat: repeat;
219
+  }
220
+
221
+  &__inner {
222
+    position: relative;
223
+    width: 100%;
224
+    height: 100%;
225
+    border-radius: 15px;
226
+    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMkAAAAdCAYAAAAAaUg8AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAKtJREFUeNrs09EKgjAUgOGzEFfv/7CVBceiLiJiLnf7fSAbDoUj/iWnyKgRcXxf9Wtt7Vvntf8854jLY3uN19qzf67nH/e2nmmdZ8xjg2x+sI533qf9g4wM/3GvLPumOHVMWf/4SiWWsUG6/6bG+/NWDgE0iQREAiIBkYBIQCQgEhAJiAQQCYgERAIiAZGASEAkIBJAJCASEAmIBEQCIgGRgEgAkYBIYNAqwAD5oWo3bpsiKwAAAABJRU5ErkJggg==);
227
+    background-size: 100%;
228
+
229
+    &-pointer {
230
+      position: absolute;
231
+      width: 14px;
232
+      height: 14px;
233
+    }
234
+
235
+    &-handle {
236
+      width: 14px;
237
+      height: 14px;
238
+      border-radius: 6px;
239
+      transform: translate(-7px, -2px);
240
+      //background-color: #fff;
241
+      background-color: #f8f8f8;
242
+      margin-top: 2px;
243
+      box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37);
244
+      cursor: pointer;
245
+
246
+      &.vertical {
247
+        transform: translate(-1px, -7px);
248
+        margin-top: 0;
249
+      }
250
+    }
251
+  }
252
+}
253
+</style>

+ 203
- 0
ant-design-pro-vue3/src/components/ColorPicker/common/Saturation.vue View File

@@ -0,0 +1,203 @@
1
+<template>
2
+  <div class="bee-saturation" :class="{
3
+    'bee-saturation__chrome': round,
4
+    'bee-saturation__hidden': hidden
5
+  }" :style="{ backgroundColor: background }">
6
+    <div class="bee-saturation__white"></div>
7
+    <div class="bee-saturation__black"></div>
8
+    <div class="bee-saturation__cursor" :style="{
9
+      top: cursorTop + 'px',
10
+      left: cursorLeft + 'px'
11
+    }" @click="handleDrag">
12
+      <div></div>
13
+    </div>
14
+  </div>
15
+</template>
16
+
17
+<script lang="ts" setup name="Saturation">
18
+import {
19
+  getCurrentInstance,
20
+  onMounted,
21
+  reactive,
22
+  ref,
23
+  watch
24
+} from "vue";
25
+import { DOMUtils } from "@aesoper/normal-utils";
26
+
27
+const clamp = (value: number, min: number, max: number) => {
28
+  return min < max
29
+    ? value < min
30
+      ? min
31
+      : value > max
32
+        ? max
33
+        : value
34
+    : value < max
35
+      ? max
36
+      : value > min
37
+        ? min
38
+        : value;
39
+};
40
+const props = defineProps({
41
+  hue: {
42
+    type: Number,
43
+    default: 0,
44
+    validator: (value: number) => {
45
+      return value >= 0 && value <= 360;
46
+    }
47
+  },
48
+  saturation: {
49
+    type: Number,
50
+    default: 0,
51
+    validator: (value: number) => {
52
+      return value >= 0 && value <= 1;
53
+    }
54
+  },
55
+  value: {
56
+    type: Number,
57
+    default: 0,
58
+    validator: (value: number) => {
59
+      return value >= 0 && value <= 1;
60
+    }
61
+  },
62
+  round: Boolean,
63
+  hidden: Boolean
64
+})
65
+
66
+const emit = defineEmits(["update:saturation", "update:value", "change"])
67
+// instance
68
+const instance = getCurrentInstance();
69
+// data
70
+const cursorTop = ref(0);
71
+const cursorLeft = ref(0);
72
+const background = ref("hsl(" + props.hue + ", 100%, 50%)");
73
+const currentHsv = reactive({
74
+  h: props.hue,
75
+  s: props.saturation,
76
+  v: props.value
77
+});
78
+
79
+const updatePosition = () => {
80
+  if (instance) {
81
+    const el = instance.vnode.el;
82
+    cursorLeft.value = currentHsv.s * el?.clientWidth;
83
+    cursorTop.value = (1 - currentHsv.v) * el?.clientHeight;
84
+  }
85
+};
86
+
87
+const handleDrag = (event: MouseEvent) => {
88
+  if (instance) {
89
+    const el = instance.vnode.el;
90
+    const rect = el?.getBoundingClientRect();
91
+
92
+    let left = event.clientX - rect.left;
93
+    let top = event.clientY - rect.top;
94
+
95
+    left = clamp(left, 0, rect.width);
96
+    top = clamp(top, 0, rect.height);
97
+
98
+    const saturation = Math.round((left / rect.width) * 100) / 100;
99
+    const bright =
100
+      Math.round(clamp(-(top / rect.height) + 1, 0, 1) * 100) / 100;
101
+
102
+    cursorLeft.value = left;
103
+    cursorTop.value = top;
104
+
105
+    currentHsv.s = saturation;
106
+    currentHsv.v = bright;
107
+
108
+    emit("update:saturation", saturation);
109
+    emit("update:value", bright);
110
+    emit("change", saturation, bright);
111
+  }
112
+};
113
+
114
+onMounted(() => {
115
+  if (instance && instance.vnode.el) {
116
+    DOMUtils.triggerDragEvent(instance.vnode.el as HTMLElement, {
117
+      drag: (event: Event) => {
118
+        handleDrag(event as MouseEvent);
119
+      },
120
+      end: event => {
121
+        handleDrag(event as MouseEvent);
122
+      }
123
+    });
124
+
125
+    updatePosition();
126
+  }
127
+});
128
+
129
+// watch
130
+watch(
131
+  () => props.hue,
132
+  (hue: number) => {
133
+    currentHsv.h = hue;
134
+    background.value = "hsl(" + Math.round(currentHsv.h) + ", 100%, 50%)";
135
+  }
136
+);
137
+
138
+watch(
139
+  () => props.value,
140
+  (value: number) => {
141
+    currentHsv.v = value;
142
+    updatePosition();
143
+  }
144
+);
145
+
146
+watch(
147
+  () => props.saturation,
148
+  (saturation: number) => {
149
+    currentHsv.s = saturation;
150
+    updatePosition();
151
+  }
152
+);
153
+</script>
154
+
155
+<style lang="scss" scoped>
156
+.bee-saturation {
157
+  position: relative;
158
+  margin-bottom: 15px;
159
+  width: 100%;
160
+  height: 125px;
161
+
162
+  &__chrome {
163
+    border-top-left-radius: 5px;
164
+    border-top-right-radius: 5px;
165
+    border-color: transparent;
166
+  }
167
+
168
+  &__hidden {
169
+    overflow: hidden;
170
+  }
171
+
172
+  &__white,
173
+  &__black {
174
+    position: absolute;
175
+    top: 0;
176
+    left: 0;
177
+    right: 0;
178
+    bottom: 0;
179
+  }
180
+
181
+  &__black {
182
+    background: linear-gradient(0deg, #000, transparent);
183
+  }
184
+
185
+  &__white {
186
+    background: linear-gradient(90deg, #fff, hsla(0, 0%, 100%, 0));
187
+  }
188
+
189
+  &__cursor {
190
+    position: absolute;
191
+
192
+    div {
193
+      transform: translate(-5px, -5px);
194
+      box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37);
195
+      width: 10px;
196
+      height: 10px;
197
+      border: 1px solid white;
198
+      border-radius: 50%;
199
+      cursor: pointer;
200
+    }
201
+  }
202
+}
203
+</style>

+ 198
- 0
ant-design-pro-vue3/src/components/ColorPicker/common/VColorInput.vue View File

@@ -0,0 +1,198 @@
1
+<template>
2
+  <div class="inputs-controls">
3
+    <!-- <button class="formatBtn" @click="onChangeFormat"> -->
4
+    {{ currentFormat }}
5
+    <!-- </button> -->
6
+    <!-- <div class="format-group" v-if="currentFormat === 'hsv'">
7
+      <input
8
+        v-model="currentColor.hsv.h"
9
+        type="number"
10
+        min="0"
11
+        max="360"
12
+        placeholder="h"
13
+        @blur="onInputChange('hsv')"
14
+      />
15
+      <input
16
+        v-model="currentColor.hsv.s"
17
+        type="number"
18
+        min="0"
19
+        max="1"
20
+        placeholder="s"
21
+        @blur="onInputChange('hsv')"
22
+      />
23
+      <input
24
+        v-model="currentColor.hsv.v"
25
+        type="number"
26
+        min="0"
27
+        max="1"
28
+        placeholder="v"
29
+        @blur="onInputChange('hsv')"
30
+      />
31
+    </div>
32
+    <div class="format-group" v-if="currentFormat === 'hsl'">
33
+      <input
34
+        v-model="currentColor.hsl.h"
35
+        type="number"
36
+        min="0"
37
+        max="360"
38
+        placeholder="h"
39
+        @blur="onInputChange('hsl')"
40
+      />
41
+      <input
42
+        v-model="currentColor.hsl.s"
43
+        type="number"
44
+        min="0"
45
+        max="1"
46
+        placeholder="s"
47
+        @blur="onInputChange('hsl')"
48
+      />
49
+      <input
50
+        v-model="currentColor.hsl.l"
51
+        type="number"
52
+        min="0"
53
+        max="1"
54
+        placeholder="l"
55
+        @blur="onInputChange('hsl')"
56
+      />
57
+    </div>
58
+    <div class="format-group" v-if="currentFormat === 'rgb'">
59
+      <input
60
+        v-model="currentColor.rgb.r"
61
+        type="number"
62
+        min="0"
63
+        max="255"
64
+        placeholder="r"
65
+        @blur="onInputChange('rgb')"
66
+      />
67
+      <input
68
+        v-model="currentColor.rgb.g"
69
+        type="number"
70
+        min="0"
71
+        max="255"
72
+        placeholder="g"
73
+        @blur="onInputChange('rgb')"
74
+      />
75
+      <input
76
+        v-model="currentColor.rgb.b"
77
+        type="number"
78
+        min="0"
79
+        max="255"
80
+        @blur="onInputChange('rgb')"
81
+        placeholder="b"
82
+      />
83
+    </div> -->
84
+    <div class="format-group" v-if="currentFormat === 'hex'">
85
+      <input v-model="currentColor.hex" type="text" maxlength="7" placeholder="hex" @blur="onInputChange('hex')" />
86
+    </div>
87
+  </div>
88
+</template>
89
+
90
+<script lang="ts" setup name="VColorInput">
91
+import { PropType, ref, toRaw, watch } from "vue";
92
+import { Color, ColorAttrs, ColorInput } from "../color";
93
+import { ArrayUtils } from "@aesoper/normal-utils";
94
+
95
+const formatList = ["hex", "hsl", "rgb", "hsv"];
96
+
97
+const props = defineProps({
98
+  color: {
99
+    type: [String, Object] as PropType<ColorInput>,
100
+    default: "#000000"
101
+  }
102
+})
103
+const emit = defineEmits(["update:color", "change"])
104
+
105
+const colorClass = new Color();
106
+
107
+const currentFormat = ref(formatList[0]);
108
+const currentColor = ref<ColorAttrs>(colorClass.parseColor(props.color));
109
+
110
+const onChangeFormat = () => {
111
+  const index = ArrayUtils.findIndex(
112
+    formatList,
113
+    (val: string) => val == currentFormat.value
114
+  );
115
+
116
+  currentFormat.value = formatList[(index + 1) % formatList.length];
117
+};
118
+
119
+watch(
120
+  () => props.color,
121
+  (newVal: ColorInput) => {
122
+    currentColor.value = colorClass.parseColor(toRaw(newVal));
123
+  }
124
+);
125
+
126
+const doOnChange = (data: any, oldHue?: number): void => {
127
+  currentColor.value = colorClass.parseColor(data, oldHue);
128
+  emit("update:color", currentColor.value);
129
+  emit("change", currentColor.value);
130
+};
131
+
132
+const onInputChange = (source: string) => {
133
+  switch (source) {
134
+    case "hex":
135
+      doOnChange({ hex: currentColor.value.hex, source: "hex" });
136
+      break;
137
+    case "hsl":
138
+      doOnChange({ hsl: currentColor.value.hsl, source: "hsl" });
139
+      break;
140
+    case "rgb":
141
+      doOnChange({ rgb: currentColor.value.rgb, source: "rgb" });
142
+      break;
143
+    case "hsv":
144
+      doOnChange({ hsv: currentColor.value.hsv, source: "hsv" });
145
+  }
146
+};
147
+</script>
148
+
149
+<style lang="scss" scoped>
150
+.inputs-controls {
151
+  display: flex;
152
+  font-size: 16px;
153
+  margin-bottom: 5px;
154
+
155
+  .formatBtn {
156
+    position: relative;
157
+    display: inline-flex;
158
+    justify-content: center;
159
+    align-items: center;
160
+    padding: 1px;
161
+    border: 0;
162
+    text-align: center;
163
+    cursor: pointer;
164
+    background-color: transparent;
165
+    font-weight: 700;
166
+    outline: none;
167
+    margin-right: 5px;
168
+
169
+    &:hover {
170
+      color: #1a3aff;
171
+    }
172
+  }
173
+
174
+  .format-group {
175
+    display: flex;
176
+    flex-grow: 1;
177
+
178
+    input {
179
+      padding: 5px;
180
+      margin: 0 3px;
181
+      min-width: 0;
182
+      text-align: center;
183
+      border-width: 0 0 1px 0;
184
+      -webkit-appearance: none;
185
+      appearance: none;
186
+      -moz-appearance: textfield;
187
+      outline: none;
188
+      flex: 1;
189
+
190
+      &::-webkit-outer-spin-button,
191
+      &::-webkit-inner-spin-button {
192
+        -webkit-appearance: none !important;
193
+        margin: 0;
194
+      }
195
+    }
196
+  }
197
+}
198
+</style>

+ 185
- 0
ant-design-pro-vue3/src/components/ColorPicker/index.vue View File

@@ -0,0 +1,185 @@
1
+<template>
2
+  <div class="bee-ele-colorPicker">
3
+    <div class="bee-ele-row">
4
+      <saturation class="bee-ele-saturation" :hidden="true" :saturation="currentColor.hsv.s" :hue="currentColor.hsv.h"
5
+        :value="currentColor.hsv.v" @change="onSaturationChange" />
6
+      <hue class="bee-ele-hue" :vertical="true" size="small" :hue="currentColor.hsv.h" @change="onHueChange"
7
+        v-if="!disableHue" />
8
+    </div>
9
+    <alpha style="width: 257px" :color="currentColor.hex8" @change="onAlphaChange" :alpha="currentColor.alpha"
10
+      v-if="!disableAlpha" />
11
+
12
+    <v-color-input style="width: 257px" :color="currentColor" @change="onInputChange" />
13
+
14
+    <history :color-list="storageColorList" :round="historyRound" @change="onCompactChange" v-if="!disableHistory" />
15
+  </div>
16
+</template>
17
+
18
+<script lang="ts" setup name="EleColorPicker">
19
+import { onMounted, PropType, ref, toRaw, watch } from "vue";
20
+import Saturation from "./common/Saturation.vue";
21
+import Hue from "./common/Hue.vue";
22
+import Alpha from "./common/Alpha.vue";
23
+import History from "./common/History.vue";
24
+import VColorInput from "./common/VColorInput.vue";
25
+import {
26
+  Color,
27
+  ColorAttrs,
28
+  ColorFormat,
29
+  ColorInput,
30
+  debounceFn,
31
+  MAX_STORAGE_LENGTH,
32
+  STORAGE_COLOR_KEY
33
+} from "./color";
34
+import ls from '@/utils/Storage'
35
+
36
+const props = defineProps({
37
+  color: {
38
+    type: [String, Object] as PropType<ColorInput>,
39
+    default: "#000000"
40
+  },
41
+  format: {
42
+    type: String as PropType<ColorFormat>
43
+  },
44
+  disableAlpha: Boolean,
45
+  disableHue: Boolean,
46
+  disableHistory: Boolean,
47
+  historyRound: {
48
+    type: Boolean,
49
+    default: true
50
+  }
51
+})
52
+
53
+const emit = defineEmits(["update:color", "change"])
54
+const colorClass = new Color();
55
+
56
+const currentColor = ref<ColorAttrs>(colorClass.parseColor(props.color));
57
+
58
+const storageColorList = ref<string[]>([]);
59
+
60
+const onStorageColor = () => {
61
+  storageColorList.value = storageColorList.value.filter(value => {
62
+    return value !== currentColor.value.hex8;
63
+  });
64
+  if (storageColorList.value.length >= MAX_STORAGE_LENGTH) {
65
+    storageColorList.value.shift();
66
+  }
67
+  storageColorList.value.push(currentColor.value.hex8);
68
+  ls.set(STORAGE_COLOR_KEY, storageColorList.value)
69
+};
70
+
71
+const onInitColorList = () => {
72
+  storageColorList.value = ls.get(STORAGE_COLOR_KEY) || []
73
+};
74
+
75
+const doOnChange = (data: any, oldHue?: number): void => {
76
+  currentColor.value = colorClass.parseColor(data, oldHue);
77
+  debounceFn(onStorageColor);
78
+};
79
+
80
+const doUpdate = () => {
81
+  if (props.format) {
82
+    emit("update:color", colorClass.format(props.format));
83
+    emit("change", colorClass.format(props.format));
84
+  } else {
85
+    emit("update:color", currentColor.value);
86
+    emit("change", currentColor.value);
87
+  }
88
+};
89
+
90
+const onCompactChange = (color: string) => {
91
+  doOnChange(color);
92
+  doUpdate();
93
+};
94
+
95
+const onAlphaChange = (alpha: number) => {
96
+  doOnChange(
97
+    {
98
+      h: currentColor.value.hsl.h,
99
+      s: currentColor.value.hsl.s,
100
+      l: currentColor.value.hsl.l,
101
+      a: alpha,
102
+      source: "alpha"
103
+    },
104
+    currentColor.value.hsl.h
105
+  );
106
+  doUpdate();
107
+};
108
+
109
+const onSaturationChange = (saturation: number, bright: number) => {
110
+  doOnChange(
111
+    {
112
+      h: currentColor.value.hsv.h,
113
+      s: saturation,
114
+      v: bright,
115
+      a: currentColor.value.hsv.a,
116
+      source: "saturation"
117
+    },
118
+    currentColor.value.hsv.h
119
+  );
120
+  doUpdate();
121
+};
122
+
123
+const onHueChange = (hue: number) => {
124
+  const { s: saturation, v: bright, a: alpha } = currentColor.value.hsv;
125
+  doOnChange(
126
+    {
127
+      h: hue,
128
+      s: saturation,
129
+      v: bright,
130
+      a: alpha,
131
+      source: "hue"
132
+    },
133
+    hue
134
+  );
135
+
136
+  doUpdate();
137
+};
138
+
139
+const onInputChange = (val: ColorAttrs) => {
140
+  currentColor.value = val;
141
+  doUpdate();
142
+};
143
+
144
+watch(
145
+  () => props.color,
146
+  (newVal: ColorInput) => {
147
+    doOnChange(toRaw(newVal));
148
+    onInitColorList();
149
+  }
150
+);
151
+
152
+onMounted(() => {
153
+  onInitColorList();
154
+});
155
+</script>
156
+
157
+<style lang="scss" scoped>
158
+.bee-ele-colorPicker {
159
+  position: relative;
160
+  box-sizing: border-box;
161
+  border-radius: 3px;
162
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
163
+  -webkit-user-select: none;
164
+  -moz-user-select: none;
165
+  -ms-user-select: none;
166
+  user-select: none;
167
+  background-color: white;
168
+  padding: 10px;
169
+  width: 300px;
170
+
171
+  .bee-ele-row {
172
+    display: flex;
173
+
174
+    .bee-ele-saturation {
175
+      width: 280px;
176
+      height: 180px;
177
+    }
178
+
179
+    .bee-ele-hue {
180
+      margin-left: 10px;
181
+      height: 180px;
182
+    }
183
+  }
184
+}
185
+</style>

+ 153
- 0
ant-design-pro-vue3/src/components/DescriptionList/DescriptionList.vue View File

@@ -0,0 +1,153 @@
1
+<template>
2
+  <div :class="['description-list', size, layout === 'vertical' ? 'vertical': 'horizontal']">
3
+    <div v-if="title" class="title">{{ title }}</div>
4
+    <a-row>
5
+      <slot></slot>
6
+    </a-row>
7
+  </div>
8
+</template>
9
+
10
+<script>
11
+import { Col } from 'ant-design-vue/es/grid/'
12
+
13
+const Item = {
14
+  name: 'DetailListItem',
15
+  props: {
16
+    term: {
17
+      type: String,
18
+      default: '',
19
+      required: false
20
+    }
21
+  },
22
+  inject: {
23
+    col: {
24
+      type: Number
25
+    }
26
+  },
27
+  render () {
28
+    return (
29
+      <Col {...{ props: responsive[this.col] }}>
30
+        <div class="term">{this.$props.term}</div>
31
+        <div class="content">{this.$slots.default}</div>
32
+      </Col>
33
+    )
34
+  }
35
+}
36
+
37
+const responsive = {
38
+  1: { xs: 24 },
39
+  2: { xs: 24, sm: 12 },
40
+  3: { xs: 24, sm: 12, md: 8 },
41
+  4: { xs: 24, sm: 12, md: 6 }
42
+}
43
+
44
+export default {
45
+  name: 'DetailList',
46
+  Item: Item,
47
+  components: {
48
+    Col
49
+  },
50
+  props: {
51
+    title: {
52
+      type: String,
53
+      default: '',
54
+      required: false
55
+    },
56
+    col: {
57
+      type: Number,
58
+      required: false,
59
+      default: 3
60
+    },
61
+    size: {
62
+      type: String,
63
+      required: false,
64
+      default: 'large'
65
+    },
66
+    layout: {
67
+      type: String,
68
+      required: false,
69
+      default: 'horizontal'
70
+    }
71
+  },
72
+  provide () {
73
+    return {
74
+      col: this.col > 4 ? 4 : this.col
75
+    }
76
+  }
77
+}
78
+</script>
79
+
80
+<style lang="less" scoped>
81
+
82
+  .description-list {
83
+
84
+    .title {
85
+      color: rgba(0,0,0,.85);
86
+      font-size: 14px;
87
+      font-weight: 500;
88
+      margin-bottom: 16px;
89
+    }
90
+
91
+    /deep/ .term {
92
+      color: rgba(0,0,0,.85);
93
+      display: table-cell;
94
+      line-height: 20px;
95
+      margin-right: 8px;
96
+      padding-bottom: 16px;
97
+      white-space: nowrap;
98
+
99
+      &:not(:empty):after {
100
+        content: ":";
101
+        margin: 0 8px 0 2px;
102
+        position: relative;
103
+        top: -.5px;
104
+      }
105
+    }
106
+
107
+    /deep/ .content {
108
+      color: rgba(0,0,0,.65);
109
+      display: table-cell;
110
+      min-height: 22px;
111
+      line-height: 22px;
112
+      padding-bottom: 16px;
113
+      width: 100%;
114
+      &:empty {
115
+        content: ' ';
116
+        height: 38px;
117
+        padding-bottom: 16px;
118
+      }
119
+    }
120
+
121
+    &.small {
122
+
123
+      .title {
124
+        font-size: 14px;
125
+        color: rgba(0, 0, 0, .65);
126
+        font-weight: normal;
127
+        margin-bottom: 12px;
128
+      }
129
+      /deep/ .term, .content {
130
+        padding-bottom: 8px;
131
+      }
132
+    }
133
+
134
+    &.large {
135
+      /deep/ .term, .content {
136
+        padding-bottom: 16px;
137
+      }
138
+
139
+      .title {
140
+        font-size: 16px;
141
+      }
142
+    }
143
+
144
+    &.vertical {
145
+      .term {
146
+        padding-bottom: 8px;
147
+      }
148
+      /deep/ .term, .content {
149
+        display: block;
150
+      }
151
+    }
152
+  }
153
+</style>

+ 84
- 0
ant-design-pro-vue3/src/components/FastDevelopBall/FastDevelopModal.vue View File

@@ -0,0 +1,84 @@
1
+<template>
2
+  <a-modal v-model:visible="showModal" title="快速开发面板" :footer="null" @cancel="onCancel" width="60%">
3
+    <a-spin :spinning="loading">
4
+      <section :style="{ height: '400px' }">
5
+        <a-tabs>
6
+          <a-tab-pane tab="模板">
7
+            <div style="margin-bottom:20px">
8
+              <a-space>
9
+                <a-input v-model:value="v" placeholder="请输入页面名称" :style="{ width: '200px' }" />
10
+                <a-button type="primary" @click="createV">创建view</a-button>
11
+              </a-space>
12
+            </div>
13
+            <div>
14
+              <a-space>
15
+                <a-input v-model:value="c" placeholder="请输入组件名称" :style="{ width: '200px' }" />
16
+                <a-button type="primary" @click="createC">创建component</a-button>
17
+              </a-space>
18
+            </div>
19
+          </a-tab-pane>
20
+        </a-tabs>
21
+      </section>
22
+    </a-spin>
23
+  </a-modal>
24
+</template>
25
+<script lang="ts">
26
+import { ref, watch } from 'vue'
27
+import * as api from './service'
28
+
29
+export default {
30
+  props: {
31
+    isShow: {
32
+      type: Boolean,
33
+      default: false
34
+    }
35
+  },
36
+  setup(props, { emit }) {
37
+    const v = ref('')
38
+    const c = ref('')
39
+    const loading = ref(false)
40
+    const onCancel = () => {
41
+      emit('close')
42
+    }
43
+    const createV = () => {
44
+      if (v.value) {
45
+        loading.value = true
46
+        api.createV(v.value)
47
+      } else {
48
+        alert('请输入页面名称')
49
+      }
50
+    }
51
+    const createC = () => {
52
+      if (c.value) {
53
+        loading.value = true
54
+        api.createC(c.value)
55
+      } else {
56
+        alert('请输入组件名称')
57
+      }
58
+    }
59
+
60
+    const showModal = ref<boolean>(false)
61
+    watch(
62
+      () => props.isShow,
63
+      (newVal) => {
64
+        showModal.value = newVal
65
+      },
66
+      {
67
+        immediate: true,
68
+      },
69
+    );
70
+
71
+    return {
72
+      onCancel,
73
+      createV,
74
+      createC,
75
+      c,
76
+      v,
77
+      loading,
78
+      showModal
79
+    }
80
+  }
81
+}
82
+</script>
83
+<style lang="less">
84
+</style>

+ 0
- 0
ant-design-pro-vue3/src/components/FastDevelopBall/helper.ts View File


+ 0
- 0
ant-design-pro-vue3/src/components/FastDevelopBall/index.less View File


+ 58
- 0
ant-design-pro-vue3/src/components/FastDevelopBall/index.vue View File

@@ -0,0 +1,58 @@
1
+<template>
2
+  <div v-if="useBall">
3
+    <a-tooltip>
4
+      <template #title>仿造umi ui做的一个用途图形界面操作命令行的球,生产环境下不会出现</template>
5
+      <div class="FastDevelopBall" id="FastDevelopBall">
6
+        <SvgIcon name="logo" width="30px" height="30px" @click="onShowFastDevelopModal" />
7
+      </div>
8
+    </a-tooltip>
9
+    <FastDevelopModal :isShow="showModal" @close="() => (this.showModal = false)" />
10
+  </div>
11
+</template>
12
+<script lang="ts">
13
+import { onMounted, ref } from 'vue'
14
+import useMove from '@/hooks/mouseMove'
15
+import SvgIcon from '@/components/SvgIcon/index.vue'
16
+import { isDev } from '@/utils/util'
17
+import FastDevelopModal from './FastDevelopModal.vue'
18
+
19
+export default {
20
+  name: 'about',
21
+  components: {
22
+    SvgIcon,
23
+    FastDevelopModal
24
+  },
25
+  setup() {
26
+    const showModal = ref(false)
27
+    const useBall = isDev && (import.meta.env.MODE === 'UseFastDevelopBall')
28
+    onMounted(() => {
29
+      if (useBall) {
30
+        const el = document.getElementById('FastDevelopBall')
31
+        useMove(el)
32
+      }
33
+    })
34
+    const onShowFastDevelopModal = () => {
35
+      showModal.value = true
36
+    }
37
+    return {
38
+      useBall,
39
+      showModal,
40
+      onShowFastDevelopModal
41
+    }
42
+  }
43
+}
44
+</script>
45
+<style scoped>
46
+.FastDevelopBall {
47
+  width: 50px;
48
+  height: 50px;
49
+  top: calc(90% - 100px);
50
+  left: calc(90% - 100px);
51
+  z-index: 99999;
52
+  border: 3px solid #0094ff;
53
+  border-radius: 50%;
54
+  padding: 6.5px 0 0 6.5px;
55
+  cursor: pointer;
56
+  background-color: azure;
57
+}
58
+</style>

+ 1
- 0
ant-design-pro-vue3/src/components/FastDevelopBall/lang/cn.ts View File

@@ -0,0 +1 @@
1
+export default {}

+ 1
- 0
ant-design-pro-vue3/src/components/FastDevelopBall/lang/en.ts View File

@@ -0,0 +1 @@
1
+export default {}

+ 13
- 0
ant-design-pro-vue3/src/components/FastDevelopBall/service.ts View File

@@ -0,0 +1,13 @@
1
+import baseService from '@/utils/http/axios'
2
+
3
+const baseURL = "http://localhost:3006/"
4
+
5
+export const createC = (name) => {
6
+  const api = baseURL + `createModule/addComponent?name=${name}`
7
+  return baseService.get(api)
8
+}
9
+
10
+export const createV = (name) => {
11
+  const api = baseURL + `createModule/addView?name=${name}`
12
+  return baseService.get(api)
13
+}

+ 0
- 0
ant-design-pro-vue3/src/components/FastDevelopBall/types.ts View File


+ 53
- 0
ant-design-pro-vue3/src/components/FormComponents/DynamicForm.vue View File

@@ -0,0 +1,53 @@
1
+<template>
2
+    <a-form class="dynamicForm" :model="formModel">
3
+        <a-row :gutter="24">
4
+            <template v-for="({ type, label, options, onChange, name }) in formProps" :key="name">
5
+                <a-col :span="24 / colNumber">
6
+                    <a-form-item :name="name">
7
+                        <template #label>
8
+                            <span>{{ label }}</span>
9
+                        </template>
10
+                        <a-input v-model:value="formModel[name]" style="width:100%" v-if="type === 'input'" />
11
+                        <a-select v-model:value="formModel[name]" style="width:100%"
12
+                            @change="onFieldChange($event, onChange)" v-else-if="type === 'select'" :allowClear="true">
13
+                            <a-select-option v-for="item in options" :key="item.value" :title="item.label">{{ item.label
14
+                                }}</a-select-option>
15
+                        </a-select>
16
+                    </a-form-item>
17
+                </a-col>
18
+            </template>
19
+        </a-row>
20
+        <slot name="zidingyi"></slot>
21
+    </a-form>
22
+</template>
23
+<script lang='ts' setup name="DynamicForm">
24
+const props = defineProps({
25
+    disabledAll: {
26
+        type: Boolean,
27
+        default: true,
28
+        required: false
29
+    },
30
+    formProps: {
31
+        default: [],
32
+        required: true
33
+    },
34
+    // 列数,默认每行2列
35
+    colNumber: {
36
+        type: Number,
37
+        default: 2,
38
+        required: false
39
+    },
40
+    formModel: {
41
+        type: Object,
42
+        default: {},
43
+        required: true
44
+    },
45
+})
46
+const formProps = props.formProps
47
+const onFieldChange = (value, fn) => {
48
+    if (fn) {
49
+        fn(value)
50
+    }
51
+}
52
+</script>
53
+<style lang='less'></style>

+ 51
- 0
ant-design-pro-vue3/src/components/GlobalFooter/index.vue View File

@@ -0,0 +1,51 @@
1
+<template>
2
+    <div class="footer">
3
+        <div class="copyright">
4
+            Copyright
5
+            <CopyrightOutlined />&nbsp;2023
6
+            <span>Ones</span>
7
+        </div>
8
+    </div>
9
+</template>
10
+
11
+<script lang="ts" setup name="GlobalFooter">
12
+import { CopyrightOutlined, GithubOutlined } from '@ant-design/icons-vue'
13
+import { isMobile } from '@/utils/device'
14
+</script>
15
+
16
+<style lang="less" scoped>
17
+.footer {
18
+    padding: 0 16px;
19
+    margin: 48px 0 24px;
20
+    text-align: center;
21
+
22
+    .links {
23
+        margin-bottom: 8px;
24
+
25
+        a {
26
+            color: rgba(0, 0, 0, 0.45);
27
+
28
+            &:hover {
29
+                color: rgba(0, 0, 0, 0.65);
30
+            }
31
+
32
+            &:not(:last-child) {
33
+                margin-right: 40px;
34
+            }
35
+        }
36
+
37
+        &.lessMargin {
38
+            a {
39
+                &:not(:last-child) {
40
+                    margin-right: 20px;
41
+                }
42
+            }
43
+        }
44
+    }
45
+
46
+    .copyright {
47
+        color: rgba(0, 0, 0, 0.45);
48
+        font-size: 14px;
49
+    }
50
+}
51
+</style>

+ 140
- 0
ant-design-pro-vue3/src/components/GlobalHeader/index.vue View File

@@ -0,0 +1,140 @@
1
+<template>
2
+  <transition name="showHeader">
3
+    <div v-if="visible" class="header-animat">
4
+      <a-layout-header v-if="visible"
5
+        :class="[fixedHeader && 'ant-header-fixedHeader', sidebarOpened ? 'ant-header-side-opened' : 'ant-header-side-closed',]"
6
+        :style="{ padding: '0' }">
7
+        <div v-if="mode === 'sidemenu'" class="header">
8
+          <span @click="toggle">
9
+            <template v-if="device === 'mobile'">
10
+              <MenuFoldOutlined v-if="collapsed" class="trigger" />
11
+              <MenuUnfoldOutlined v-else class="trigger" />
12
+            </template>
13
+            <template v-else>
14
+              <MenuUnfoldOutlined v-if="collapsed" class="trigger" />
15
+              <MenuFoldOutlined v-else class="trigger" />
16
+            </template>
17
+          </span>
18
+          <ReloadOutlined class="trigger" style="" @click="refreshPage" />
19
+          <user-menu :theme="theme"></user-menu>
20
+        </div>
21
+        <div v-else :class="['top-nav-header-index', theme]">
22
+          <div class="header-index-wide">
23
+            <div class="header-index-left">
24
+              <logo class="top-nav-header" :show-title="device !== 'mobile'" />
25
+              <s-menu v-if="device !== 'mobile'" mode="horizontal" :menu="menus" :theme="theme" />
26
+              <span v-else @click="toggle">
27
+                <MenuFoldOutlined v-if="!collapsed" class="trigger" />
28
+                <MenuUnfoldOutlined v-else class="trigger" />
29
+              </span>
30
+            </div>
31
+            <user-menu class="header-index-right" :theme="theme"></user-menu>
32
+          </div>
33
+        </div>
34
+      </a-layout-header>
35
+    </div>
36
+  </transition>
37
+</template>
38
+
39
+<script lang="ts" setup name="GlobalHeader">
40
+import UserMenu from '../tools/UserMenu/index.vue'
41
+import SMenu from '../Menu/Menu.vue'
42
+import Logo from '../tools/Logo.vue'
43
+import { ref, onMounted, onBeforeUnmount } from 'vue'
44
+import { MenuFoldOutlined, MenuUnfoldOutlined, ReloadOutlined } from '@ant-design/icons-vue'
45
+import useSiteSettings from '@/store/useSiteSettings'
46
+const props = defineProps({
47
+  mode: {
48
+    type: String,
49
+    // sidemenu, topmenu
50
+    default: 'sidemenu'
51
+  },
52
+  menus: {
53
+    type: Array,
54
+    required: true
55
+  },
56
+  theme: {
57
+    type: String,
58
+    required: false,
59
+    default: 'dark'
60
+  },
61
+  collapsed: {
62
+    type: Boolean,
63
+    required: false,
64
+    default: false
65
+  },
66
+  device: {
67
+    type: String,
68
+    required: false,
69
+    default: 'desktop'
70
+  }
71
+})
72
+const visible = ref<boolean>(true)
73
+const oldScrollTop = ref<number>(0)
74
+const ticking = ref<boolean>(false)
75
+
76
+const { sidebarOpened, device, fixedHeader, autoHideHeader } = useSiteSettings()
77
+// 下滑时隐藏 Header
78
+const handleScroll = () => {
79
+  if (!autoHideHeader.value) {
80
+    return
81
+  }
82
+
83
+  const scrollTop = document.body.scrollTop + document.documentElement.scrollTop
84
+  if (!ticking.value) {
85
+    ticking.value = true
86
+    requestAnimationFrame(() => {
87
+      if (oldScrollTop.value > scrollTop) {
88
+        visible.value = true
89
+      } else if (scrollTop > 200 && visible.value) {
90
+        visible.value = false
91
+      } else if (scrollTop < 200 && !visible.value) {
92
+        visible.value = true
93
+      }
94
+      oldScrollTop.value = scrollTop
95
+      ticking.value = false
96
+    })
97
+  }
98
+}
99
+
100
+
101
+const emit = defineEmits(['toggle', 'refresh'])
102
+const toggle = () => {
103
+  emit('toggle')
104
+}
105
+
106
+onMounted(() => {
107
+  document.addEventListener('scroll', handleScroll, { passive: true })
108
+})
109
+
110
+onBeforeUnmount(() => {
111
+  document.body.removeEventListener('scroll', handleScroll, true)
112
+})
113
+
114
+const refreshPage = () => {
115
+  emit('refresh')
116
+}
117
+
118
+</script>
119
+
120
+<style lang="less">
121
+@import '../../style/index.less';
122
+
123
+.header-animat {
124
+  position: relative;
125
+  z-index: @ant-global-header-zindex;
126
+}
127
+
128
+.showHeader-enter-active {
129
+  transition: all 0.25s ease;
130
+}
131
+
132
+.showHeader-leave-active {
133
+  transition: all 0.5s ease;
134
+}
135
+
136
+.showHeader-enter,
137
+.showHeader-leave-to {
138
+  opacity: 0;
139
+}
140
+</style>

+ 21
- 0
ant-design-pro-vue3/src/components/HelloWord.tsx View File

@@ -0,0 +1,21 @@
1
+import { defineComponent, ref } from 'vue';
2
+
3
+export default defineComponent({
4
+  name: 'HelloWord',
5
+  props: {
6
+    msg: {
7
+      type: String,
8
+      default: ''
9
+    }
10
+  },
11
+  setup(prop) {
12
+    const count = ref(0)
13
+    return () => (
14
+      <>
15
+        <h1>{prop.msg}</h1>
16
+        <button onClick={() => {count.value ++}}>count is: { count.value }</button>
17
+        <p>Edit <code>components/HelloWorld.vue</code> to test hot module replacement.</p>
18
+      </>
19
+    );
20
+  },
21
+});

+ 343
- 0
ant-design-pro-vue3/src/components/LockScreen/index.vue View File

@@ -0,0 +1,343 @@
1
+<template>
2
+    <section class="LockScreen" v-if="lockScreen" :class="afterUnlock">
3
+        <div v-if="lockImg" class="bg" :class="isClickedUnlockBtn ? 'unlockClicked' : ''"
4
+            :style="{ backgroundImage: `url(${lockImg})` }"></div>
5
+        <div class="content">
6
+            <!-- 点击解锁后出现输入框 -->
7
+            <div class="iptPassword" v-if="isClickedUnlockBtn">
8
+                <!-- <UserOutlined style="color:grey" class="avatar" /> -->
9
+                <img :src="userinfo.avatar" class="avatar" />
10
+                <div class="username">{{ userinfo.username }}</div>
11
+                <a-input-search v-model:value="password" placeholder="密码" style="width: 300px" @search="onUnlockScreen">
12
+                    <template #enterButton>
13
+                        <a-button type="link">
14
+                            <template #icon>
15
+                                <div class="ArrowRightOutlined">
16
+                                    <ArrowRightOutlined />
17
+                                </div>
18
+                            </template>
19
+                        </a-button>
20
+                    </template>
21
+                </a-input-search>
22
+                <div class="wrongPwd" v-if="isWrongPwd">密码不正确</div>
23
+            </div>
24
+            <!-- 未点击解锁可修改背景图片 -->
25
+            <a-upload :before-upload="onChangeBg" :showUploadList="false" v-else>
26
+                <div class="uploadTxt">
27
+                    <SearchOutlined class="changeBg" />
28
+                    <div class="txt">点击更换背景图片</div>
29
+                </div>
30
+            </a-upload>
31
+            <!-- 左下角时间 -->
32
+            <div class="timeZone">
33
+                <div class="currentTime">{{ currentTime }}</div>
34
+                <div class="dateTime">{{ dateTime }}</div>
35
+            </div>
36
+            <!-- 右下角三个按钮 -->
37
+            <div class="deviceStatus">
38
+                <!-- 是否联网 -->
39
+                <span class="onlineStatus">
40
+                    <img src="/icons/onLine.ico" v-show="isOnline" />
41
+                    <img src="/icons/offLine.ico" v-show="!isOnline" />
42
+                </span>
43
+                <!-- 是否充电 -->
44
+                <SvgIcon :name="charging ? 'batteryCharge' : 'battery'" color="#fff" width="33px" height="33px"
45
+                    class="charge" />
46
+                <!-- 解锁按钮 -->
47
+                <a-tooltip>
48
+                    <template #title>{{ isClickedUnlockBtn ? '返回' : '点击解锁' }}</template>
49
+                    <LockOutlined class="unlock" @click="onClickLockBtn" v-if="isClickedUnlockBtn" />
50
+                    <UnlockOutlined class="unlock" @click="onClickUnlockBtn" v-else />
51
+                </a-tooltip>
52
+            </div>
53
+        </div>
54
+    </section>
55
+</template>
56
+<script lang="ts" setup name="LockScreen">
57
+import { onMounted, ref } from 'vue'
58
+import { systemConfig } from '@/store/reactiveState'
59
+import useSiteSettings from '@/store/useSiteSettings'
60
+import { SET_LOCK_SCREEN } from '@/store/mutation-types'
61
+import indexdb from '@/utils/indexDB'
62
+import dayjs from 'dayjs';
63
+import { getWeek } from '@/utils/util'
64
+import { useBattery, useNetwork } from '@vueuse/core'
65
+import SvgIcon from '@/components/SvgIcon/index.vue'
66
+import {
67
+    SearchOutlined,
68
+    UnlockOutlined,
69
+    LockOutlined,
70
+    ArrowRightOutlined,
71
+    UserOutlined
72
+} from '@ant-design/icons-vue'
73
+import { USER_INFO } from '@/store/mutation-types'
74
+import ls from '@/utils/Storage'
75
+import * as api from './service'
76
+
77
+const userinfo = ls.get(USER_INFO)
78
+const initBg =
79
+    'https://desk-fd.zol-img.com.cn/t_s1920x1080c5/g6/M00/03/0B/ChMkKWECB-OIKeSVAFU590PRoH0AASPhQB7J0oAVToP393.jpg'
80
+
81
+const isClickedUnlockBtn = ref(false)
82
+const { lockScreen } = useSiteSettings()
83
+const onClickUnlockBtn = () => {
84
+    isClickedUnlockBtn.value = true
85
+}
86
+const onClickLockBtn = () => {
87
+    isClickedUnlockBtn.value = false
88
+}
89
+
90
+// 获取锁屏壁纸
91
+const lockImg = ref(null)
92
+onMounted(async () => {
93
+    setTimeout(async () => {
94
+        const bg = await indexdb.get('lockImg')
95
+        lockImg.value = bg?.value || initBg
96
+    }, 100)
97
+})
98
+
99
+// 获取左下角日期时间
100
+const getDateTime = () => {
101
+    const week = dayjs().weekday()
102
+    const formatedWeek = getWeek(week, false)
103
+    const day = dayjs().date()
104
+    const month = dayjs().month() + 1
105
+    return month + '月' + day + '日' + ', ' + formatedWeek
106
+}
107
+const dateTime = ref(getDateTime())
108
+const currentTime = ref(dayjs().format('HH:mm'))
109
+setInterval(() => {
110
+    currentTime.value = dayjs().format('HH:mm')
111
+    dateTime.value = getDateTime()
112
+}, 1000)
113
+
114
+// 获取电池状态
115
+const { charging } = useBattery()
116
+// 获取网络状态
117
+const { isOnline } = useNetwork()
118
+
119
+const onChangeBg = (file) => {
120
+    if (file.type.indexOf('image') < 0) {
121
+        alert('只能传图片!')
122
+    }
123
+    const reader = new FileReader()
124
+    reader.readAsDataURL(file)
125
+    reader.onload = function () {
126
+        indexdb.set('lockImg', this.result)
127
+        lockImg.value = this.result
128
+    }
129
+    return false
130
+}
131
+
132
+const password = ref()
133
+const isWrongPwd = ref(false)
134
+const afterUnlock = ref()
135
+
136
+const onUnlockScreen = () => {
137
+    api.userLogin({ username: userinfo.username, password: password.value }).then((res: any) => {
138
+        if (!password.value) {
139
+            isWrongPwd.value = true
140
+            return false
141
+        } else {
142
+            isWrongPwd.value = false
143
+        }
144
+        if (res) {
145
+            if (res.unlocked) {
146
+                afterUnlock.value = 'afterUnlock'
147
+                setTimeout(() => {
148
+                    systemConfig.commit('SET_LOCK_SCREEN', false)
149
+                    afterUnlock.value = null
150
+                    isWrongPwd.value = false
151
+                    isClickedUnlockBtn.value = false
152
+                    password.value = null
153
+                }, 300)
154
+            } else {
155
+                isWrongPwd.value = true
156
+            }
157
+        } else {
158
+            isWrongPwd.value = true
159
+        }
160
+    })
161
+}
162
+</script>
163
+<style lang="less" scoped>
164
+.afterUnlock {
165
+    opacity: 0 !important;
166
+    transition: opacity 0.3s;
167
+}
168
+
169
+.LockScreen {
170
+    background-color: rgba(0, 0, 0, 0.6);
171
+    opacity: 1;
172
+    position: absolute;
173
+    top: 0;
174
+    bottom: 0;
175
+    left: 0;
176
+    right: 0;
177
+    z-index: 106;
178
+    overflow: hidden;
179
+
180
+    .bg {
181
+        width: 100%;
182
+        position: absolute;
183
+        z-index: 1;
184
+        background-color: #fff;
185
+        background-size: 100% auto;
186
+        background-repeat: no-repeat;
187
+        height: 100%;
188
+    }
189
+
190
+    .unlockClicked {
191
+        transform: scale(1.1);
192
+        filter: blur(10px);
193
+        transition: all 0.1s;
194
+    }
195
+
196
+    .content {
197
+        position: absolute;
198
+        width: 100%;
199
+        height: 100%;
200
+        z-index: 2;
201
+
202
+        .iptPassword {
203
+            display: flex;
204
+            flex-direction: column;
205
+            justify-content: center;
206
+            align-items: center;
207
+            position: absolute;
208
+            left: 50%;
209
+            top: 50%;
210
+            transform: translate(-50%, -50%);
211
+
212
+            .avatar {
213
+                width: 130px;
214
+                height: 130px;
215
+                background-color: #e8eceb;
216
+                border-radius: 50%;
217
+                font-size: 80px;
218
+                line-height: 130px;
219
+                padding: 5px;
220
+            }
221
+
222
+            .username {
223
+                color: #fff;
224
+                font-size: 40px;
225
+                margin: 10px auto 15px auto;
226
+            }
227
+
228
+            .wrongPwd {
229
+                color: #f88070;
230
+                font-size: 16px;
231
+                text-align: left;
232
+                margin: 5px 0;
233
+                width: 100%;
234
+            }
235
+
236
+            ::v-deep(.ant-input) {
237
+                border-radius: 0;
238
+
239
+                &:hover {
240
+                    border-color: grey;
241
+                }
242
+            }
243
+
244
+            .ant-btn.ant-btn-link {
245
+                width: 32px;
246
+                height: 32px;
247
+                background-color: grey;
248
+                border: 2px solid #fff;
249
+
250
+                &:hover {
251
+                    color: #fff;
252
+                    border-color: #fff;
253
+                }
254
+
255
+                .ArrowRightOutlined {
256
+                    color: #fff;
257
+
258
+                    &:hover {
259
+                        color: rgba(0, 0, 0, 0.6);
260
+                    }
261
+                }
262
+            }
263
+        }
264
+
265
+        .uploadTxt {
266
+            display: flex;
267
+            flex-direction: row;
268
+            justify-content: center;
269
+            align-items: center;
270
+            position: absolute;
271
+            left: 45%;
272
+            top: 50%;
273
+            color: #fff;
274
+
275
+            &:hover {
276
+                color: #0094ff;
277
+            }
278
+
279
+            .changeBg {
280
+                font-size: 20px;
281
+                cursor: pointer;
282
+                margin-right: 15px;
283
+            }
284
+
285
+            .txt {
286
+                cursor: pointer;
287
+            }
288
+        }
289
+
290
+        .timeZone {
291
+            position: absolute;
292
+            bottom: 50px;
293
+            left: 20px;
294
+            color: #fff;
295
+
296
+            .currentTime {
297
+                font-size: 100px;
298
+                font-weight: 100;
299
+                height: 90px;
300
+                line-height: 90px;
301
+            }
302
+
303
+            .dateTime {
304
+                font-size: 60px;
305
+                font-weight: 300;
306
+            }
307
+        }
308
+
309
+        .deviceStatus {
310
+            position: absolute;
311
+            bottom: 30px;
312
+            right: 50px;
313
+
314
+            .onlineStatus {
315
+                margin-right: 20px;
316
+                display: inline-block;
317
+
318
+                img {
319
+                    width: 25px;
320
+                    height: 25px;
321
+                }
322
+            }
323
+
324
+            .onlineStatus,
325
+            .charge,
326
+            .unlock {
327
+                vertical-align: middle;
328
+            }
329
+
330
+            .unlock {
331
+                font-size: 23px;
332
+                color: #fff;
333
+                margin-left: 20px;
334
+                font-weight: 500;
335
+
336
+                &:hover {
337
+                    color: #0094ff;
338
+                }
339
+            }
340
+        }
341
+    }
342
+}
343
+</style>

+ 7
- 0
ant-design-pro-vue3/src/components/LockScreen/service.ts View File

@@ -0,0 +1,7 @@
1
+import baseService from '@/utils/http/axios'
2
+import { baseURL } from '@/utils/util'
3
+
4
+export const userLogin = data => {
5
+  const api = baseURL + `auth/unlock`
6
+  return baseService.post(api, data)
7
+}

+ 53
- 0
ant-design-pro-vue3/src/components/LogicFlow/basic/customRect.ts View File

@@ -0,0 +1,53 @@
1
+import { RectNode, RectNodeModel, HtmlNode, HtmlNodeModel } from "@logicflow/core";
2
+import { getShapeStyleFuction } from '../utils/getShapeStyleUtil'
3
+import { colors } from '../utils/config'
4
+
5
+class CustomRectNode extends RectNode { }
6
+
7
+class CustomRectModel extends RectNodeModel {
8
+  initNodeData(data) {
9
+    super.initNodeData(data);
10
+    this.width = 100;
11
+    this.height = 60;
12
+    this.radius = 10;
13
+  }
14
+  getNodeStyle() {
15
+    const style = super.getNodeStyle();
16
+    style.stroke = colors.nodeBorderColor
17
+    style.fill = colors.nodeColor
18
+    const properties = this.getProperties()
19
+    return getShapeStyleFuction(style, properties)
20
+  }
21
+}
22
+
23
+class ButtonNode extends HtmlNode {
24
+  setHtml(rootEl) {
25
+    const { properties } = this.props.model;
26
+
27
+    const el = document.createElement("div");
28
+    el.className = "uml-wrapper";
29
+    const html = `
30
+      <div style="width:100px;height:60px;border:2px solid #349EFF;background-color:#E8F8FF;border-radius:10px">
31
+      </div>
32
+    `;
33
+    el.innerHTML = html;
34
+    rootEl.innerHTML = "";
35
+    rootEl.appendChild(el);
36
+  }
37
+}
38
+
39
+class ButtonNodeModel extends HtmlNodeModel {
40
+  setAttributes() {
41
+    this.stroke = '#349EFF';
42
+    this.fill = '#E8F8FF'
43
+    this.width = 100;
44
+    this.height = 60;
45
+    this.radius = 10;
46
+  }
47
+}
48
+
49
+export default {
50
+  type: "custom-rect",
51
+  view: CustomRectNode,
52
+  model: CustomRectModel
53
+};

+ 37
- 0
ant-design-pro-vue3/src/components/LogicFlow/edge/customBezierEdge.ts View File

@@ -0,0 +1,37 @@
1
+import { BezierEdge, BezierEdgeModel } from '@logicflow/core'
2
+import { getShapeStyleFuction, getTextStyleFunction } from '../utils/getShapeStyleUtil'
3
+
4
+// 贝塞尔曲线
5
+class Model extends BezierEdgeModel {
6
+  constructor(data, graphModel) {
7
+    super(data, graphModel)
8
+    this.strokeWidth = 1
9
+  }
10
+  // getTextStyle() {
11
+  //   const style = super.getTextStyle()
12
+  //   return getTextStyleFunction(style, this.properties)
13
+  // }
14
+
15
+  getEdgeStyle() {
16
+    const attributes = super.getEdgeStyle()
17
+    const properties = this.properties;
18
+    const style = getShapeStyleFuction(attributes, properties)
19
+    return { ...style }
20
+  }
21
+
22
+  // setAttributes() {
23
+  //   this.isAnimation = true;
24
+  // }
25
+  // getEdgeAnimationStyle() {
26
+  //   const style = super.getEdgeAnimationStyle();
27
+  //   style.strokeDasharray = "20 2";
28
+  //   style.animationDuration = "30s";
29
+  //   return style;
30
+  // }
31
+}
32
+
33
+export default {
34
+  type: "custom-bezier",
35
+  view: BezierEdge,
36
+  model: Model
37
+};

+ 1
- 0
ant-design-pro-vue3/src/components/LogicFlow/icon/rectImg.ts View File

@@ -0,0 +1 @@
1
+export default 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAAA4CAYAAAB5YT9uAAAAAXNSR0IArs4c6QAAAt1JREFUeF7t3M9Lk3EcB/D3V7eKOS1j0BgMIS0RLJiokbcgIekSeOjSTcYOHSrynwgSNjtZu0S3Dh0KRlTnEMvVQMKQggyWxkpozWq/nnge9oz5bHvcI34OsvdgsPF8n/eevfbec/t8FfgQFVA26XbHRC/qgIZrja67EaJ69jl/9umq+9HbNIY2c3CVG556QBn28bI7FHCiC8XRAD5cGcxfu9x/eAXADi0rsIE799q9GDwKFR7B9slelPQgPuoF9OJ92kLnwjI8335Bmz2fH7ci19IZr8MJLfW3hNN3LiJL1NYFZl+i23sIq/cvqVDlLKPJVmAVimv/YlPIDhxHqfV4rlz7ic5bz+FNzqgjldvEDmAd2ngGYlpxKYwMbwvOSqPfLsYfwJe+oVwAymaLzQZXgf1RrZiMIOMsnqt1gZEF+DZuGsB6e42nFbjDH9UKBN5bYSrA7kqDCbw3xuZnEXi/RS15BCawsIBwPBtMYGEB4Xg2mMDCAsLxbDCBhQWE49lgAgsLCMezwQQWFhCOZ4MJLCwgHM8GE1hYQDieDSawsIBwPBtMYGEB4Xg2mMDCAsLxbDCBhQWE49lgAgsLCMezwQQWFhCOZ4MJLCwgHM8GE1hYQDieDSawsIBwfEsNDsS0Ase4nP8SpTJwLm6McdkPwYTi2p/oFLKnOIjoSPljBq7bL9CVnFEe2ymjcEJbzhUxeHeSo7ROhK8n0BPsQWp+Uk3YAasnK1vD994fW/R3Q0VGsT3AYfCmzvp059oPuOaX4MkVUIz0r5+ZHuv7YjeIaEx8Pn73ffjVhu/hm7Qa2vwNN7czaGysjxv7vShMBLXUhd6vV6fH+tYruHWjtHpCdZwWQEfNe/OYk39Mu6w194YwR2d12OoYrRWubm7ZgtwuaE6/Zy2o+VrPqNvOoBbcbDPbuzu3tcVV3GZ4dZt07P4Zbb+idhsZ2y1laqW4kYyz3rS8KZKzWK62FfgP5lsoV6FAKMQAAAAASUVORK5CYII='

+ 147
- 0
ant-design-pro-vue3/src/components/LogicFlow/index.vue View File

@@ -0,0 +1,147 @@
1
+<template>
2
+  <section class="LogicFlow">
3
+    <div id="flow"></div>
4
+  </section>
5
+</template>
6
+
7
+<script lang="ts" setup name="LogicFlow">
8
+import { ref, onMounted, watch } from 'vue'
9
+import icon from './icon/rectImg';
10
+import customRect from "./basic/customRect";
11
+import customBezierEdge from "./edge/customBezierEdge";
12
+import { selectedNodeStyle, nodeStyle, edgeStyle, selectedEdgeStyle, colors } from './utils/config'
13
+import LogicFlow from '@logicflow/core'
14
+import { Menu, DndPanel } from '@logicflow/extension';
15
+import "@logicflow/core/dist/style/index.css";
16
+import '@logicflow/extension/lib/style/index.css'
17
+let lfRef = null
18
+let selectedNode = { type: '', id: '' }
19
+const emit = defineEmits(['parentNodes'])
20
+const props = defineProps(['flowData'])
21
+
22
+const clearSelectedNodeStyle = (lf) => {
23
+  lf.setProperties(selectedNode.id, selectedNode.type === 'node' ? nodeStyle : edgeStyle)
24
+}
25
+
26
+const getFlowJson = () => {
27
+  const data = lfRef.value.getGraphData()
28
+  return data
29
+}
30
+
31
+const getAllParentNodes = (lf, id, currentTxt) => {
32
+  const parentNodes = [currentTxt]
33
+  function func(lf, id) {
34
+    const nodes = lf.getNodeIncomingNode(id)
35
+    const node = nodes && nodes[0]
36
+    if (node) {
37
+      parentNodes.push(node.text.value)
38
+      func(lf, node.id)
39
+    }
40
+  }
41
+  func(lf, id)
42
+  emit('parentNodes', parentNodes)
43
+  return parentNodes
44
+}
45
+
46
+defineExpose({
47
+  lfRef,
48
+  getFlowJson
49
+})
50
+
51
+onMounted(() => {
52
+  const lf = new LogicFlow({
53
+    container: document.querySelector("#flow"),
54
+    plugins: [Menu, DndPanel],
55
+    snapline: false,
56
+  });
57
+  lfRef = ref(lf)
58
+  lf.setDefaultEdgeType('bezier')
59
+  lf.register(customRect);
60
+  lf.register(customBezierEdge);
61
+  lf.setDefaultEdgeType('custom-bezier')
62
+  lf.on('node:click', ({ data }) => {
63
+    // 先清除之前的颜色
64
+    clearSelectedNodeStyle(lf)
65
+    // 再设置新的id
66
+    lf.setProperties(data.id, selectedNodeStyle)
67
+    selectedNode = { id: data.id, type: 'node' }
68
+    getAllParentNodes(lf, data.id, data?.text?.value)
69
+  });
70
+  lf.on('edge:click', ({ data }) => {
71
+    // 先清除之前的颜色
72
+    clearSelectedNodeStyle(lf)
73
+    // 再设置新的id
74
+    lf.setProperties(data.id, selectedEdgeStyle)
75
+    selectedNode = { id: data.id, type: 'edge' }
76
+  });
77
+  lf.on('blank:click', () => {
78
+    clearSelectedNodeStyle(lf)
79
+    selectedNode = { id: 'blank', type: 'blank' }
80
+  });
81
+  lf.setTheme({
82
+    bezier: {
83
+      stroke: colors.edgeColor,
84
+      adjustLine: {
85
+        stroke: '#949494',
86
+      },
87
+      adjustAnchor: {
88
+        r: 4,
89
+        fill: '#949494',
90
+        stroke: '#949494',
91
+        fillOpacity: 1,
92
+      },
93
+    },
94
+    nodeText: {
95
+      fontSize: 13,
96
+    },
97
+    edgeText: {
98
+      fontSize: 13,
99
+    },
100
+  })
101
+  lf.extension.dndPanel.setPatternItems([
102
+    {
103
+      type: 'custom-rect',
104
+      label: '请拖拽节点',
105
+      icon,
106
+      className: 'flow-rect-node'
107
+    },
108
+  ]);
109
+
110
+  // ajax 获取数据
111
+  watch(
112
+    () => props.flowData,
113
+    (newVal) => {
114
+      lf.render(newVal)
115
+    },
116
+    {
117
+      deep: true,
118
+      immediate: true
119
+    }
120
+  );
121
+})
122
+</script>
123
+
124
+<style lang="less">
125
+.LogicFlow {
126
+  height: 100vh;
127
+
128
+  #flow {
129
+    height: 100%;
130
+    width: 100%;
131
+
132
+    .flow-rect-node {
133
+      .lf-dnd-shape {
134
+        background-size: 100% 80%;
135
+        width: 50px;
136
+        height: 40px;
137
+      }
138
+    }
139
+
140
+    rect {
141
+      cursor: pointer;
142
+    }
143
+
144
+    .uml-wrapper {}
145
+  }
146
+}
147
+</style>

+ 14
- 0
ant-design-pro-vue3/src/components/LogicFlow/utils/config.ts View File

@@ -0,0 +1,14 @@
1
+export const colors = {
2
+  nodeBorderColor: '#90CFFD',
3
+  selectedNodeBorderColor: '#40A6FE',
4
+  nodeColor: '#E7F7FE',
5
+  selectedNodeColor: '#94D5FD',
6
+  edgeColor: '#AAB7C4',
7
+  selectedEdgeColor: '#40A6FE'
8
+}
9
+
10
+
11
+export const selectedNodeStyle = { fill: colors.selectedNodeColor, stroke: colors.selectedNodeBorderColor }
12
+export const nodeStyle = { fill: colors.nodeColor, stroke: colors.nodeBorderColor }
13
+export const edgeStyle = { stroke: colors.edgeColor }
14
+export const selectedEdgeStyle = { stroke: colors.selectedEdgeColor }

+ 61
- 0
ant-design-pro-vue3/src/components/LogicFlow/utils/getShapeStyleUtil.js View File

@@ -0,0 +1,61 @@
1
+export const getShapeStyleFuction = (style, properties) => {
2
+  if (properties.fill) {
3
+    style.fill = properties.fill
4
+  }
5
+  // if (properties.gradientColor && style.fill !== properties.gradientColor) {
6
+  //   style.fillGradient = properties.gradientColor
7
+  // }
8
+  if (properties.stroke) {
9
+    style.stroke = properties.stroke
10
+  }
11
+  if (properties.strokeWidth) {
12
+    style.strokeWidth = properties.strokeWidth
13
+  }
14
+  // if (properties.borderStyle) {
15
+  //   if (properties.borderStyle === 'solid') {
16
+  //     style.strokeDashArray = '0'
17
+  //     // nodeResize里的bug导致的,array小写了
18
+  //     style.strokeDasharray = '0'
19
+  //   }
20
+  //   if (properties.borderStyle === 'dashed') {
21
+  //     style.strokeDashArray = '3 3'
22
+  //     style.strokeDasharray = '3 3'
23
+  //   }
24
+  //   if (properties.borderStyle === 'dotted') {
25
+  //     style.strokeDashArray = '1 1'
26
+  //     style.strokeDasharray = '1 1'
27
+  //   }
28
+  //   if (properties.borderStyle === 'hidden') {
29
+  //     style.stroke = style.fill
30
+  //   }
31
+  // }
32
+  return style
33
+}
34
+
35
+export const getTextStyleFunction = (style = {}, properties) => {
36
+  if (properties.fontColor) {
37
+    style.color = properties.fontColor
38
+  }
39
+  if (properties.fontSize) {
40
+    style.fontSize = properties.fontSize
41
+  }
42
+  if (properties.fontFamily) {
43
+    style.fontFamily = properties.fontFamily
44
+  }
45
+  if (properties.lineHeight) {
46
+    style.lineHeight = properties.lineHeight
47
+  }
48
+  if (properties.textAlign) {
49
+    style.textAlign = properties.textAlign
50
+  }
51
+  if (properties.fontWeight) {
52
+    style.fontWeight = properties.fontWeight
53
+  }
54
+  if (properties.textDecoration) {
55
+    style.textDecoration = properties.textDecoration
56
+  }
57
+  if (properties.fontStyle) {
58
+    style.fontStyle = properties.fontStyle
59
+  }
60
+  return style
61
+}

+ 110
- 0
ant-design-pro-vue3/src/components/Menu/Menu.vue View File

@@ -0,0 +1,110 @@
1
+<template>
2
+  <a-menu :mode="mode" :theme="theme" :openKeys="openKeys.value" :selectedKeys="selectedKeys" @openChange="onOpenChange"
3
+    @click="onSelect" class="SysMenu">
4
+    <template v-for="m in menu" :key="m.path">
5
+      <RenderSubMenu :menu="m" v-if="!m.hidden" />
6
+    </template>
7
+  </a-menu>
8
+</template>
9
+<script lang="ts" setup name="Menu">
10
+import { reactive, computed, onMounted, watch, ref, ComputedRef } from 'vue'
11
+import { useRouter } from 'vue-router'
12
+import RenderSubMenu from './RenderSubMenu.vue'
13
+
14
+const props = defineProps({
15
+  menu: {
16
+    type: Array,
17
+    required: true
18
+  },
19
+  theme: {
20
+    type: String,
21
+    required: false,
22
+    default: 'dark'
23
+  },
24
+  mode: {
25
+    type: String,
26
+    required: false,
27
+    default: 'inline'
28
+  },
29
+  collapsed: {
30
+    type: Boolean,
31
+    required: false,
32
+    default: false
33
+  }
34
+})
35
+const router = useRouter()
36
+const route = router.currentRoute
37
+const openKeys = reactive<any>({ value: [] })
38
+const selectedKeys = ref<any>([])
39
+const cachedOpenKeys = reactive<any>({ value: [] })
40
+const rootSubmenuKeys: ComputedRef<string[]> = computed(() => {
41
+  const keys: string[] = []
42
+  props.menu.forEach((item: any) => keys.push(item.path))
43
+  return keys
44
+})
45
+onMounted(() => {
46
+  updateMenu()
47
+})
48
+
49
+watch(
50
+  () => props.collapsed,
51
+  (val) => {
52
+    if (val) {
53
+      cachedOpenKeys.value = openKeys.value.concat()
54
+    } else {
55
+      openKeys.value = cachedOpenKeys.value
56
+    }
57
+  }
58
+)
59
+
60
+// 主要作用:使用router.push跳转页面时更左侧新菜单选中项
61
+watch(
62
+  () => route.value,
63
+  (val) => {
64
+    updateMenu()
65
+  }
66
+)
67
+
68
+// select menu item
69
+const onOpenChange = (openKeysParams) => {
70
+  // 在水平模式下时执行,并且不再执行后续
71
+  if (props.mode === 'horizontal') {
72
+    openKeys.value = openKeysParams
73
+    return
74
+  }
75
+  // 非水平模式时
76
+  const latestOpenKey: string = openKeysParams.find(
77
+    (key) => /*去掉这个!则可以全部打开菜单(目前只能打开一个菜单)*/ !openKeys.value.includes(key)
78
+  )
79
+  if (!rootSubmenuKeys.value.includes(latestOpenKey)) {
80
+    openKeys.value = openKeysParams
81
+  } else {
82
+    openKeys.value = latestOpenKey ? [latestOpenKey] : []
83
+  }
84
+}
85
+
86
+const emit = defineEmits(['menuSelect'])
87
+const onSelect = ({ item, key, selectedKeys: selectedKeysParams }) => {
88
+  selectedKeys.value = selectedKeysParams
89
+  emit('menuSelect', { item, key, selectedKeys })
90
+}
91
+const updateMenu = () => {
92
+  const routes = route.value.matched.concat()
93
+  const { hidden } = route.value.meta
94
+  if (routes.length >= 3 && hidden) {
95
+    routes.pop()
96
+    selectedKeys.value = [routes[routes.length - 1].path]
97
+  } else {
98
+    selectedKeys.value = [routes.pop()!.path]
99
+  }
100
+  const openKeysArr: any = []
101
+  if (props.mode === 'inline') {
102
+    routes.forEach((item) => {
103
+      openKeysArr.push(item.path)
104
+    })
105
+  }
106
+  props.collapsed ? (cachedOpenKeys.value = openKeysArr) : (openKeys.value = openKeysArr)
107
+}
108
+</script>
109
+<style lang="less">
110
+</style>

+ 60
- 0
ant-design-pro-vue3/src/components/Menu/RenderSubMenu.vue View File

@@ -0,0 +1,60 @@
1
+<template>
2
+  <a-sub-menu v-if="menu.children && !menu.hideChildrenInMenu" :key="menu.path" popupClassName="popupSubMenu">
3
+    <template #icon>
4
+      <SvgIcon :name="menu.meta.icon" v-if="menu.meta.icon" />
5
+    </template>
6
+    <template #title>{{ $t(menu.meta.title) }}</template>
7
+    <template v-if="!menu.hideChildrenInMenu">
8
+      <template v-for="sub in menu.children">
9
+        <!-- 递归组件 -->
10
+        <RenderSubMenu :menu="sub" />
11
+      </template>
12
+    </template>
13
+  </a-sub-menu>
14
+  <!-- renderMenuItem -->
15
+  <a-menu-item :key="menu.path" v-else-if="!menu.meta.hidden">
16
+    <template #icon>
17
+      <SvgIcon :name="menu.meta.icon" v-if="menu.meta.icon" />
18
+    </template>
19
+    <!-- 外部链接 -->
20
+    <a v-if="menu.meta.target" :href="menu.meta.target" :target="menu.meta.blank === false ? '' : '_blank'">
21
+      <!-- span重复了吧?这就是template的弊端,jsx才是王道 -->
22
+      <span>{{ $t(menu.meta.title) }}</span>
23
+    </a>
24
+    <router-link :to="filterParams(menu.path)" v-else>
25
+      <span>{{ $t(menu.meta.title) }}</span>
26
+    </router-link>
27
+  </a-menu-item>
28
+</template>
29
+<script lang="ts" setup name="RenderSubMenu">
30
+import SvgIcon from '@/components/SvgIcon/index.vue'
31
+
32
+const props = defineProps(['menu'])
33
+// info:todo:貌似没用
34
+if (props.menu.children && props.menu.hideChildrenInMenu) {
35
+  // 把有子菜单的 并且 父菜单是要隐藏子菜单的
36
+  // 都给子菜单增加一个 hidden 属性
37
+  // 用来给刷新页面时, selectedKeys 做控制用
38
+  props.menu.children.forEach((item) => {
39
+    item.meta = Object.assign(item.meta, { hidden: true })
40
+  })
41
+}
42
+
43
+// info:todo:目前没有发现需要入口带参数的情况,一般这种跳转的都是二级页面,是从其他页面跳转过来的,不需要显示在菜单中,目前菜单中是这种路径的,点击也会报404,因为没有对:pageNo([1-9]\\d*)?进行翻译,直接当做了路径去匹配,目前做法是去掉后面的参数
44
+const filterParams = (menu) => {
45
+  return menu.indexOf('/:') > 0 ? menu.split('/:')[0] : menu
46
+}
47
+</script>
48
+<style lang="less" scoped>
49
+.menuName {
50
+
51
+  svg,
52
+  span {
53
+    vertical-align: middle;
54
+  }
55
+
56
+  svg {
57
+    margin-right: 10px;
58
+  }
59
+}
60
+</style>

+ 59
- 0
ant-design-pro-vue3/src/components/Menu/SideMenu.vue View File

@@ -0,0 +1,59 @@
1
+<template>
2
+  <a-layout-sider :class="['sider', isDesktop ? null : 'shadow', theme, fixSiderbar ? 'ant-fixed-sidemenu' : null]"
3
+    width="256px" :collapsible="collapsible" v-model:collapsed="sideMenuCollapsed" :trigger="null">
4
+    <logo />
5
+    <Menu :collapsed="collapsed" :menu="menus" :theme="theme" :mode="mode" @select="onSelect"></Menu>
6
+  </a-layout-sider>
7
+</template>
8
+
9
+<script lang="ts" setup name="SideMenu">
10
+import { watch, ref } from 'vue'
11
+import Logo from '@/components/tools/Logo.vue'
12
+import Menu from './Menu.vue'
13
+import { isDesktop } from '@/utils/device'
14
+import useSiteSettings from '@/store/useSiteSettings'
15
+
16
+const props = defineProps({
17
+  mode: {
18
+    type: String,
19
+    required: false,
20
+    default: 'inline'
21
+  },
22
+  theme: {
23
+    type: String,
24
+    required: false,
25
+    default: 'dark'
26
+  },
27
+  collapsible: {
28
+    type: Boolean,
29
+    required: false,
30
+    default: false
31
+  },
32
+  collapsed: {
33
+    type: Boolean,
34
+    required: false,
35
+    default: false
36
+  },
37
+  menus: {
38
+    type: Array,
39
+    required: true
40
+  }
41
+})
42
+
43
+const sideMenuCollapsed = ref(false)
44
+watch(
45
+  () => props.collapsed,
46
+  (newVal) => {
47
+    sideMenuCollapsed.value = newVal
48
+  },
49
+  {
50
+    immediate: true
51
+  }
52
+);
53
+
54
+const emit = defineEmits(['menuSelect'])
55
+const onSelect = (obj) => {
56
+  emit('menuSelect', obj)
57
+}
58
+const { fixSiderbar } = useSiteSettings()
59
+</script>

+ 25
- 0
ant-design-pro-vue3/src/components/MultiTab/index.less View File

@@ -0,0 +1,25 @@
1
+@import '../../style/index.less';
2
+
3
+@multi-tab-prefix-cls: ~"@{ant-pro-prefix}-multi-tab";
4
+@multi-tab-wrapper-prefix-cls: ~"@{ant-pro-prefix}-multi-tab-wrapper";
5
+
6
+/*
7
+.topmenu .@{multi-tab-prefix-cls} {
8
+  max-width: 1200px;
9
+  margin: -23px auto 24px auto;
10
+}
11
+*/
12
+.@{multi-tab-prefix-cls} {
13
+  margin: -23px -24px 24px -24px;
14
+  background: #fff;
15
+}
16
+
17
+.topmenu .@{multi-tab-wrapper-prefix-cls} {
18
+  max-width: 1200px;
19
+  margin: 0 auto;
20
+}
21
+
22
+.topmenu.content-width-Fluid .@{multi-tab-wrapper-prefix-cls} {
23
+  max-width: 100%;
24
+  margin: 0 auto;
25
+}

+ 203
- 0
ant-design-pro-vue3/src/components/MultiTab/index.vue View File

@@ -0,0 +1,203 @@
1
+<template>
2
+    <div class="ant-pro-multi-tab">
3
+        <div class="ant-pro-multi-tab-wrapper">
4
+            <a-tabs hideAdd type="editable-card" v-model:activeKey="activeKey"
5
+                :tabBarStyle="{ margin: 0, paddingLeft: '11px', paddingTop: '1px' }" @edit="onEdit">
6
+                <a-tab-pane v-for="page in pages" :key="page.fullPath" :closable="pages.length > 1" style="height: 0">
7
+                    <template #tab>
8
+                        <a-dropdown :trigger="['contextmenu']">
9
+                            <span :style="{ userSelect: 'none' }">{{ page.meta.customTitle || $t(page.meta.title) }}</span>
10
+                            <template #overlay>
11
+                                <a-menu @click="({ key, item, domEvent }) => {
12
+                                    closeMenuClick(key, page.fullPath);
13
+                                }">
14
+                                    <a-menu-item key="closeSelf">{{ $t('multiTab.closeCurrent') }}</a-menu-item>
15
+                                    <a-menu-item key="closeRight">{{ $t('multiTab.closeRight') }}</a-menu-item>
16
+                                    <a-menu-item key="closeLeft">{{ $t('multiTab.closeLeft') }}</a-menu-item>
17
+                                    <a-menu-item key="closeAll">{{ $t('multiTab.closeAll') }}</a-menu-item>
18
+                                </a-menu>
19
+                            </template>
20
+                        </a-dropdown>
21
+                    </template>
22
+                </a-tab-pane>
23
+            </a-tabs>
24
+        </div>
25
+    </div>
26
+</template>
27
+<script lang="ts" setup name="MultiTab">
28
+import { ref, reactive, watch, getCurrentInstance } from 'vue'
29
+import { useRouter, RouteLocationNormalizedLoaded } from 'vue-router'
30
+import events from '@/utils/eventBus'
31
+import { message } from 'ant-design-vue'
32
+import { useI18n } from 'vue-i18n'
33
+import './index.less'
34
+
35
+let fullPathList: Array<string> = []
36
+const pages = reactive<Array<RouteLocationNormalizedLoaded>>([])
37
+const activeKey = ref('')
38
+const router = useRouter()
39
+const { t } = useI18n()
40
+const { proxy } = getCurrentInstance()
41
+
42
+const selectedLastPath = () => {
43
+    activeKey.value = fullPathList[fullPathList.length - 1]
44
+}
45
+
46
+    ; (function created() {
47
+        // 全局的事件绑定用于页面内控制tab标签,暂时用不上
48
+        // #region
49
+        events.once('multiTab.open', (val) => {
50
+            if (!val) {
51
+                throw new Error(`multi-tab: open tab ${val} err`)
52
+            }
53
+            activeKey.value = val
54
+        })
55
+        events.once('multiTab.close', (val) => {
56
+            if (!val) {
57
+                closeSelf(activeKey.value)
58
+                return
59
+            }
60
+            closeSelf(val)
61
+        })
62
+        events.once('multiTab.rename', ({ key, name }) => {
63
+            console.log('rename', key, name)
64
+            try {
65
+                const item = pages.find((item) => item.path === key)
66
+                item!.meta.customTitle = name
67
+                proxy.$forceUpdate()
68
+            } catch (e) {
69
+                console.error(e)
70
+            }
71
+        })
72
+        // #endregion
73
+
74
+        pages.push(router.currentRoute.value)
75
+        fullPathList.push(router.currentRoute.value.fullPath)
76
+        selectedLastPath()
77
+    })()
78
+
79
+const onEdit = (targetKey, action) => {
80
+    //proxy[action](targetKey)
81
+    remove(targetKey)
82
+}
83
+const remove = (targetKey) => {
84
+    const temp = pages.filter((page) => page.fullPath !== targetKey)
85
+    pages.length = 0
86
+    pages.push(...temp)
87
+    fullPathList = fullPathList.filter((path) => path !== targetKey)
88
+    // 判断当前标签是否关闭,若关闭则跳转到最后一个还存在的标签页
89
+    if (!fullPathList.includes(activeKey.value)) {
90
+        selectedLastPath()
91
+    }
92
+}
93
+
94
+// content menu
95
+const closeSelf = (e) => {
96
+    // 判断是否为最后一个标签页,如果是最后一个,则无法被关闭
97
+    if (fullPathList.length > 1) {
98
+        remove(e)
99
+    } else {
100
+        message.info(t('multiTab.cannotCloseLast'))
101
+    }
102
+}
103
+const closeLeft = (e) => {
104
+    const currentIndex = fullPathList.indexOf(e)
105
+    if (currentIndex > 0) {
106
+        fullPathList.forEach((item, index) => {
107
+            if (index < currentIndex) {
108
+                remove(item)
109
+            }
110
+        })
111
+    } else {
112
+        message.info(t('multiTab.noLeft'))
113
+    }
114
+}
115
+const closeRight = (e) => {
116
+    const currentIndex = fullPathList.indexOf(e)
117
+    if (currentIndex < fullPathList.length - 1) {
118
+        fullPathList.forEach((item, index) => {
119
+            if (index > currentIndex) {
120
+                remove(item)
121
+            }
122
+        })
123
+    } else {
124
+        message.info(t('multiTab.noRight'))
125
+    }
126
+}
127
+const closeAll = (e) => {
128
+    const currentIndex = fullPathList.indexOf(e)
129
+    fullPathList.forEach((item, index) => {
130
+        if (index !== currentIndex) {
131
+            remove(item)
132
+        }
133
+    })
134
+}
135
+const closeMenuClick = (key: string, route) => {
136
+    const allFun = { closeAll, closeRight, closeLeft, closeSelf }
137
+    allFun[key](route)
138
+}
139
+
140
+watch(
141
+    () => router.currentRoute.value,
142
+    (newVal) => {
143
+        activeKey.value = newVal.fullPath
144
+        if (fullPathList.indexOf(newVal.fullPath) < 0) {
145
+            fullPathList.push(newVal.fullPath)
146
+            pages.push(newVal)
147
+        }
148
+    }
149
+)
150
+
151
+watch(activeKey, (newPathKey) => {
152
+    router.push({ path: newPathKey })
153
+})
154
+</script>
155
+<style lang="less">
156
+.tab_style() {
157
+    .ant-tabs-card {
158
+        padding-left: 0;
159
+
160
+        .ant-tabs-nav-wrap {
161
+            margin: 5px
162
+        }
163
+
164
+        .ant-tabs-nav-container {
165
+
166
+            .ant-tabs-tab-prev:hover,
167
+            .ant-tabs-tab-next:hover {
168
+                // width: 22px;
169
+                background-color: rgba(0, 0, 0, 0.03);
170
+            }
171
+
172
+            height: 37px;
173
+        }
174
+
175
+        .ant-tabs-tab {
176
+            height: 32px;
177
+            margin-right: 5px;
178
+            line-height: 32px;
179
+            background: #ffffff;
180
+            border: 1px solid #dedede;
181
+        }
182
+
183
+        .ant-tabs-tab-active {
184
+            height: 32px;
185
+
186
+            .anticon-close {
187
+                display: inline-block;
188
+            }
189
+        }
190
+
191
+        .ant-tabs-tab:hover {
192
+            .anticon-close {
193
+                color: #333;
194
+                display: inline-block;
195
+            }
196
+        }
197
+    }
198
+}
199
+
200
+.ant-pro-multi-tab-wrapper {
201
+    .tab_style() !important;
202
+}
203
+</style>

+ 9
- 0
ant-design-pro-vue3/src/components/MultiTab/lang/cn.ts View File

@@ -0,0 +1,9 @@
1
+export default {
2
+  closeCurrent: '关闭当前标签',
3
+  closeRight: '关闭右侧',
4
+  closeLeft: '关闭左侧',
5
+  closeAll: '关闭全部',
6
+  cannotCloseLast:'这是最后一个标签了, 无法被关闭',
7
+  noLeft:'左侧没有标签',
8
+  noRight:'右侧没有标签'
9
+}

+ 9
- 0
ant-design-pro-vue3/src/components/MultiTab/lang/en.ts View File

@@ -0,0 +1,9 @@
1
+export default {
2
+  closeCurrent: 'Close current',
3
+  closeRight: 'Close right',
4
+  closeLeft: 'Close left',
5
+  closeAll: 'Close all',
6
+  cannotCloseLast: 'Can not close the last label',
7
+  noLeft: 'No left label',
8
+  noRight: 'No right label'
9
+}

+ 75
- 0
ant-design-pro-vue3/src/components/NProgress/nprogress.less View File

@@ -0,0 +1,75 @@
1
+@import url('../../style/index.less');
2
+
3
+/* Make clicks pass-through */
4
+#nprogress {
5
+  pointer-events: none;
6
+}
7
+
8
+#nprogress .bar {
9
+  background: @primary-color;
10
+
11
+  position: fixed;
12
+  z-index: 1031;
13
+  top: 0;
14
+  left: 0;
15
+
16
+  width: 100%;
17
+  height: 2px;
18
+}
19
+
20
+/* Fancy blur effect */
21
+#nprogress .peg {
22
+  display: block;
23
+  position: absolute;
24
+  right: 0px;
25
+  width: 100px;
26
+  height: 100%;
27
+  box-shadow: 0 0 10px @primary-color, 0 0 5px @primary-color;
28
+  opacity: 1.0;
29
+
30
+  -webkit-transform: rotate(3deg) translate(0px, -4px);
31
+  -ms-transform: rotate(3deg) translate(0px, -4px);
32
+  transform: rotate(3deg) translate(0px, -4px);
33
+}
34
+
35
+/* Remove these to get rid of the spinner */
36
+#nprogress .spinner {
37
+  display: block;
38
+  position: fixed;
39
+  z-index: 1031;
40
+  top: 15px;
41
+  right: 15px;
42
+}
43
+
44
+#nprogress .spinner-icon {
45
+  width: 18px;
46
+  height: 18px;
47
+  box-sizing: border-box;
48
+
49
+  border: solid 2px transparent;
50
+  border-top-color: @primary-color;
51
+  border-left-color: @primary-color;
52
+  border-radius: 50%;
53
+
54
+  -webkit-animation: nprogress-spinner 400ms linear infinite;
55
+  animation: nprogress-spinner 400ms linear infinite;
56
+}
57
+
58
+.nprogress-custom-parent {
59
+  overflow: hidden;
60
+  position: relative;
61
+}
62
+
63
+.nprogress-custom-parent #nprogress .spinner,
64
+.nprogress-custom-parent #nprogress .bar {
65
+  position: absolute;
66
+}
67
+
68
+@-webkit-keyframes nprogress-spinner {
69
+  0%   { -webkit-transform: rotate(0deg); }
70
+  100% { -webkit-transform: rotate(360deg); }
71
+}
72
+@keyframes nprogress-spinner {
73
+  0%   { transform: rotate(0deg); }
74
+  100% { transform: rotate(360deg); }
75
+}

+ 86
- 0
ant-design-pro-vue3/src/components/NoticeIcon/index.vue View File

@@ -0,0 +1,86 @@
1
+<template>
2
+  <!--placement="bottomRight"
3
+    :autoAdjustOverflow="false"
4
+  :arrowPointAtCenter="true"-->
5
+  <a-popover v-model:visible="visible" trigger="click" :placement="isMobile ? 'bottom' : 'bottomRight'"
6
+    overlayClassName="header-notice-wrapper" :getPopupContainer="getPopupContainer"
7
+    :overlayStyle="{ width: isMobile ? '250px' : '300px', top: '50px' }">
8
+    <template #content>
9
+      <a-spin :spinning="loading">
10
+        <a-tabs>
11
+          <a-tab-pane tab="通知" key="1">
12
+            <a-list>
13
+              <a-list-item>
14
+                <a-list-item-meta title="你收到了 14 份新周报" description="一年前">
15
+                  <a-avatar style="background-color: white" slot="avatar"
16
+                    src="https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png" />
17
+                </a-list-item-meta>
18
+              </a-list-item>
19
+              <a-list-item>
20
+                <a-list-item-meta title="你推荐的 曲妮妮 已通过第三轮面试" description="一年前">
21
+                  <a-avatar style="background-color: white" slot="avatar"
22
+                    src="https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png" />
23
+                </a-list-item-meta>
24
+              </a-list-item>
25
+              <a-list-item>
26
+                <a-list-item-meta title="这种模板可以区分多种通知类型" description="一年前">
27
+                  <a-avatar style="background-color: white" slot="avatar"
28
+                    src="https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png" />
29
+                </a-list-item-meta>
30
+              </a-list-item>
31
+            </a-list>
32
+          </a-tab-pane>
33
+          <a-tab-pane tab="消息" key="2">123</a-tab-pane>
34
+          <a-tab-pane tab="待办" key="3">123</a-tab-pane>
35
+        </a-tabs>
36
+      </a-spin>
37
+    </template>
38
+    <span @click="fetchNotice" class="header-notice" ref="noticeRef" style="padding: 0 18px">
39
+      <a-badge count="12">
40
+        <BellOutlined style="font-size: 16px; padding: 4px" />
41
+      </a-badge>
42
+    </span>
43
+  </a-popover>
44
+</template>
45
+
46
+<script lang="ts" setup name="HeaderNotice">
47
+import { ref } from 'vue'
48
+import { BellOutlined } from '@ant-design/icons-vue'
49
+import { isMobile } from '@/utils/device'
50
+
51
+const loading = ref<boolean>(false)
52
+const visible = ref<boolean>(false)
53
+const noticeRef = ref(null)
54
+
55
+const fetchNotice = () => {
56
+  if (!visible.value) {
57
+    loading.value = true
58
+    setTimeout(() => {
59
+      loading.value = false
60
+    }, 300)
61
+  } else {
62
+    loading.value = false
63
+  }
64
+  // visible.value = !visible.value;
65
+}
66
+
67
+const getPopupContainer = () => {
68
+  return noticeRef.value!.parentElement
69
+}
70
+</script>
71
+
72
+<style lang="css">
73
+.header-notice-wrapper {
74
+  top: 50px !important;
75
+}
76
+</style>
77
+<style lang="less" scoped>
78
+.header-notice {
79
+  display: inline-block;
80
+  transition: all 0.3s;
81
+
82
+  span {
83
+    // vertical-align: initial;
84
+  }
85
+}
86
+</style>

+ 48
- 0
ant-design-pro-vue3/src/components/OpenModelButton/index.vue View File

@@ -0,0 +1,48 @@
1
+<template>
2
+    <span>
3
+        <a-button type="primary" @click="click" v-bind="$attrs">
4
+            {{ text ?? '打开' }}
5
+        </a-button>
6
+        <component v-if="visible" :is="is" :visible="visible" @close:modal="visible = false" />
7
+    </span>
8
+</template>
9
+
10
+<script setup>
11
+import { computed } from 'vue';
12
+import { ref } from 'vue'
13
+import { useStore } from 'vuex';
14
+const store = useStore();
15
+
16
+const props = defineProps({
17
+    modal: {
18
+        type: [Object, Function],
19
+        required: true
20
+    },
21
+    text: String,
22
+    afterShow: [String, Function],
23
+    payload: Object
24
+})
25
+
26
+const is = computed(() => {
27
+    if (typeof props.modal === 'function') {
28
+        return props.modal()
29
+    } else {
30
+        return props.modal
31
+    }
32
+})
33
+
34
+const visible = ref(false)
35
+function click () {
36
+    visible.value = true;
37
+    const afterShow = props.afterShow
38
+    if (afterShow) {
39
+        if (typeof afterShow === 'function') {
40
+            afterShow(props.payload)
41
+        } else if (typeof afterShow === 'string') {
42
+            store.dispatch(afterShow, props.payload)
43
+        }
44
+    }
45
+}
46
+</script>
47
+
48
+<style lang="scss" scoped></style>

+ 199
- 0
ant-design-pro-vue3/src/components/PageHeader/index.vue View File

@@ -0,0 +1,199 @@
1
+<template>
2
+  <div class="page-header">
3
+    <div class="page-header-index-wide">
4
+      <Breadcrumb />
5
+      <div class="detail">
6
+        <div class="main" v-if="!$route.meta.hiddenHeaderContent">
7
+          <div class="row">
8
+            <img v-if="logo" :src="logo" class="logo"/>
9
+            <h1 v-if="title" class="title">{{ title }}</h1>
10
+            <div class="action">
11
+              <slot name="action"></slot>
12
+            </div>
13
+          </div>
14
+          <div class="row">
15
+            <div v-if="avatar" class="avatar">
16
+              <a-avatar :src="avatar" />
17
+            </div>
18
+            <div v-if="this.$slots.content" class="headerContent">
19
+              <slot name="content"></slot>
20
+            </div>
21
+            <div v-if="this.$slots.extra" class="extra">
22
+              <slot name="extra"></slot>
23
+            </div>
24
+          </div>
25
+          <div>
26
+            <slot name="pageMenu"></slot>
27
+          </div>
28
+        </div>
29
+      </div>
30
+    </div>
31
+  </div>
32
+</template>
33
+
34
+<script lang="ts">
35
+import Breadcrumb from '@/components/tools/Breadcrumb.vue'
36
+
37
+export default {
38
+  name: 'PageHeader',
39
+  components: {
40
+    Breadcrumb
41
+  },
42
+  props: {
43
+    title: {
44
+      type: [String, Boolean],
45
+      default: true,
46
+      required: false
47
+    },
48
+    logo: {
49
+      type: String,
50
+      default: '',
51
+      required: false
52
+    },
53
+    avatar: {
54
+      type: String,
55
+      default: '',
56
+      required: false
57
+    }
58
+  }
59
+}
60
+</script>
61
+
62
+<style lang="less" scoped>
63
+.page-header {
64
+  background: #fff;
65
+  padding: 16px 32px 0;
66
+  border-bottom: 1px solid #e8e8e8;
67
+
68
+  .breadcrumb {
69
+    margin-bottom: 16px;
70
+  }
71
+
72
+  .detail {
73
+    display: flex;
74
+    /*margin-bottom: 16px;*/
75
+
76
+    .avatar {
77
+      flex: 0 1 72px;
78
+      margin: 0 24px 8px 0;
79
+
80
+      & > span {
81
+        border-radius: 72px;
82
+        display: block;
83
+        width: 72px;
84
+        height: 72px;
85
+      }
86
+    }
87
+
88
+    .main {
89
+      width: 100%;
90
+      flex: 0 1 auto;
91
+
92
+      .row {
93
+        display: flex;
94
+        width: 100%;
95
+
96
+        .avatar {
97
+          margin-bottom: 16px;
98
+        }
99
+      }
100
+
101
+      .title {
102
+        font-size: 20px;
103
+        font-weight: 500;
104
+
105
+        font-size: 20px;
106
+        line-height: 28px;
107
+        font-weight: 500;
108
+        color: rgba(0, 0, 0, 0.85);
109
+        margin-bottom: 16px;
110
+        flex: auto;
111
+      }
112
+      .logo {
113
+        width: 28px;
114
+        height: 28px;
115
+        border-radius: 4px;
116
+        margin-right: 16px;
117
+      }
118
+      .content,
119
+      .headerContent {
120
+        flex: auto;
121
+        color: rgba(0, 0, 0, 0.45);
122
+        line-height: 22px;
123
+
124
+        .link {
125
+          margin-top: 16px;
126
+          line-height: 24px;
127
+
128
+          a {
129
+            font-size: 14px;
130
+            margin-right: 32px;
131
+          }
132
+        }
133
+      }
134
+      .extra {
135
+        flex: 0 1 auto;
136
+        margin-left: 88px;
137
+        min-width: 242px;
138
+        text-align: right;
139
+      }
140
+      .action {
141
+        margin-left: 56px;
142
+        min-width: 266px;
143
+        flex: 0 1 auto;
144
+        text-align: right;
145
+        &:empty {
146
+          display: none;
147
+        }
148
+      }
149
+    }
150
+  }
151
+}
152
+
153
+.mobile .page-header {
154
+  .main {
155
+    .row {
156
+      flex-wrap: wrap;
157
+
158
+      .avatar {
159
+        flex: 0 1 25%;
160
+        margin: 0 2% 8px 0;
161
+      }
162
+
163
+      .content,
164
+      .headerContent {
165
+        flex: 0 1 70%;
166
+
167
+        .link {
168
+          margin-top: 16px;
169
+          line-height: 24px;
170
+
171
+          a {
172
+            font-size: 14px;
173
+            margin-right: 10px;
174
+          }
175
+        }
176
+      }
177
+
178
+      .extra {
179
+        flex: 1 1 auto;
180
+        margin-left: 0;
181
+        min-width: 0;
182
+        text-align: right;
183
+      }
184
+
185
+      .action {
186
+        margin-left: unset;
187
+        min-width: 266px;
188
+        flex: 0 1 auto;
189
+        text-align: left;
190
+        margin-bottom: 12px;
191
+
192
+        &:empty {
193
+          display: none;
194
+        }
195
+      }
196
+    }
197
+  }
198
+}
199
+</style>

+ 0
- 0
ant-design-pro-vue3/src/components/PageInit/PageInit.vue View File


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

Loading…
Cancel
Save